]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysext: support distribution-independent extensions using ID=_any
authorKai Lueke <kailuke@microsoft.com>
Tue, 9 Aug 2022 11:34:18 +0000 (13:34 +0200)
committerKai Lueke <kailuke@microsoft.com>
Mon, 15 Aug 2022 08:51:01 +0000 (10:51 +0200)
A sysext image that merely contains static binaries has no dependency
on the host distribution and should be able to be used anywhere.
Support the special '_any' value for the ID field in the extension to
opt-out of ID and VERSION_ID/SYSEXT_LEVEL matching.

See https://github.com/systemd/systemd/issues/24061

man/systemd-sysext.xml
src/shared/extension-release.c
test/test-functions
test/units/testsuite-50.sh

index 42e8e12df97ff660c39d4f6171291067f5a21c6b..c2cf87c9cb9526817bd9da0fc6ca407aebb30af4 100644 (file)
     <para>A simple mechanism for version compatibility is enforced: a system extension image must carry a
     <filename>/usr/lib/extension-release.d/extension-release.<replaceable>$name</replaceable></filename>
     file, which must match its image name, that is compared with the host <filename>os-release</filename>
-    file: the contained <varname>ID=</varname> fields have to match, as well as the
-    <varname>SYSEXT_LEVEL=</varname> field (if defined). If the latter is not defined, the
+    file: the contained <varname>ID=</varname> fields have to match unless <literal>_any</literal> is set
+    for the extension. If the extension <varname>ID=</varname> is not <literal>_any</literal>, the
+    <varname>SYSEXT_LEVEL=</varname> field (if defined) has to match. If the latter is not defined, the
     <varname>VERSION_ID=</varname> field has to match instead. System extensions should not ship a
     <filename>/usr/lib/os-release</filename> file (as that would be merged into the host
     <filename>/usr/</filename> tree, overriding the host OS version data, which is not desirable). The
index db87b23a71e1eeefd06fa7a4bc34159748ba716a..681dcbf7f8160ce41df1e26e8dead09ab57f5dd7 100644 (file)
@@ -50,11 +50,18 @@ int extension_release_validate(
 
         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'",
+                log_debug("Extension '%s' does not contain ID in extension-release but requested to match '%s' or be '_any'",
                           name, host_os_release_id);
                 return 0;
         }
 
+        /* A sysext with no host OS dependency (static binaries or scripts) can match
+         * '_any' host OS, and VERSION_ID or SYSEXT_LEVEL are not required anywhere */
+        if (streq(extension_release_id, "_any")) {
+                log_debug("Extension '%s' matches '_any' OS.", name);
+                return 1;
+        }
+
         if (!streq(host_os_release_id, extension_release_id)) {
                 log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
                           name, extension_release_id, host_os_release_id);
index b208825e67425b4f8ec4d2239ed25c9d242557b8..f7f467dfca8bfce3b93902f415d4b17d16d3905f 100644 (file)
@@ -712,6 +712,12 @@ EOF
         chmod +x "$initdir/opt/script1.sh"
         echo MARKER=1 >"$initdir/usr/lib/systemd/system/other_file"
         mksquashfs "$initdir" "$oldinitdir/usr/share/app1.raw" -noappend
+
+        export initdir="$TESTDIR/app-nodistro"
+        mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system"
+        ( echo "ID=_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
     )
 }
 
index 31cb52064eaa149a6228856899cb1e8c677b1c4d..ae6dd0b3d7eba109201599379150a30fa957a266 100755 (executable)
@@ -305,6 +305,7 @@ 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 /usr/lib/systemd/system/some_file | grep -q -F "MARKER=1"
 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"
 cat >/run/systemd/system/testservice-50e.service <<EOF
 [Service]
 MountAPIVFS=yes
@@ -323,17 +324,19 @@ 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"
+mkdir -p "${image_dir}/app0" "${image_dir}/app1" "${image_dir}/app-nodistro"
 systemd-run -P --property ExtensionDirectories="${image_dir}/nonexistent" --property RootImage="${image}.raw" cat /opt/script0.sh && { echo 'unexpected success'; exit 1; }
 systemd-run -P --property ExtensionDirectories="${image_dir}/app0" --property RootImage="${image}.raw" cat /opt/script0.sh && { echo 'unexpected success'; exit 1; }
 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-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"
 systemd-run -P --property ExtensionDirectories="${image_dir}/app0 ${image_dir}/app1" --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/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"
 cat >/run/systemd/system/testservice-50f.service <<EOF
 [Service]
 MountAPIVFS=yes