Support global sysext/confext in systemd-stub/systemd-sysext (#38113)

Systemd-stub supports loading addons, credentials, system and
configuration
extensions from ESP and while addons and credentials can be both global
and
per-UKI, sysext/confext are only per-UKI. 

Add support for global sysext/confext to systemd-stub/systemd-sysext.

Fixes #37993
This commit is contained in:
Lennart Poettering
2025-07-11 21:10:51 +02:00
committed by GitHub
6 changed files with 83 additions and 9 deletions

View File

@@ -36,6 +36,8 @@
<member><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.confext.raw</filename></member>
<member><filename><replaceable>ESP</replaceable>/loader/addons/*.addon.efi</filename></member>
<member><filename><replaceable>ESP</replaceable>/loader/credentials/*.cred</filename></member>
<member><filename><replaceable>ESP</replaceable>/loader/extensions/*.sysext.raw</filename></member>
<member><filename><replaceable>ESP</replaceable>/loader/extensions/*.confext.raw</filename></member>
</simplelist></para>
</refsynopsisdiv>
@@ -202,8 +204,8 @@
<listitem><para>Similarly, files
<filename><replaceable>foo</replaceable>.efi.extra.d/*.sysext.raw</filename> are packed up in a
<command>cpio</command> archive and placed in the <filename>/.extra/sysext/</filename> directory in the
initrd file hierarchy. This is supposed to be used to pass additional system extension images to the
initrd. See
initrd file hierarchy. This is supposed to be used to pass additional UKI-specific system extension
images to the initrd. See
<citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details on system extension images. The generated <command>cpio</command> archive containing these
system extension images is measured into TPM PCR 13 (if a TPM is present).</para></listitem>
@@ -212,11 +214,27 @@
compatibility reasons with old versions. But we want people to name their system extensions
properly, hence we document the *.sysext.raw suffix only. -->
<listitem><para>Similarly, files <filename>/loader/extensions/*.sysext.raw</filename>
are packed up in a <command>cpio</command> archive and placed in the <filename>/.extra/global_sysext/</filename>
directory in the initrd file hierarchy. This is supposed to be used to pass additional global system
extension images to the initrd. See
<citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details on system extension images. The generated <command>cpio</command> archive containing these
system extension images is measured into TPM PCR 13 (if a TPM is present).</para></listitem>
<listitem><para>Similarly, files
<filename><replaceable>foo</replaceable>.efi.extra.d/*.confext.raw</filename> are packed up in a
<command>cpio</command> archive and placed in the <filename>/.extra/confext/</filename> directory in
the initrd file hierarchy. This is supposed to be used to pass additional configuration extension
images to the initrd. See
the initrd file hierarchy. This is supposed to be used to pass additional UKI-specific configuration
extension images to the initrd. See
<citerefentry><refentrytitle>systemd-confext</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details on configuration extension images. The generated <command>cpio</command> archive containing
these configuration extension images is measured into TPM PCR 12 (if a TPM is present).</para></listitem>
<listitem><para>Similarly, files <filename>/loader/extensions/*.confext.raw</filename>
are packed up in a <command>cpio</command> archive and placed in the <filename>/.extra/global_confext/</filename>
directory in the initrd file hierarchy. This is supposed to be used to pass additional global configuration
extension images to the initrd. See
<citerefentry><refentrytitle>systemd-confext</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details on configuration extension images. The generated <command>cpio</command> archive containing
these configuration extension images is measured into TPM PCR 12 (if a TPM is present).</para></listitem>
@@ -676,6 +694,16 @@
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/global_sysext/*.sysext.raw</filename></term>
<listitem><para>Similarly, system extension image files (suffix <literal>.sysext.raw</literal>) that
are placed in the <filename>/loader/extensions/</filename> directory in the file system the unified
kernel image is placed in are copied into the <filename>/.extra/global_sysext/</filename>
directory in the initrd execution environment.</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/confext/*.confext.raw</filename></term>
<listitem><para>Configuration extension image files (suffix <literal>.confext.raw</literal>) that are
@@ -685,6 +713,16 @@
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/global_confext/*.confext.raw</filename></term>
<listitem><para>Similarly, configuration extension image files (suffix <literal>.confext.raw</literal>)
that are placed in the <filename>/loader/extensions/</filename> directory in the file system the unified
kernel image is placed in are copied into the <filename>/.extra/global_confext/</filename>
directory in the initrd execution environment.</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/tpm2-pcr-signature.json</filename></term>
<listitem><para>The TPM2 PCR signature JSON object included in the <literal>.pcrsig</literal> PE

View File

@@ -38,7 +38,9 @@ enum {
INITRD_CREDENTIAL = _INITRD_DYNAMIC_FIRST,
INITRD_GLOBAL_CREDENTIAL,
INITRD_SYSEXT,
INITRD_GLOBAL_SYSEXT,
INITRD_CONFEXT,
INITRD_GLOBAL_CONFEXT,
INITRD_PCRSIG,
INITRD_PCRPKEY,
INITRD_OSREL,
@@ -869,6 +871,19 @@ static void generate_sidecar_initrds(
&m) == EFI_SUCCESS)
combine_measured_flag(sysext_measured, m);
if (pack_cpio(loaded_image,
u"\\loader\\extensions",
u".sysext.raw",
/* exclude_suffix= */ NULL,
".extra/global_sysext",
/* dir_mode= */ 0555,
/* access_mode= */ 0444,
/* tpm_pcr= */ TPM2_PCR_SYSEXTS,
u"Global system extension initrd",
initrds + INITRD_GLOBAL_SYSEXT,
&m) == EFI_SUCCESS)
combine_measured_flag(sysext_measured, m);
if (pack_cpio(loaded_image,
/* dropin_dir= */ NULL,
u".confext.raw",
@@ -881,6 +896,19 @@ static void generate_sidecar_initrds(
initrds + INITRD_CONFEXT,
&m) == EFI_SUCCESS)
combine_measured_flag(confext_measured, m);
if (pack_cpio(loaded_image,
u"\\loader\\extensions",
u".confext.raw",
/* exclude_suffix= */ NULL,
".extra/global_confext",
/* dir_mode= */ 0555,
/* access_mode= */ 0444,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Global configuration extension initrd",
initrds + INITRD_GLOBAL_CONFEXT,
&m) == EFI_SUCCESS)
combine_measured_flag(confext_measured, m);
}
static void generate_embedded_initrds(

View File

@@ -76,20 +76,22 @@ const char* const image_search_path[_IMAGE_CLASS_MAX] = {
"/usr/lib/confexts\0",
};
/* Inside the initrd, use a slightly different set of search path (i.e. include .extra/sysext/ and
* .extra/confext/ in extension search dir) */
/* Inside the initrd, use a slightly different set of search path (i.e. include .extra/sysext/,
* /.extra/global_sysext, .extra/confext/, and /.extra/global_confext in extension search dir) */
static const char* const image_search_path_initrd[_IMAGE_CLASS_MAX] = {
/* (entries that aren't listed here will get the same search path as for the non initrd-case) */
[IMAGE_SYSEXT] = "/etc/extensions\0" /* only place symlinks here */
"/run/extensions\0" /* and here too */
"/var/lib/extensions\0" /* the main place for images */
"/.extra/sysext\0", /* put sysext picked up by systemd-stub last, since not trusted */
"/.extra/sysext\0" /* put sysext (per-UKI and global) picked up by systemd-stub */
"/.extra/global_sysext\0", /* last, since not trusted */
[IMAGE_CONFEXT] = "/run/confexts\0" /* only place symlinks here */
"/var/lib/confexts\0" /* the main place for images */
"/usr/local/lib/confexts\0"
"/.extra/confext\0", /* put confext picked up by systemd-stub last, since not trusted */
"/.extra/confext\0" /* put confext (per-UKI and global) picked up by systemd-stub */
"/.extra/global_confext\0", /* last, since not trusted. */
};
static const char* image_class_suffix_table[_IMAGE_CLASS_MAX] = {

View File

@@ -1660,15 +1660,19 @@ static const ImagePolicy *pick_image_policy(const Image *img) {
if (arg_image_policy)
return arg_image_policy;
/* If located in /.extra/sysext/ in the initrd, then it was placed there by systemd-stub, and was
/* If located in /.extra/ in the initrd, then it was placed there by systemd-stub, and was
* picked up from an untrusted ESP. Thus, require a stricter policy by default for them. (For the
* other directories we assume the appropriate level of trust was already established already. */
if (in_initrd()) {
if (path_startswith(img->path, "/.extra/sysext/"))
return &image_policy_sysext_strict;
if (path_startswith(img->path, "/.extra/global_sysext/"))
return &image_policy_sysext_strict;
if (path_startswith(img->path, "/.extra/confext/"))
return &image_policy_confext_strict;
if (path_startswith(img->path, "/.extra/global_confext/"))
return &image_policy_confext_strict;
/* Better safe than sorry, refuse everything else passed in via the untrusted /.extra/ dir */
if (path_startswith(img->path, "/.extra/"))

View File

@@ -17,6 +17,7 @@ ConditionDirectoryNotEmpty=|/var/lib/confexts
ConditionDirectoryNotEmpty=|/usr/local/lib/confexts
ConditionDirectoryNotEmpty=|/usr/lib/confexts
ConditionDirectoryNotEmpty=|/.extra/confext
ConditionDirectoryNotEmpty=|/.extra/global_confext
ConditionPathExists=/etc/initrd-release
DefaultDependencies=no

View File

@@ -16,6 +16,7 @@ ConditionDirectoryNotEmpty=|/etc/extensions
ConditionDirectoryNotEmpty=|/run/extensions
ConditionDirectoryNotEmpty=|/var/lib/extensions
ConditionDirectoryNotEmpty=|/.extra/sysext
ConditionDirectoryNotEmpty=|/.extra/global_sysext
ConditionPathExists=/etc/initrd-release
DefaultDependencies=no