From 0da675fddde6e82675ff44901b8d688d640f7b03 Mon Sep 17 00:00:00 2001 From: Maanya Goenka Date: Tue, 8 Aug 2023 21:37:36 +0000 Subject: [PATCH 1/3] add an @ option for confext --- src/analyze/analyze-image-policy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyze/analyze-image-policy.c b/src/analyze/analyze-image-policy.c index 026216629c..0146b50c78 100644 --- a/src/analyze/analyze-image-policy.c +++ b/src/analyze/analyze-image-policy.c @@ -92,6 +92,8 @@ int verb_image_policy(int argc, char *argv[], void *userdata) { p = &image_policy_sysext; else if (streq(argv[i], "@sysext-strict")) p = &image_policy_sysext_strict; + else if (streq(argv[i], "@confext")) + p = &image_policy_confext; else if (streq(argv[i], "@container")) p = &image_policy_container; else if (streq(argv[i], "@service")) From 55ea4ef096543d2bceea9315868d5aca945d7a57 Mon Sep 17 00:00:00 2001 From: Maanya Goenka Date: Tue, 8 Aug 2023 21:57:53 +0000 Subject: [PATCH 2/3] allow ExtensionImages= and ExtensionDirectories= settings to support confext images --- src/core/namespace.c | 65 ++++++++++++++++++++++++++++++------- src/shared/extension-util.c | 3 ++ 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index 5d353520be..32f9c45dea 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -229,6 +229,21 @@ static const char * const mount_mode_table[_MOUNT_MODE_MAX] = { [MQUEUEFS] = "mqueuefs", }; +/* Helper struct for naming simplicity and reusability */ +static const struct { + const char *level_env; + const char *level_env_print; +} image_class_info[_IMAGE_CLASS_MAX] = { + [IMAGE_SYSEXT] = { + .level_env = "SYSEXT_LEVEL", + .level_env_print = " SYSEXT_LEVEL=", + }, + [IMAGE_CONFEXT] = { + .level_env = "CONFEXT_LEVEL", + .level_env_print = " CONFEXT_LEVEL=", + } +}; + DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(mount_mode, MountMode); static const char *mount_entry_path(const MountEntry *p) { @@ -1231,17 +1246,32 @@ static int mount_image( const ImagePolicy *image_policy) { _cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL, - *host_os_release_sysext_level = NULL; + *host_os_release_level = NULL, *extension_name = NULL; + _cleanup_strv_free_ char **extension_release = NULL; + ImageClass class = IMAGE_SYSEXT; int r; assert(m); + r = path_extract_filename(mount_entry_source(m), &extension_name); + if (r < 0) + return log_debug_errno(r, "Failed to extract extension name from %s: %m", mount_entry_source(m)); + if (m->mode == EXTENSION_IMAGES) { + r = load_extension_release_pairs(mount_entry_source(m), IMAGE_SYSEXT, extension_name, /* relax_extension_release_check= */ false, &extension_release); + if (r == -ENOENT) { + r = load_extension_release_pairs(mount_entry_source(m), IMAGE_CONFEXT, extension_name, /* relax_extension_release_check= */ false, &extension_release); + if (r >= 0) + class = IMAGE_CONFEXT; + } + if (r == -ENOENT) + return r; + r = parse_os_release( empty_to_root(root_directory), "ID", &host_os_release_id, "VERSION_ID", &host_os_release_version_id, - "SYSEXT_LEVEL", &host_os_release_sysext_level, + image_class_info[class].level_env, &host_os_release_level, NULL); if (r < 0) return log_debug_errno(r, "Failed to acquire 'os-release' data of OS tree '%s': %m", empty_to_root(root_directory)); @@ -1257,7 +1287,7 @@ static int mount_image( image_policy, host_os_release_id, host_os_release_version_id, - host_os_release_sysext_level, + host_os_release_level, NULL); if (r == -ENOENT && m->ignore) return 0; @@ -1268,8 +1298,8 @@ static int mount_image( host_os_release_id, host_os_release_version_id ? " VERSION_ID=" : "", strempty(host_os_release_version_id), - host_os_release_sysext_level ? " SYSEXT_LEVEL=" : "", - strempty(host_os_release_sysext_level)); + host_os_release_level ? image_class_info[class].level_env_print : "", + strempty(host_os_release_level)); if (r < 0) return log_debug_errno(r, "Failed to mount image %s on %s: %m", mount_entry_source(m), mount_entry_path(m)); @@ -1402,25 +1432,35 @@ static int apply_one_mount( case EXTENSION_DIRECTORIES: { _cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL, - *host_os_release_sysext_level = NULL, *extension_name = NULL; + *host_os_release_level = NULL, *extension_name = NULL; _cleanup_strv_free_ char **extension_release = NULL; + ImageClass class = IMAGE_SYSEXT; r = path_extract_filename(mount_entry_source(m), &extension_name); if (r < 0) return log_debug_errno(r, "Failed to extract extension name from %s: %m", mount_entry_source(m)); + r = load_extension_release_pairs(mount_entry_source(m), IMAGE_SYSEXT, extension_name, /* relax_extension_release_check= */ false, &extension_release); + if (r == -ENOENT) { + r = load_extension_release_pairs(mount_entry_source(m), IMAGE_CONFEXT, extension_name, /* relax_extension_release_check= */ false, &extension_release); + if (r >= 0) + class = IMAGE_CONFEXT; + } + if (r == -ENOENT) + return r; + r = parse_os_release( empty_to_root(root_directory), "ID", &host_os_release_id, "VERSION_ID", &host_os_release_version_id, - "SYSEXT_LEVEL", &host_os_release_sysext_level, + image_class_info[class].level_env, &host_os_release_level, NULL); if (r < 0) return log_debug_errno(r, "Failed to acquire 'os-release' data of OS tree '%s': %m", empty_to_root(root_directory)); if (isempty(host_os_release_id)) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "'ID' field not found or empty in 'os-release' data of OS tree '%s': %m", empty_to_root(root_directory)); - r = load_extension_release_pairs(mount_entry_source(m), IMAGE_SYSEXT, extension_name, /* relax_extension_release_check= */ false, &extension_release); + r = load_extension_release_pairs(mount_entry_source(m), class, extension_name, /* relax_extension_release_check= */ false, &extension_release); if (r == -ENOENT && m->ignore) return 0; if (r < 0) @@ -1430,10 +1470,10 @@ static int apply_one_mount( extension_name, host_os_release_id, host_os_release_version_id, - host_os_release_sysext_level, - /* host_sysext_scope */ NULL, /* Leave empty, we need to accept both system and portable */ + host_os_release_level, + /* host_extension_scope */ NULL, /* Leave empty, we need to accept both system and portable */ extension_release, - IMAGE_SYSEXT); + class); if (r == 0) return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "Directory %s extension-release metadata does not match the root's", extension_name); if (r < 0) @@ -2091,7 +2131,8 @@ int setup_namespace( } if (n_extension_images > 0 || !strv_isempty(extension_directories)) { - r = parse_env_extension_hierarchies(&hierarchies, "SYSTEMD_SYSEXT_HIERARCHIES"); + /* Hierarchy population needs to be done for sysext and confext extension images */ + r = parse_env_extension_hierarchies(&hierarchies, "SYSTEMD_SYSEXT_AND_CONFEXT_HIERARCHIES"); if (r < 0) return r; } diff --git a/src/shared/extension-util.c b/src/shared/extension-util.c index 43a19bf262..d8b16b94e1 100644 --- a/src/shared/extension-util.c +++ b/src/shared/extension-util.c @@ -136,6 +136,9 @@ int parse_env_extension_hierarchies(char ***ret_hierarchies, const char *hierarc else if (streq(hierarchy_env, "SYSTEMD_SYSEXT_HIERARCHIES")) /* Default for sysext when unset */ l = strv_new("/usr", "/opt"); + else if (streq(hierarchy_env, "SYSTEMD_SYSEXT_AND_CONFEXT_HIERARCHIES")) + /* Combined sysext and confext directories */ + l = strv_new("/usr", "/opt", "/etc"); else return -ENXIO; } else if (r < 0) From b856f1dfc5bca0fbe60c37b7d0132a396c991270 Mon Sep 17 00:00:00 2001 From: Maanya Goenka Date: Mon, 14 Aug 2023 18:29:13 +0000 Subject: [PATCH 3/3] test: add test for confext service-scoped support --- test/test-functions | 7 +++++++ test/units/testsuite-50.sh | 13 ++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/test/test-functions b/test/test-functions index 4b4587aca7..9971ced7de 100644 --- a/test/test-functions +++ b/test/test-functions @@ -839,6 +839,13 @@ EOF echo "ARCHITECTURE=_any" ) >"$initdir/usr/lib/extension-release.d/extension-release.app-nodistro" echo MARKER=1 >"$initdir/usr/lib/systemd/system/some_file" mksquashfs "$initdir" "$oldinitdir/usr/share/app-nodistro.raw" -noappend + + export initdir="$TESTDIR/service-scoped-test" + mkdir -p "$initdir/etc/extension-release.d" "$initdir/etc/systemd/system" + ( echo "ID=_any" + echo "ARCHITECTURE=_any" ) >"$initdir/etc/extension-release.d/extension-release.service-scoped-test" + echo MARKER_CONFEXT_123 >"$initdir/etc/systemd/system/some_file" + mksquashfs "$initdir" "$oldinitdir/etc/service-scoped-test.raw" -noappend ) } diff --git a/test/units/testsuite-50.sh b/test/units/testsuite-50.sh index 21e9c75526..728674e14e 100755 --- a/test/units/testsuite-50.sh +++ b/test/units/testsuite-50.sh @@ -17,6 +17,7 @@ cleanup() {( umount "${image_dir}/app0" umount "${image_dir}/app1" umount "${image_dir}/app-nodistro" + umount "${image_dir}/service-scoped-test" rm -rf "${image_dir}" )} @@ -376,11 +377,19 @@ systemd-run -P --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.r systemd-run -P --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage="${image}.raw" cat /opt/script1.sh | grep -q -F "extension-release.app2" systemd-run -P --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage="${image}.raw" cat /usr/lib/systemd/system/other_file | grep -q -F "MARKER=1" systemd-run -P --property ExtensionImages=/usr/share/app-nodistro.raw --property RootImage="${image}.raw" cat /usr/lib/systemd/system/some_file | grep -q -F "MARKER=1" +systemd-run -P --property ExtensionImages=/etc/service-scoped-test.raw --property RootImage="${image}.raw" cat /etc/systemd/system/some_file | grep -q -F "MARKER_CONFEXT_123" # Check that using a symlink to NAME-VERSION.raw works as long as the symlink has the correct name NAME.raw mkdir -p /usr/share/symlink-test/ cp /usr/share/app-nodistro.raw /usr/share/symlink-test/app-nodistro-v1.raw ln -fs /usr/share/symlink-test/app-nodistro-v1.raw /usr/share/symlink-test/app-nodistro.raw systemd-run -P --property ExtensionImages=/usr/share/symlink-test/app-nodistro.raw --property RootImage="${image}.raw" cat /usr/lib/systemd/system/some_file | grep -q -F "MARKER=1" + +# Symlink check again but for confext +mkdir -p /etc/symlink-test/ +cp /etc/service-scoped-test.raw /etc/symlink-test/service-scoped-test-v1.raw +ln -fs /etc/symlink-test/service-scoped-test-v1.raw /etc/symlink-test/service-scoped-test.raw +systemd-run -P --property ExtensionImages=/etc/symlink-test/service-scoped-test.raw --property RootImage="${image}.raw" cat /etc/systemd/system/some_file | grep -q -F "MARKER_CONFEXT_123" + cat >/run/systemd/system/testservice-50e.service </run/systemd/system/testservice-50f.service <