Projects
Mega:23.03
systemd
_service:tar_scm:backport-portabled-validate-SY...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:backport-portabled-validate-SYSEXT_LEVEL-when-attaching.patch of Package systemd
From 5453257f8caebbcfe880601de27853f2d51acbb7 Mon Sep 17 00:00:00 2001 From: Luca Boccassi <luca.boccassi@microsoft.com> Date: Wed, 4 Aug 2021 15:00:06 +0100 Subject: [PATCH] portabled: validate SYSEXT_LEVEL when attaching When attaching a portable service with extensions, immediately validate that the os-release and extension-release metadata values match, rather than letting it fail when the units are started (cherry picked from commit 239ac0c7f72c30cab2e84d395d064c3b7384ff84) Conflict:NA Reference:https://github.com/systemd/systemd/commit/5453257f8caebbcfe880601de27853f2d51acbb7 --- src/portable/portable.c | 88 ++++++++++++++++++++++++++++++++--------- src/portable/portable.h | 1 + 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/src/portable/portable.c b/src/portable/portable.c index 8550becded..765aedf852 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -11,8 +11,10 @@ #include "dirent-util.h" #include "discover-image.h" #include "dissect-image.h" +#include "env-file.h" #include "errno-list.h" #include "escape.h" +#include "extension-release.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" @@ -232,6 +234,8 @@ DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(portable_metadata_hash_ops, char, static int extract_now( const char *where, char **matches, + const char *image_name, + bool path_is_extension, int socket_fd, PortableMetadata **ret_os_release, Hashmap **ret_unit_files) { @@ -241,6 +245,7 @@ static int extract_now( _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_close_ int os_release_fd = -1; _cleanup_free_ char *os_release_path = NULL; + const char *os_release_id; char **i; int r; @@ -255,19 +260,27 @@ static int extract_now( assert(where); - /* First, find /etc/os-release and send it upstream (or just save it). */ - r = open_os_release(where, &os_release_path, &os_release_fd); + /* First, find os-release/extension-release and send it upstream (or just save it). */ + if (path_is_extension) { + os_release_id = strjoina("/usr/lib/extension-release.d/extension-release.", image_name); + r = open_extension_release(where, image_name, &os_release_path, &os_release_fd); + } else { + os_release_id = "/etc/os-release"; + r = open_os_release(where, &os_release_path, &os_release_fd); + } if (r < 0) - log_debug_errno(r, "Couldn't acquire os-release file, ignoring: %m"); + log_debug_errno(r, + "Couldn't acquire %s file, ignoring: %m", + path_is_extension ? "extension-release " : "os-release"); else { if (socket_fd >= 0) { - r = send_item(socket_fd, "/etc/os-release", os_release_fd); + r = send_item(socket_fd, os_release_id, os_release_fd); if (r < 0) return log_debug_errno(r, "Failed to send os-release file: %m"); } if (ret_os_release) { - os_release = portable_metadata_new("/etc/os-release", NULL, os_release_fd); + os_release = portable_metadata_new(os_release_id, NULL, os_release_fd); if (!os_release) return -ENOMEM; @@ -353,7 +366,7 @@ static int extract_now( static int portable_extract_by_path( const char *path, - bool extract_os_release, + bool path_is_extension, char **matches, PortableMetadata **ret_os_release, Hashmap **ret_unit_files, @@ -371,7 +384,7 @@ static int portable_extract_by_path( /* We can't turn this into a loop-back block device, and this returns EISDIR? Then this is a directory * tree and not a raw device. It's easy then. */ - r = extract_now(path, matches, -1, &os_release, &unit_files); + r = extract_now(path, matches, NULL, path_is_extension, -1, &os_release, &unit_files); if (r < 0) return r; @@ -428,7 +441,7 @@ static int portable_extract_by_path( seq[0] = safe_close(seq[0]); - if (!extract_os_release) + if (path_is_extension) flags |= DISSECT_IMAGE_VALIDATE_OS_EXT; else flags |= DISSECT_IMAGE_VALIDATE_OS; @@ -439,7 +452,7 @@ static int portable_extract_by_path( goto child_finish; } - r = extract_now(tmpdir, matches, seq[1], NULL, NULL); + r = extract_now(tmpdir, matches, m->image_name, path_is_extension, seq[1], NULL, NULL); child_finish: _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); @@ -485,7 +498,7 @@ static int portable_extract_by_path( add = NULL; - } else if (PORTABLE_METADATA_IS_OS_RELEASE(add)) { + } else if (PORTABLE_METADATA_IS_OS_RELEASE(add) || PORTABLE_METADATA_IS_EXTENSION_RELEASE(add)) { assert(!os_release); os_release = TAKE_PTR(add); @@ -499,10 +512,12 @@ static int portable_extract_by_path( child = 0; } - /* When the portable image is layered, the image with units will not - * have a full filesystem, so no os-release - it will be in the root layer */ - if (extract_os_release && !os_release) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image '%s' lacks os-release data, refusing.", path); + if (!os_release) + return sd_bus_error_setf(error, + SD_BUS_ERROR_INVALID_ARGS, + "Image '%s' lacks %s data, refusing.", + path, + path_is_extension ? "extension-release" : "os-release"); if (ret_unit_files) *ret_unit_files = TAKE_PTR(unit_files); @@ -555,14 +570,14 @@ int portable_extract( } } - r = portable_extract_by_path(image->path, true, matches, &os_release, &unit_files, error); + r = portable_extract_by_path(image->path, /* path_is_extension= */ false, matches, &os_release, &unit_files, error); if (r < 0) return r; ORDERED_HASHMAP_FOREACH(ext, extension_images) { _cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL; - r = portable_extract_by_path(ext->path, false, matches, NULL, &extra_unit_files, error); + r = portable_extract_by_path(ext->path, /* path_is_extension= */ true, matches, NULL, &extra_unit_files, error); if (r < 0) return r; r = hashmap_move(unit_files, extra_unit_files); @@ -1151,6 +1166,8 @@ int portable_attach( size_t *n_changes, sd_bus_error *error) { + _cleanup_free_ char *id = NULL, *version_id = NULL, *sysext_level = NULL; + _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL; _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL; _cleanup_hashmap_free_ Hashmap *unit_files = NULL; _cleanup_(lookup_paths_free) LookupPaths paths = {}; @@ -1184,16 +1201,51 @@ int portable_attach( } } - r = portable_extract_by_path(image->path, true, matches, NULL, &unit_files, error); + r = portable_extract_by_path(image->path, /* path_is_extension= */ false, matches, &os_release, &unit_files, error); if (r < 0) return r; + /* If we are layering extension images on top of a runtime image, check that the os-release and extension-release metadata + * match, otherwise reject it immediately as invalid, or it will fail when the units are started. */ + if (os_release) { + _cleanup_fclose_ FILE *f = NULL; + + r = take_fdopen_unlocked(&os_release->fd, "r", &f); + if (r < 0) + return r; + + r = parse_env_file(f, os_release->name, + "ID", &id, + "VERSION_ID", &version_id, + "SYSEXT_LEVEL", &sysext_level); + if (r < 0) + return r; + } + ORDERED_HASHMAP_FOREACH(ext, extension_images) { + _cleanup_(portable_metadata_unrefp) PortableMetadata *extension_release_meta = NULL; _cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL; + _cleanup_strv_free_ char **extension_release = NULL; + _cleanup_fclose_ FILE *f = NULL; + + r = portable_extract_by_path(ext->path, /* path_is_extension= */ true, matches, &extension_release_meta, &extra_unit_files, error); + if (r < 0) + return r; - r = portable_extract_by_path(ext->path, false, matches, NULL, &extra_unit_files, error); + r = take_fdopen_unlocked(&extension_release_meta->fd, "r", &f); if (r < 0) return r; + + r = load_env_file_pairs(f, extension_release_meta->name, &extension_release); + if (r < 0) + return r; + + r = extension_release_validate(ext->path, id, version_id, sysext_level, extension_release); + if (r == 0) + return sd_bus_error_set_errnof(error, SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", ext->path); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to compare image %s extension-release metadata with the root's os-release: %m", ext->path); + r = hashmap_move(unit_files, extra_unit_files); if (r < 0) return r; diff --git a/src/portable/portable.h b/src/portable/portable.h index dd080edf4e..94144287ae 100644 --- a/src/portable/portable.h +++ b/src/portable/portable.h @@ -16,6 +16,7 @@ typedef struct PortableMetadata { } PortableMetadata; #define PORTABLE_METADATA_IS_OS_RELEASE(m) (streq((m)->name, "/etc/os-release")) +#define PORTABLE_METADATA_IS_EXTENSION_RELEASE(m) (startswith((m)->name, "/usr/lib/extension-release.d/extension-release.")) #define PORTABLE_METADATA_IS_UNIT(m) (!IN_SET((m)->name[0], 0, '/')) typedef enum PortableFlags { -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2