]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysext: introduce ARCHITECTURE field to match host architecture 24263/head
authorKai Lueke <kailuke@microsoft.com>
Tue, 9 Aug 2022 15:07:20 +0000 (17:07 +0200)
committerKai Lueke <kailuke@microsoft.com>
Mon, 15 Aug 2022 08:54:32 +0000 (10:54 +0200)
When an extension image has binaries they should match the host
architecture. Currently there is no way to specify this requirement.
Introduce an ARCHITECTURE field in the extension's release file that
may be set to prevent loading on the wrong host architecture.
Since this new field is introduced late, we don't want to make
specifying it mandatory as it would break existing sysext images.

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

man/os-release.xml
man/systemd-sysext.xml
src/shared/extension-release.c
test/test-functions

index fc880c47651499a77be7b37461795af9d0bad053..168c1675a9491d63a87d09ab98c06ea4c996d420 100644 (file)
           determines the fallback hostname.</para></listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>ARCHITECTURE=</varname></term>
+          <listitem><para>A string that specifies which CPU architecture the userspace binaries require.
+          The architecture identifiers are the same as for <varname>ConditionArchitecture=</varname>
+          described in <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+          The field is optional and should only be used when just single architecture is supported.
+          It may provide redundant information when used in a GPT partition with a GUID type that already
+          encodes the architecture. If this is not the case, the architecture should be specified in
+          e.g., an extension image, to prevent an incompatible host from loading it.
+          </para></listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>SYSEXT_LEVEL=</varname></term>
 
index c2cf87c9cb9526817bd9da0fc6ca407aebb30af4..8da6bd26ad93f7115878418a6b995191d41b38ba 100644 (file)
     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
-    <filename>extension-release</filename> file follows the same format and semantics, and carries the same
+    <varname>VERSION_ID=</varname> field has to match instead. If the extension defines the
+    <varname>ARCHITECTURE=</varname> field and the value is not <literal>_any</literal> it has to match the kernel's
+    architecture reported by <citerefentry><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+    but the used architecture identifiers are the same as for <varname>ConditionArchitecture=</varname>
+    described in <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+    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 <filename>extension-release</filename> file follows the same format and semantics, and carries the same
     content, as the <filename>os-release</filename> file of the OS, but it describes the resources carried
     in the extension image.</para>
   </refsect1>
index 681dcbf7f8160ce41df1e26e8dead09ab57f5dd7..2da8e7ea94bec49d261fac8891d42da32d8a7b7b 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include "alloc-util.h"
+#include "architecture.h"
 #include "env-util.h"
 #include "extension-release.h"
 #include "log.h"
@@ -15,7 +16,7 @@ int extension_release_validate(
                 const char *host_sysext_scope,
                 char **extension_release) {
 
-        const char *extension_release_id = NULL, *extension_release_sysext_level = NULL;
+        const char *extension_release_id = NULL, *extension_release_sysext_level = NULL, *extension_architecture = NULL;
 
         assert(name);
         assert(!isempty(host_os_release_id));
@@ -48,6 +49,16 @@ int extension_release_validate(
                 }
         }
 
+        /* When the architecture field is present and not '_any' it must match the host - for now just look at uname but in
+         * the future we could check if the kernel also supports 32 bit or binfmt has a translator set up for the architecture */
+        extension_architecture = strv_env_pairs_get(extension_release, "ARCHITECTURE");
+        if (!isempty(extension_architecture) && !streq(extension_architecture, "_any") &&
+            !streq(architecture_to_string(uname_architecture()), extension_architecture)) {
+                log_debug("Extension '%s' is for architecture '%s', but deployed on top of '%s'.",
+                          name, extension_architecture, architecture_to_string(uname_architecture()));
+                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' or be '_any'",
index f7f467dfca8bfce3b93902f415d4b17d16d3905f..5dec5e28dec1e04b1270ee432a28d7c0b19c71f5 100644 (file)
@@ -715,7 +715,8 @@ EOF
 
         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 "ID=_any"
+          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
     )