From 06768b90a32ac0d36252ebc5f426ad471bf29fce Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Tue, 11 Oct 2022 18:58:33 +0100 Subject: portable: allow caller to override extension-release name check When the --force flag is used, do not insist that the extension-release file has to match the extension image name --- src/portable/portable.c | 32 ++++++++++++++++++++++++-------- src/portable/portable.h | 11 ++++++----- src/portable/portablectl.c | 6 +++--- src/portable/portabled-image-bus.c | 3 +++ 4 files changed, 36 insertions(+), 16 deletions(-) (limited to 'src/portable') diff --git a/src/portable/portable.c b/src/portable/portable.c index 79bda5cf0b..be906f786c 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -171,6 +171,7 @@ static int extract_now( char **matches, const char *image_name, bool path_is_extension, + bool relax_extension_release_check, int socket_fd, PortableMetadata **ret_os_release, Hashmap **ret_unit_files) { @@ -197,7 +198,7 @@ static int extract_now( /* 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); + r = open_extension_release(where, image_name, relax_extension_release_check, &os_release_path, &os_release_fd); } else { os_release_id = "/etc/os-release"; r = open_os_release(where, &os_release_path, &os_release_fd); @@ -321,6 +322,7 @@ static int extract_now( static int portable_extract_by_path( const char *path, bool path_is_extension, + bool relax_extension_release_check, char **matches, PortableMetadata **ret_os_release, Hashmap **ret_unit_files, @@ -344,7 +346,7 @@ static int portable_extract_by_path( if (r < 0) return log_error_errno(r, "Failed to extract image name from path '%s': %m", path); - r = extract_now(path, matches, image_name, path_is_extension, -1, &os_release, &unit_files); + r = extract_now(path, matches, image_name, path_is_extension, /* relax_extension_release_check= */ false, -1, &os_release, &unit_files); if (r < 0) return r; @@ -400,7 +402,7 @@ static int portable_extract_by_path( seq[0] = safe_close(seq[0]); if (path_is_extension) - flags |= DISSECT_IMAGE_VALIDATE_OS_EXT; + flags |= DISSECT_IMAGE_VALIDATE_OS_EXT | (relax_extension_release_check ? DISSECT_IMAGE_RELAX_SYSEXT_CHECK : 0); else flags |= DISSECT_IMAGE_VALIDATE_OS; @@ -410,7 +412,7 @@ static int portable_extract_by_path( goto child_finish; } - r = extract_now(tmpdir, matches, m->image_name, path_is_extension, seq[1], NULL, NULL); + r = extract_now(tmpdir, matches, m->image_name, path_is_extension, relax_extension_release_check, seq[1], NULL, NULL); child_finish: _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); @@ -505,6 +507,7 @@ static int extract_image_and_extensions( char **matches, char **extension_image_paths, bool validate_sysext, + bool relax_extension_release_check, Image **ret_image, OrderedHashmap **ret_extension_images, OrderedHashmap **ret_extension_releases, @@ -553,7 +556,7 @@ static int extract_image_and_extensions( } } - r = portable_extract_by_path(image->path, /* path_is_extension= */ false, matches, &os_release, &unit_files, error); + r = portable_extract_by_path(image->path, /* path_is_extension= */ false, /* relax_extension_release_check= */ false, matches, &os_release, &unit_files, error); if (r < 0) return r; @@ -593,7 +596,7 @@ static int extract_image_and_extensions( _cleanup_fclose_ FILE *f = NULL; const char *e; - r = portable_extract_by_path(ext->path, /* path_is_extension= */ true, matches, &extension_release_meta, &extra_unit_files, error); + r = portable_extract_by_path(ext->path, /* path_is_extension= */ true, relax_extension_release_check, matches, &extension_release_meta, &extra_unit_files, error); if (r < 0) return r; @@ -668,6 +671,7 @@ int portable_extract( const char *name_or_path, char **matches, char **extension_image_paths, + PortableFlags flags, PortableMetadata **ret_os_release, OrderedHashmap **ret_extension_releases, Hashmap **ret_unit_files, @@ -688,6 +692,7 @@ int portable_extract( matches, extension_image_paths, /* validate_sysext= */ false, + /* relax_extension_release_check= */ FLAGS_SET(flags, PORTABLE_FORCE_SYSEXT), &image, &extension_images, &extension_releases, @@ -955,6 +960,7 @@ static int install_chroot_dropin( OrderedHashmap *extension_images, const PortableMetadata *m, const char *dropin_dir, + PortableFlags flags, char **ret_dropin, PortableChange **changes, size_t *n_changes) { @@ -1004,7 +1010,16 @@ static int install_chroot_dropin( if (m->image_path && !path_equal(m->image_path, image_path)) ORDERED_HASHMAP_FOREACH(ext, extension_images) - if (!strextend(&text, extension_setting_from_image(ext->type), ext->path, "\n")) + if (!strextend(&text, + extension_setting_from_image(ext->type), + ext->path, + /* With --force tell PID1 to avoid enforcing that the image and + * extension-release. have to match. */ + !IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) && + FLAGS_SET(flags, PORTABLE_FORCE_SYSEXT) ? + ":x-systemd.relax-extension-release-check" : + "", + "\n")) return -ENOMEM; } @@ -1138,7 +1153,7 @@ static int attach_unit_file( * is reloaded while we are creating things here: as long as only the drop-ins exist the unit doesn't exist at * all for PID 1. */ - r = install_chroot_dropin(image_path, type, extension_images, m, dropin_dir, &chroot_dropin, changes, n_changes); + r = install_chroot_dropin(image_path, type, extension_images, m, dropin_dir, flags, &chroot_dropin, changes, n_changes); if (r < 0) return r; @@ -1303,6 +1318,7 @@ int portable_attach( matches, extension_image_paths, /* validate_sysext= */ true, + /* relax_extension_release_check= */ FLAGS_SET(flags, PORTABLE_FORCE_SYSEXT), &image, &extension_images, /* extension_releases= */ NULL, diff --git a/src/portable/portable.h b/src/portable/portable.h index 30895b18f9..1a33f30944 100644 --- a/src/portable/portable.h +++ b/src/portable/portable.h @@ -23,10 +23,11 @@ typedef struct PortableMetadata { typedef enum PortableFlags { PORTABLE_RUNTIME = 1 << 0, /* Public API via DBUS, do not change */ PORTABLE_FORCE_ATTACH = 1 << 1, /* Public API via DBUS, do not change */ - PORTABLE_PREFER_COPY = 1 << 2, - PORTABLE_PREFER_SYMLINK = 1 << 3, - PORTABLE_REATTACH = 1 << 4, - _PORTABLE_MASK_PUBLIC = PORTABLE_RUNTIME | PORTABLE_FORCE_ATTACH, + PORTABLE_FORCE_SYSEXT = 1 << 2, /* Public API via DBUS, do not change */ + PORTABLE_PREFER_COPY = 1 << 3, + PORTABLE_PREFER_SYMLINK = 1 << 4, + PORTABLE_REATTACH = 1 << 5, + _PORTABLE_MASK_PUBLIC = PORTABLE_RUNTIME | PORTABLE_FORCE_ATTACH | PORTABLE_FORCE_SYSEXT, _PORTABLE_TYPE_MAX, _PORTABLE_TYPE_INVALID = -EINVAL, } PortableFlags; @@ -66,7 +67,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(PortableMetadata*, portable_metadata_unref); int portable_metadata_hashmap_to_sorted_array(Hashmap *unit_files, PortableMetadata ***ret); -int portable_extract(const char *image, char **matches, char **extension_image_paths, PortableMetadata **ret_os_release, OrderedHashmap **ret_extension_releases, Hashmap **ret_unit_files, char ***ret_valid_prefixes, sd_bus_error *error); +int portable_extract(const char *image, char **matches, char **extension_image_paths, PortableFlags flags, PortableMetadata **ret_os_release, OrderedHashmap **ret_extension_releases, Hashmap **ret_unit_files, char ***ret_valid_prefixes, sd_bus_error *error); int portable_attach(sd_bus *bus, const char *name_or_path, char **matches, const char *profile, char **extension_images, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error); int portable_detach(sd_bus *bus, const char *name_or_path, char **extension_image_paths, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error); diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c index 94a3970f87..6ee9ee8f43 100644 --- a/src/portable/portablectl.c +++ b/src/portable/portablectl.c @@ -260,7 +260,7 @@ static int maybe_reload(sd_bus **bus) { static int get_image_metadata(sd_bus *bus, const char *image, char **matches, sd_bus_message **reply) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - uint64_t flags = 0; + uint64_t flags = arg_force ? PORTABLE_FORCE_SYSEXT : 0; const char *method; int r; @@ -869,7 +869,7 @@ static int attach_reattach_image(int argc, char *argv[], const char *method) { return bus_log_create_error(r); if (STR_IN_SET(method, "AttachImageWithExtensions", "ReattachImageWithExtensions")) { - uint64_t flags = (arg_runtime ? PORTABLE_RUNTIME : 0) | (arg_force ? PORTABLE_FORCE_ATTACH : 0); + uint64_t flags = (arg_runtime ? PORTABLE_RUNTIME : 0) | (arg_force ? PORTABLE_FORCE_ATTACH | PORTABLE_FORCE_SYSEXT : 0); r = sd_bus_message_append(m, "st", arg_copy_mode, flags); } else @@ -941,7 +941,7 @@ static int detach_image(int argc, char *argv[], void *userdata) { if (strv_isempty(arg_extension_images)) r = sd_bus_message_append(m, "b", arg_runtime); else { - uint64_t flags = (arg_runtime ? PORTABLE_RUNTIME : 0) | (arg_force ? PORTABLE_FORCE_ATTACH : 0); + uint64_t flags = (arg_runtime ? PORTABLE_RUNTIME : 0) | (arg_force ? PORTABLE_FORCE_ATTACH | PORTABLE_FORCE_SYSEXT : 0); r = sd_bus_message_append(m, "t", flags); } diff --git a/src/portable/portabled-image-bus.c b/src/portable/portabled-image-bus.c index 7d393476a0..b108fd34af 100644 --- a/src/portable/portabled-image-bus.c +++ b/src/portable/portabled-image-bus.c @@ -108,6 +108,7 @@ int bus_image_common_get_metadata( _cleanup_hashmap_free_ Hashmap *unit_files = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ PortableMetadata **sorted = NULL; + PortableFlags flags = 0; int r; assert(name_or_path || image); @@ -142,6 +143,7 @@ int bus_image_common_get_metadata( return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Invalid 'flags' parameter '%" PRIu64 "'", input_flags); + flags |= input_flags; } r = bus_image_acquire(m, @@ -161,6 +163,7 @@ int bus_image_common_get_metadata( image->path, matches, extension_images, + flags, &os_release, &extension_releases, &unit_files, -- cgit v1.2.1