From: Lennart Poettering Date: Wed, 12 Apr 2023 11:46:08 +0000 (+0200) Subject: Merge pull request #25608 from poettering/dissect-moar X-Git-Tag: v254-rc1~748 X-Git-Url: http://git-history.diyao.me/?a=commitdiff_plain;h=3af48a86d99b3117a44bc22258ab4d34d0ba7655;p=systemd%2F.git Merge pull request #25608 from poettering/dissect-moar dissect: add dissection policies --- 3af48a86d99b3117a44bc22258ab4d34d0ba7655 diff --cc man/systemd-sysext.xml index f3a12e0a1c,2b7a87f510..a257fa73bc --- a/man/systemd-sysext.xml +++ b/man/systemd-sysext.xml @@@ -265,11 -230,24 +270,24 @@@ When merging system extensions into /usr/ and - /opt/, ignore version incompatibilities, i.e. force merging regardless of - whether the version information included in the extension images matches the host or - not. + /opt/ for sysext and /etc/ for confext, + ignore version incompatibilities, i.e. force merging regardless of + whether the version information included in the images matches the host or not. + + + + Takes an image policy string as argument, as per + systemd.image-policy7. The + policy is enforced when operating on system extension disk images. If not specified defaults to + root=verity+signed+encrypted+unprotected+absent:usr=verity+signed+encrypted+unprotected+absent, + i.e. only the root and /usr/ file systems in the image are used. When run in the + initrd and operating on a system extension image stored in the /.extra/sysext/ + directory a slightly stricter policy is used by default: + root=signed+absent:usr=signed+absent, see above for details. + + diff --cc src/core/execute.c index 93024b1ce4,cd11683407..8b09794089 --- a/src/core/execute.c +++ b/src/core/execute.c @@@ -3785,50 -3801,65 +3785,57 @@@ static int apply_mount_namespace if (MANAGER_IS_SYSTEM(u->manager)) { propagate_dir = path_join("/run/systemd/propagate/", u->id); - if (!propagate_dir) { - r = -ENOMEM; - goto finalize; - } + if (!propagate_dir) + return -ENOMEM; incoming_dir = strdup("/run/systemd/incoming"); - if (!incoming_dir) { - r = -ENOMEM; - goto finalize; - } + if (!incoming_dir) + return -ENOMEM; extension_dir = strdup("/run/systemd/unit-extensions"); - if (!extension_dir) { - r = -ENOMEM; - goto finalize; - } + if (!extension_dir) + return -ENOMEM; } else - if (asprintf(&extension_dir, "/run/user/" UID_FMT "/systemd/unit-extensions", geteuid()) < 0) { - r = -ENOMEM; - goto finalize; - } + if (asprintf(&extension_dir, "/run/user/" UID_FMT "/systemd/unit-extensions", geteuid()) < 0) + return -ENOMEM; - r = setup_namespace(root_dir, root_image, context->root_image_options, - &ns_info, read_write_paths, - needs_sandboxing ? context->read_only_paths : NULL, - needs_sandboxing ? context->inaccessible_paths : NULL, - needs_sandboxing ? context->exec_paths : NULL, - needs_sandboxing ? context->no_exec_paths : NULL, - empty_directories, - symlinks, - bind_mounts, - n_bind_mounts, - context->temporary_filesystems, - context->n_temporary_filesystems, - context->mount_images, - context->n_mount_images, - tmp_dir, - var_tmp_dir, - creds_path, - context->log_namespace, - context->mount_propagation_flag, - context->root_hash, context->root_hash_size, context->root_hash_path, - context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path, - context->root_verity, - context->extension_images, - context->n_extension_images, - context->extension_directories, - propagate_dir, - incoming_dir, - extension_dir, - root_dir || root_image ? params->notify_socket : NULL, - error_path); + r = setup_namespace( + root_dir, + root_image, + context->root_image_options, + context->root_image_policy ?: &image_policy_service, + &ns_info, + read_write_paths, + needs_sandboxing ? context->read_only_paths : NULL, + needs_sandboxing ? context->inaccessible_paths : NULL, + needs_sandboxing ? context->exec_paths : NULL, + needs_sandboxing ? context->no_exec_paths : NULL, + empty_directories, + symlinks, + bind_mounts, + n_bind_mounts, + context->temporary_filesystems, + context->n_temporary_filesystems, + context->mount_images, + context->n_mount_images, + context->mount_image_policy ?: &image_policy_service, + tmp_dir, + var_tmp_dir, + creds_path, + context->log_namespace, + context->mount_propagation_flag, + context->root_hash, context->root_hash_size, context->root_hash_path, + context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path, + context->root_verity, + context->extension_images, + context->n_extension_images, + context->extension_image_policy ?: &image_policy_sysext, + context->extension_directories, + propagate_dir, + incoming_dir, + extension_dir, + root_dir || root_image ? params->notify_socket : NULL, + error_path); /* If we couldn't set up the namespace this is probably due to a missing capability. setup_namespace() reports * that with a special, recognizable error ENOANO. In this case, silently proceed, but only if exclusively diff --cc src/shared/discover-image.c index d0b3245a27,df3d5b7765..ac6a8033dd --- a/src/shared/discover-image.c +++ b/src/shared/discover-image.c @@@ -63,16 -64,24 +64,29 @@@ static const char* const image_search_p * because extension images are supposed to extend /usr/, so you get into recursive races, especially * with directory-based extensions, as the kernel's OverlayFS explicitly checks for this and errors * out with -ELOOP if it finds that a lowerdir= is a child of another lowerdir=. */ - [IMAGE_EXTENSION] = "/etc/extensions\0" /* only place symlinks here */ - "/run/extensions\0" /* and here too */ - "/var/lib/extensions\0", /* the main place for images */ + [IMAGE_SYSEXT] = "/etc/extensions\0" /* only place symlinks here */ + "/run/extensions\0" /* and here too */ + "/var/lib/extensions\0", /* the main place for images */ + + [IMAGE_CONFEXT] = "/run/confexts\0" /* only place symlinks here */ + "/var/lib/confexts\0" /* the main place for images */ + "/usr/local/lib/confexts\0" + "/usr/lib/confexts\0", }; + /* Inside the initrd, use a slightly different set of search path (i.e. include .extra/sysext in extension + * search dir) */ + static const char* const image_search_path_initrd[_IMAGE_CLASS_MAX] = { + /* (entries that aren't listed here will get the same search path as for the non initrd-case) */ + + [IMAGE_EXTENSION] = "/etc/extensions\0" /* only place symlinks here */ + "/run/extensions\0" /* and here too */ + "/var/lib/extensions\0" /* the main place for images */ + "/usr/local/lib/extensions\0" + "/usr/lib/extensions\0" + "/.extra/sysext\0" /* put sysext picked up by systemd-stub last, since not trusted */ + }; + static Image *image_free(Image *i) { assert(i); diff --cc src/shared/discover-image.h index 342b161577,c423132a62..edfb1412a4 --- a/src/shared/discover-image.h +++ b/src/shared/discover-image.h @@@ -7,9 -7,9 +7,10 @@@ #include "sd-id128.h" #include "hashmap.h" + #include "image-policy.h" #include "lock-util.h" #include "macro.h" +#include "os-util.h" #include "path-util.h" #include "string-util.h" #include "time-util.h" diff --cc src/sysext/sysext.c index d235073743,f784627e82..3fc6b910c4 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@@ -45,43 -45,12 +45,45 @@@ static JsonFormatFlags arg_json_format_ static PagerFlags arg_pager_flags = 0; static bool arg_legend = true; static bool arg_force = false; + static ImagePolicy *arg_image_policy = NULL; +/* Is set to IMAGE_CONFEXT when systemd is called with the confext functionality instead of the default */ +static ImageClass arg_image_class = IMAGE_SYSEXT; + STATIC_DESTRUCTOR_REGISTER(arg_hierarchies, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_root, freep); + STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); +/* Helper struct for naming simplicity and reusability */ +static const struct { + const char *dot_directory_name; + const char *directory_name; + const char *short_identifier; + const char *short_identifier_plural; + const char *level_env; + const char *scope_env; + const char *name_env; +} image_class_info[_IMAGE_CLASS_MAX] = { + [IMAGE_SYSEXT] = { + .dot_directory_name = ".systemd-sysext", + .directory_name = "systemd-sysext", + .short_identifier = "sysext", + .short_identifier_plural = "extensions", + .level_env = "SYSEXT_LEVEL", + .scope_env = "SYSEXT_SCOPE", + .name_env = "SYSTEMD_SYSEXT_HIERARCHIES", + }, + [IMAGE_CONFEXT] = { + .dot_directory_name = ".systemd-confext", + .directory_name = "systemd-confext", + .short_identifier = "confext", + .short_identifier_plural = "confexts", + .level_env = "CONFEXT_LEVEL", + .scope_env = "CONFEXT_SCOPE", + .name_env = "SYSTEMD_CONFEXT_HIERARCHIES", + } +}; + static int is_our_mount_point(const char *p) { _cleanup_free_ char *buf = NULL, *f = NULL; struct stat st; @@@ -441,9 -410,27 +443,27 @@@ static int strverscmp_improvedp(char *c return strverscmp_improved(*a, *b); } + static const ImagePolicy *pick_image_policy(const Image *img) { + assert(img); + assert(img->path); + + /* Explicitly specified policy always wins */ + if (arg_image_policy) + return arg_image_policy; + + /* If located in /.extra/sysext/ in the initrd, then it was placed there by systemd-stub, and was + * picked up from an untrusted ESP. Thus, require a stricter policy by default for them. (For the + * other directories we assume the appropriate level of trust was already established already. */ + + if (in_initrd() && path_startswith(img->path, "/.extra/sysext/")) + return &image_policy_sysext_strict; + + return &image_policy_sysext; + } + static int merge_subprocess(Hashmap *images, const char *workspace) { _cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL, *host_os_release_sysext_level = NULL, - *buf = NULL; + *host_os_release_confext_level = NULL, *buf = NULL; _cleanup_strv_free_ char **extensions = NULL, **paths = NULL; size_t n_extensions = 0; unsigned n_ignored = 0; @@@ -765,12 -750,12 +786,12 @@@ static int image_discover_and_read_meta if (!images) return log_oom(); - r = image_discover(IMAGE_EXTENSION, arg_root, images); + r = image_discover(arg_image_class, arg_root, images); if (r < 0) - return log_error_errno(r, "Failed to discover extension images: %m"); + return log_error_errno(r, "Failed to discover images: %m"); HASHMAP_FOREACH(img, images) { - r = image_read_metadata(img); + r = image_read_metadata(img, &image_policy_sysext); if (r < 0) return log_error_errno(r, "Failed to read metadata for image %s: %m", img->name); }