summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-11-18 22:00:31 +0100
committerLennart Poettering <lennart@poettering.net>2021-11-23 22:55:11 +0100
commit60c5f7002bfee928fb8799eb35e5cc95da982a48 (patch)
tree914764af8704c787ece225a0f97aa01afefa4c22
parenta4e0d6171318b5f381a1cbdb6de895920d7f15d6 (diff)
downloadsystemd-60c5f7002bfee928fb8799eb35e5cc95da982a48.tar.gz
extension-release.d/: add a new field SYSEXT_SCOPE= for clarifying what a system extension is for
This should make things a bit more robust since it ensures system extension can only applied to the right environments. Right now three different "scopes" are defined: 1. "system" (for regular OS systems, after the initrd transition) 2. "initrd" (for sysext images that apply to the initrd environment) 3. "portable" (for sysext images that apply to portable images) If not specified we imply a default of "system portable", i.e. any image where the field is not specified is implicitly OK for application to OS images and for portable services – but not for initrds.
-rw-r--r--man/os-release.xml12
-rw-r--r--src/core/namespace.c2
-rw-r--r--src/portable/portable.c2
-rw-r--r--src/shared/dissect-image.c14
-rw-r--r--src/shared/dissect-image.h2
-rw-r--r--src/shared/extension-release.c23
-rw-r--r--src/shared/extension-release.h1
-rw-r--r--src/shared/mount-util.c2
-rw-r--r--src/sysext/sysext.c7
9 files changed, 54 insertions, 11 deletions
diff --git a/man/os-release.xml b/man/os-release.xml
index ef5ef8b2e1..a985151b4d 100644
--- a/man/os-release.xml
+++ b/man/os-release.xml
@@ -407,6 +407,18 @@
<para>Examples: <literal>SYSEXT_LEVEL=2</literal>, <literal>SYSEXT_LEVEL=15.14</literal>.
</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>SYSEXT_SCOPE=</varname></term>
+ <listitem><para>Takes a space-separated list of one or more of the strings
+ <literal>system</literal>, <literal>initrd</literal> and <literal>portable</literal>. This field is
+ only supported in <filename>extension-release.d/</filename> files and indicates what environments
+ the system extension is applicable to: i.e. to regular systems, to initial RAM filesystems
+ ("initrd") or to portable service images. If unspecified, <literal>SYSEXT_SCOPE=system
+ portable</literal> is implied, i.e. any system extension without this field is applicable to
+ regular systems and to portable service environments, but not to initrd
+ environments.</para></listitem>
+ </varlistentry>
</variablelist>
</refsect2>
diff --git a/src/core/namespace.c b/src/core/namespace.c
index c8e7e65e27..9393a202c4 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1149,7 +1149,7 @@ static int mount_image(const MountEntry *m, const char *root_directory) {
r = verity_dissect_and_mount(
mount_entry_source(m), mount_entry_path(m), m->image_options,
- host_os_release_id, host_os_release_version_id, host_os_release_sysext_level);
+ host_os_release_id, host_os_release_version_id, host_os_release_sysext_level, NULL);
if (r == -ENOENT && m->ignore)
return 0;
if (r == -ESTALE && host_os_release_id)
diff --git a/src/portable/portable.c b/src/portable/portable.c
index 8ccb8f5228..612893b688 100644
--- a/src/portable/portable.c
+++ b/src/portable/portable.c
@@ -595,7 +595,7 @@ static int extract_image_and_extensions(
if (r < 0)
return r;
- r = extension_release_validate(ext->path, id, version_id, sysext_level, extension_release);
+ r = extension_release_validate(ext->path, id, version_id, sysext_level, "portable", 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)
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index b92df413a9..06d0319f75 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -3525,7 +3525,8 @@ int verity_dissect_and_mount(
const MountOptions *options,
const char *required_host_os_release_id,
const char *required_host_os_release_version_id,
- const char *required_host_os_release_sysext_level) {
+ const char *required_host_os_release_sysext_level,
+ const char *required_sysext_scope) {
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
@@ -3611,11 +3612,12 @@ int verity_dissect_and_mount(
return log_debug_errno(r, "Failed to parse image %s extension-release metadata: %m", dissected_image->image_name);
r = extension_release_validate(
- dissected_image->image_name,
- required_host_os_release_id,
- required_host_os_release_version_id,
- required_host_os_release_sysext_level,
- extension_release);
+ dissected_image->image_name,
+ required_host_os_release_id,
+ required_host_os_release_version_id,
+ required_host_os_release_sysext_level,
+ required_sysext_scope,
+ extension_release);
if (r == 0)
return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", dissected_image->image_name);
if (r < 0)
diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h
index b75b86ab99..8ad26bc45b 100644
--- a/src/shared/dissect-image.h
+++ b/src/shared/dissect-image.h
@@ -228,4 +228,4 @@ bool dissected_image_verity_sig_ready(const DissectedImage *image, PartitionDesi
int mount_image_privately_interactively(const char *path, DissectImageFlags flags, char **ret_directory, LoopDevice **ret_loop_device, DecryptedImage **ret_decrypted_image);
-int verity_dissect_and_mount(const char *src, const char *dest, const MountOptions *options, const char *required_host_os_release_id, const char *required_host_os_release_version_id, const char *required_host_os_release_sysext_level);
+int verity_dissect_and_mount(const char *src, const char *dest, const MountOptions *options, const char *required_host_os_release_id, const char *required_host_os_release_version_id, const char *required_host_os_release_sysext_level, const char *required_sysext_scope);
diff --git a/src/shared/extension-release.c b/src/shared/extension-release.c
index 29cbecbf57..dccc999907 100644
--- a/src/shared/extension-release.c
+++ b/src/shared/extension-release.c
@@ -12,6 +12,7 @@ int extension_release_validate(
const char *host_os_release_id,
const char *host_os_release_version_id,
const char *host_os_release_sysext_level,
+ const char *host_sysext_scope,
char **extension_release) {
const char *extension_release_id = NULL, *extension_release_sysext_level = NULL;
@@ -25,6 +26,28 @@ int extension_release_validate(
return 0;
}
+ if (host_sysext_scope) {
+ _cleanup_strv_free_ char **extension_sysext_scope_list = NULL;
+ const char *extension_sysext_scope;
+ bool valid;
+
+ extension_sysext_scope = strv_env_pairs_get(extension_release, "SYSEXT_SCOPE");
+ if (extension_sysext_scope) {
+ extension_sysext_scope_list = strv_split(extension_sysext_scope, WHITESPACE);
+ if (!extension_sysext_scope_list)
+ return -ENOMEM;
+ }
+
+ /* by default extension are good for attachment in portable service and on the system */
+ valid = strv_contains(
+ extension_sysext_scope_list ?: STRV_MAKE("system", "portable"),
+ host_sysext_scope);
+ if (!valid) {
+ log_debug("Extension '%s' is not suitable for scope %s, ignoring extension.", name, host_sysext_scope);
+ return 0;
+ }
+ }
+
extension_release_id = strv_env_pairs_get(extension_release, "ID");
if (isempty(extension_release_id)) {
log_debug("Extension '%s' does not contain ID in extension-release but requested to match '%s'",
diff --git a/src/shared/extension-release.h b/src/shared/extension-release.h
index d026a9b225..5c3fee24be 100644
--- a/src/shared/extension-release.h
+++ b/src/shared/extension-release.h
@@ -9,6 +9,7 @@ int extension_release_validate(
const char *host_os_release_id,
const char *host_os_release_version_id,
const char *host_os_release_sysext_level,
+ const char *host_sysext_scope,
char **extension_release);
/* Parse SYSTEMD_SYSEXT_HIERARCHIES and if not set, return "/usr /opt" */
diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c
index 8d4a6cd25a..c75c02f5be 100644
--- a/src/shared/mount-util.c
+++ b/src/shared/mount-util.c
@@ -874,7 +874,7 @@ static int mount_in_namespace(
mount_tmp_created = true;
if (is_image)
- r = verity_dissect_and_mount(FORMAT_PROC_FD_PATH(chased_src_fd), mount_tmp, options, NULL, NULL, NULL);
+ r = verity_dissect_and_mount(FORMAT_PROC_FD_PATH(chased_src_fd), mount_tmp, options, NULL, NULL, NULL, NULL);
else
r = mount_follow_verbose(LOG_DEBUG, FORMAT_PROC_FD_PATH(chased_src_fd), mount_tmp, NULL, MS_BIND, NULL);
if (r < 0)
diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c
index b9387e904a..5abf1bb418 100644
--- a/src/sysext/sysext.c
+++ b/src/sysext/sysext.c
@@ -432,12 +432,17 @@ static int validate_version(
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Extension image contains /usr/lib/os-release file, which is not allowed (it may carry /etc/os-release), refusing.");
- return extension_release_validate(
+ r = extension_release_validate(
img->name,
host_os_release_id,
host_os_release_version_id,
host_os_release_sysext_level,
+ in_initrd() ? "initrd" : "system",
img->extension_release);
+ if (r < 0)
+ return log_error_errno(r, "Failed to validate extension release information: %m");
+
+ return r;
}
static int merge_subprocess(Hashmap *images, const char *workspace) {