1
0
mirror of https://github.com/systemd/systemd synced 2024-07-09 04:26:06 +00:00

stub: pick up confexts from the ESP as well

This does what we do for system extension also for configuration
extension.

This is complicated by the fact that we previously looked for
<uki-binary>.d/*.raw for system extensions. We want to measure sysexts
and confexts to different PCRs (13 vs. 12) hence we must distinguish
them, but *.raw would match both kinds.

This commit solves this via the following mechanism: we'll load confexts
from *.confext.raw and sysexts from *.raw but will then enclude
*.confext.raw from the latter. This preserves compatibility but allows
us to somewhat reasonable distinguish both types of images.

The documentation is updated not going into this detail though, and
instead now claims that sysexts shall be *.sysext.raw and confexts
*.confext.raw even though we actually are more lenient than this. This
is simply to push people towards using the longer, more descriptive
suffixes.

I added an XML comment (<!-- … -->) about this to the docs, so that
whenever somebody notices the difference between code and docs
understands why and leaves it that way.
This commit is contained in:
Lennart Poettering 2023-11-08 19:02:03 +01:00
parent cb924b9b6a
commit 39e0c237f1
6 changed files with 99 additions and 28 deletions

View File

@ -32,6 +32,8 @@
<member><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.addon.efi</filename></member>
<member><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.cred</filename></member>
<member><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.raw</filename></member>
<member><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.sysext.raw</filename></member>
<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>
</simplelist></para>
@ -153,14 +155,28 @@
details on encrypted credentials. The generated <command>cpio</command> archive is measured into TPM
PCR 12 (if a TPM is present).</para></listitem>
<listitem><para>Similarly, files <filename><replaceable>foo</replaceable>.efi.extra.d/*.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
<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
<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>
<!-- Note: the actual suffix we look for for sysexts is just *.raw (not *.sysext.raw), for
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><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
<citerefentry><refentrytitle>systemd-confext</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details on configuration extension images. The generated <command>cpio</command> archive containing
these system extension images is measured into TPM PCR 12 (if a TPM is present).</para></listitem>
<listitem><para>Similarly, files
<filename><replaceable>foo</replaceable>.efi.extra.d/*.addon.efi</filename> are loaded and verified as
PE binaries, and a <literal>.cmdline</literal> section is parsed from them. Addons are supposed to be
@ -218,9 +234,10 @@
<para>Also note that the Linux kernel will measure all initrds it receives into TPM PCR 9. This means
every type of initrd will be measured two or three times: the initrd embedded in the kernel image will be
measured to PCR 4, PCR 9 and PCR 11; the initrd synthesized from credentials will be measured to both PCR
9 and PCR 12; the initrd synthesized from system extensions will be measured to both PCR 4 and PCR
9. Let's summarize the OS resources and the PCRs they are measured to:</para>
measured to PCR 4, PCR 9 and PCR 11; the initrd synthesized from credentials (and the one synthesized
from configuration extensions) will be measured to both PCR 9 and PCR 12; the initrd synthesized from
system extensions will be measured to both PCR 4 and PCR 9. Let's summarize the OS resources and the PCRs
they are measured to:</para>
<table>
<title>OS Resource PCR Summary</title>
@ -291,6 +308,11 @@
<entry>System Extensions (synthesized initrd from companion files)</entry>
<entry>9 + 13</entry>
</row>
<row>
<entry>Configuration Extensions (synthesized initrd from companion files)</entry>
<entry>9 + 12</entry>
</row>
</tbody>
</tgroup>
</table>
@ -371,13 +393,24 @@
<varlistentry>
<term><varname>StubPcrInitRDSysExts</varname></term>
<listitem><para>The PCR register index the systemd extensions for the initrd, which are picked up
from the file system the kernel image is located on. Formatted as decimal ASCII string (e.g.
<listitem><para>The PCR register index the system extensions for the initrd, which are picked up from
the file system the kernel image is located on. Formatted as decimal ASCII string (e.g.
<literal>13</literal>). This variable is set if a measurement was successfully completed, and remains
unset otherwise.</para>
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>StubPcrInitRDConfExts</varname></term>
<listitem><para>The PCR register index the configuration extensions for the initrd, which are picked
up from the file system the kernel image is located on. Formatted as decimal ASCII string (e.g.
<literal>12</literal>). This variable is set if a measurement was successfully completed, and remains
unset otherwise.</para>
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>
</variablelist>
<para>Note that some of the variables above may also be set by the boot loader. The stub will only set
@ -422,14 +455,23 @@
</varlistentry>
<varlistentry>
<term><filename>/.extra/sysext/*.raw</filename></term>
<listitem><para>System extension image files (suffix <literal>.raw</literal>) that are placed next to
the unified kernel image (as described above) are copied into the
<term><filename>/.extra/sysext/*.sysext.raw</filename></term>
<listitem><para>System extension image files (suffix <literal>.sysext.raw</literal>) that are placed
next to the unified kernel image (as described above) are copied into the
<filename>/.extra/sysext/</filename> directory in the initrd execution environment.</para>
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/confext/*.confext.raw</filename></term>
<listitem><para>Configuration extension image files (suffix <literal>.confext.raw</literal>) that are
placed next to the unified kernel image (as described above) are copied into the
<filename>/.extra/confext/</filename> directory in the initrd execution environment.</para>
<xi:include href="version-info.xml" xpointer="v255"/></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

@ -374,14 +374,15 @@ int verb_status(int argc, char *argv[], void *userdata) {
uint64_t flag;
const char *name;
} stub_flags[] = {
{ EFI_STUB_FEATURE_REPORT_BOOT_PARTITION, "Stub sets ESP information" },
{ EFI_STUB_FEATURE_PICK_UP_CREDENTIALS, "Picks up credentials from boot partition" },
{ EFI_STUB_FEATURE_PICK_UP_SYSEXTS, "Picks up system extension images from boot partition" },
{ EFI_STUB_FEATURE_THREE_PCRS, "Measures kernel+command line+sysexts" },
{ EFI_STUB_FEATURE_RANDOM_SEED, "Support for passing random seed to OS" },
{ EFI_STUB_FEATURE_CMDLINE_ADDONS, "Pick up .cmdline from addons" },
{ EFI_STUB_FEATURE_CMDLINE_SMBIOS, "Pick up .cmdline from SMBIOS Type 11" },
{ EFI_STUB_FEATURE_DEVICETREE_ADDONS, "Pick up .dtb from addons" },
{ EFI_STUB_FEATURE_REPORT_BOOT_PARTITION, "Stub sets ESP information" },
{ EFI_STUB_FEATURE_PICK_UP_CREDENTIALS, "Picks up credentials from boot partition" },
{ EFI_STUB_FEATURE_PICK_UP_SYSEXTS, "Picks up system extension images from boot partition" },
{ EFI_STUB_FEATURE_PICK_UP_CONFEXTS, "Picks up configuration extension images from boot partition" },
{ EFI_STUB_FEATURE_THREE_PCRS, "Measures kernel+command line+sysexts" },
{ EFI_STUB_FEATURE_RANDOM_SEED, "Support for passing random seed to OS" },
{ EFI_STUB_FEATURE_CMDLINE_ADDONS, "Pick up .cmdline from addons" },
{ EFI_STUB_FEATURE_CMDLINE_SMBIOS, "Pick up .cmdline from SMBIOS Type 11" },
{ EFI_STUB_FEATURE_DEVICETREE_ADDONS, "Pick up .dtb from addons" },
};
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
sd_id128_t loader_part_uuid = SD_ID128_NULL;

View File

@ -305,6 +305,7 @@ EFI_STATUS pack_cpio(
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
const char16_t *dropin_dir,
const char16_t *match_suffix,
const char16_t *exclude_suffix,
const char *target_dir_prefix,
uint32_t dir_mode,
uint32_t access_mode,
@ -367,6 +368,8 @@ EFI_STATUS pack_cpio(
continue;
if (match_suffix && !endswith_no_case(dirent->FileName, match_suffix))
continue;
if (exclude_suffix && endswith_no_case(dirent->FileName, exclude_suffix))
continue;
if (!is_ascii(dirent->FileName))
continue;
if (strlen16(dirent->FileName) > 255) /* Max filename size on Linux */

View File

@ -8,6 +8,7 @@ EFI_STATUS pack_cpio(
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
const char16_t *dropin_dir,
const char16_t *match_suffix,
const char16_t *exclude_suffix,
const char *target_dir_prefix,
uint32_t dir_mode,
uint32_t access_mode,

View File

@ -91,6 +91,7 @@ static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
EFI_STUB_FEATURE_REPORT_BOOT_PARTITION | /* We set LoaderDevicePartUUID */
EFI_STUB_FEATURE_PICK_UP_CREDENTIALS | /* We pick up credentials from the boot partition */
EFI_STUB_FEATURE_PICK_UP_SYSEXTS | /* We pick up system extensions from the boot partition */
EFI_STUB_FEATURE_PICK_UP_CONFEXTS | /* We pick up configuration extensions from the boot partition */
EFI_STUB_FEATURE_THREE_PCRS | /* We can measure kernel image, parameters and sysext */
EFI_STUB_FEATURE_RANDOM_SEED | /* We pass a random seed to the kernel */
EFI_STUB_FEATURE_CMDLINE_ADDONS | /* We pick up .cmdline addons */
@ -497,8 +498,8 @@ static EFI_STATUS load_addons(
}
static EFI_STATUS run(EFI_HANDLE image) {
_cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL, *sysext_initrd = NULL, *pcrsig_initrd = NULL, *pcrpkey_initrd = NULL;
size_t credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0;
_cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL, *sysext_initrd = NULL, *confext_initrd = NULL, *pcrsig_initrd = NULL, *pcrpkey_initrd = NULL;
size_t credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, confext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0;
void **dt_bases_addons_global = NULL, **dt_bases_addons_uki = NULL;
char16_t **dt_filenames_addons_global = NULL, **dt_filenames_addons_uki = NULL;
_cleanup_free_ size_t *dt_sizes_addons_global = NULL, *dt_sizes_addons_uki = NULL;
@ -510,7 +511,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
_cleanup_free_ char16_t *cmdline = NULL, *cmdline_addons_global = NULL, *cmdline_addons_uki = NULL;
int sections_measured = -1, parameters_measured = -1;
_cleanup_free_ char *uname = NULL;
bool sysext_measured = false, m;
bool sysext_measured = false, confext_measured = false, m;
uint64_t loader_features = 0;
EFI_STATUS err;
@ -660,8 +661,9 @@ static EFI_STATUS run(EFI_HANDLE image) {
export_variables(loaded_image);
if (pack_cpio(loaded_image,
NULL,
/* dropin_dir= */ NULL,
u".cred",
/* exclude_suffix= */ NULL,
".extra/credentials",
/* dir_mode= */ 0500,
/* access_mode= */ 0400,
@ -675,6 +677,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
if (pack_cpio(loaded_image,
u"\\loader\\credentials",
u".cred",
/* exclude_suffix= */ NULL,
".extra/global_credentials",
/* dir_mode= */ 0500,
/* access_mode= */ 0400,
@ -686,8 +689,9 @@ static EFI_STATUS run(EFI_HANDLE image) {
parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m);
if (pack_cpio(loaded_image,
NULL,
u".raw",
/* dropin_dir= */ NULL,
u".raw", /* ideally we'd pick up only *.sysext.raw here, but for compat we pick up *.raw instead … */
u".confext.raw", /* … but then exclude *.confext.raw again */
".extra/sysext",
/* dir_mode= */ 0555,
/* access_mode= */ 0444,
@ -698,6 +702,20 @@ static EFI_STATUS run(EFI_HANDLE image) {
&m) == EFI_SUCCESS)
sysext_measured = m;
if (pack_cpio(loaded_image,
/* dropin_dir= */ NULL,
u".confext.raw",
/* exclude_suffix= */ NULL,
".extra/confext",
/* dir_mode= */ 0555,
/* access_mode= */ 0444,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Configuration extension initrd",
&confext_initrd,
&confext_initrd_size,
&m) == EFI_SUCCESS)
confext_measured = m;
dt_size = szs[UNIFIED_SECTION_DTB];
dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_DTB] : 0;
@ -728,6 +746,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
(void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrKernelParameters", TPM2_PCR_KERNEL_CONFIG, 0);
if (sysext_measured)
(void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrInitRDSysExts", TPM2_PCR_SYSEXTS, 0);
if (confext_measured)
(void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrInitRDConfExts", TPM2_PCR_KERNEL_CONFIG, 0);
/* If the PCR signature was embedded in the PE image, then let's wrap it in a cpio and also pass it
* to the kernel, so that it can be read from /.extra/tpm2-pcr-signature.json. Note that this section
@ -773,7 +793,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_INITRD] : 0;
_cleanup_pages_ Pages initrd_pages = {};
if (credential_initrd || global_credential_initrd || sysext_initrd || pcrsig_initrd || pcrpkey_initrd) {
if (credential_initrd || global_credential_initrd || sysext_initrd || confext_initrd || pcrsig_initrd || pcrpkey_initrd) {
/* If we have generated initrds dynamically, let's combine them with the built-in initrd. */
err = combine_initrd(
initrd_base, initrd_size,
@ -781,6 +801,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
credential_initrd,
global_credential_initrd,
sysext_initrd,
confext_initrd,
pcrsig_initrd,
pcrpkey_initrd,
},
@ -788,10 +809,11 @@ static EFI_STATUS run(EFI_HANDLE image) {
credential_initrd_size,
global_credential_initrd_size,
sysext_initrd_size,
confext_initrd_size,
pcrsig_initrd_size,
pcrpkey_initrd_size,
},
5,
6,
&initrd_pages, &initrd_size);
if (err != EFI_SUCCESS)
return err;
@ -802,6 +824,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
credential_initrd = mfree(credential_initrd);
global_credential_initrd = mfree(global_credential_initrd);
sysext_initrd = mfree(sysext_initrd);
confext_initrd = mfree(confext_initrd);
pcrsig_initrd = mfree(pcrsig_initrd);
pcrpkey_initrd = mfree(pcrpkey_initrd);
}

View File

@ -33,6 +33,7 @@
#define EFI_STUB_FEATURE_CMDLINE_ADDONS (UINT64_C(1) << 5)
#define EFI_STUB_FEATURE_CMDLINE_SMBIOS (UINT64_C(1) << 6)
#define EFI_STUB_FEATURE_DEVICETREE_ADDONS (UINT64_C(1) << 7)
#define EFI_STUB_FEATURE_PICK_UP_CONFEXTS (UINT64_C(1) << 8)
typedef enum SecureBootMode {
SECURE_BOOT_UNSUPPORTED,