Merge pull request #28733 from goenkam/maanya/systemd-scoped

core: add confext support for ExtensionImages= and ExtensionDirectories=
This commit is contained in:
Luca Boccassi
2023-08-16 10:12:46 +01:00
committed by GitHub
5 changed files with 77 additions and 13 deletions
+2
View File
@@ -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"))
+53 -12
View File
@@ -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;
}
+3
View File
@@ -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)
+7
View File
@@ -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
)
}
+12 -1
View File
@@ -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 <<EOF
[Service]
MountAPIVFS=yes
@@ -399,12 +408,13 @@ systemctl start testservice-50e.service
systemctl is-active testservice-50e.service
# ExtensionDirectories will set up an overlay
mkdir -p "${image_dir}/app0" "${image_dir}/app1" "${image_dir}/app-nodistro"
mkdir -p "${image_dir}/app0" "${image_dir}/app1" "${image_dir}/app-nodistro" "${image_dir}/service-scoped-test"
(! systemd-run -P --property ExtensionDirectories="${image_dir}/nonexistent" --property RootImage="${image}.raw" cat /opt/script0.sh)
(! systemd-run -P --property ExtensionDirectories="${image_dir}/app0" --property RootImage="${image}.raw" cat /opt/script0.sh)
systemd-dissect --mount /usr/share/app0.raw "${image_dir}/app0"
systemd-dissect --mount /usr/share/app1.raw "${image_dir}/app1"
systemd-dissect --mount /usr/share/app-nodistro.raw "${image_dir}/app-nodistro"
systemd-dissect --mount /etc/service-scoped-test.raw "${image_dir}/service-scoped-test"
systemd-run -P --property ExtensionDirectories="${image_dir}/app0" --property RootImage="${image}.raw" cat /opt/script0.sh | grep -q -F "extension-release.app0"
systemd-run -P --property ExtensionDirectories="${image_dir}/app0" --property RootImage="${image}.raw" cat /usr/lib/systemd/system/some_file | grep -q -F "MARKER=1"
systemd-run -P --property ExtensionDirectories="${image_dir}/app0 ${image_dir}/app1" --property RootImage="${image}.raw" cat /opt/script0.sh | grep -q -F "extension-release.app0"
@@ -412,6 +422,7 @@ systemd-run -P --property ExtensionDirectories="${image_dir}/app0 ${image_dir}/a
systemd-run -P --property ExtensionDirectories="${image_dir}/app0 ${image_dir}/app1" --property RootImage="${image}.raw" cat /opt/script1.sh | grep -q -F "extension-release.app2"
systemd-run -P --property ExtensionDirectories="${image_dir}/app0 ${image_dir}/app1" --property RootImage="${image}.raw" cat /usr/lib/systemd/system/other_file | grep -q -F "MARKER=1"
systemd-run -P --property ExtensionDirectories="${image_dir}/app-nodistro" --property RootImage="${image}.raw" cat /usr/lib/systemd/system/some_file | grep -q -F "MARKER=1"
systemd-run -P --property ExtensionDirectories="${image_dir}/service-scoped-test" --property RootImage="${image}.raw" cat /etc/systemd/system/some_file | grep -q -F "MARKER_CONFEXT_123"
cat >/run/systemd/system/testservice-50f.service <<EOF
[Service]
MountAPIVFS=yes