diff --git a/man/systemd-stub.xml b/man/systemd-stub.xml index 5b47d752ca..e489a138d6 100644 --- a/man/systemd-stub.xml +++ b/man/systemd-stub.xml @@ -32,6 +32,8 @@ ESP/.../foo.efi.extra.d/*.addon.efi ESP/.../foo.efi.extra.d/*.cred ESP/.../foo.efi.extra.d/*.raw + ESP/.../foo.efi.extra.d/*.sysext.raw + ESP/.../foo.efi.extra.d/*.confext.raw ESP/loader/addons/*.addon.efi ESP/loader/credentials/*.cred @@ -153,14 +155,28 @@ details on encrypted credentials. The generated cpio archive is measured into TPM PCR 12 (if a TPM is present). - Similarly, files foo.efi.extra.d/*.raw - are packed up in a cpio archive and placed in the /.extra/sysext/ - directory in the initrd file hierarchy. This is supposed to be used to pass additional system extension - images to the initrd. See + Similarly, files + foo.efi.extra.d/*.sysext.raw are packed up in a + cpio archive and placed in the /.extra/sysext/ directory in the + initrd file hierarchy. This is supposed to be used to pass additional system extension images to the + initrd. See systemd-sysext8 for details on system extension images. The generated cpio archive containing these system extension images is measured into TPM PCR 13 (if a TPM is present). + + + Similarly, files + foo.efi.extra.d/*.confext.raw are packed up in a + cpio archive and placed in the /.extra/confext/ directory in + the initrd file hierarchy. This is supposed to be used to pass additional configuration extension + images to the initrd. See + systemd-confext8 for + details on configuration extension images. The generated cpio archive containing + these system extension images is measured into TPM PCR 12 (if a TPM is present). + Similarly, files foo.efi.extra.d/*.addon.efi are loaded and verified as PE binaries, and a .cmdline section is parsed from them. Addons are supposed to be @@ -218,9 +234,10 @@ 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: + 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: OS Resource PCR Summary @@ -291,6 +308,11 @@ System Extensions (synthesized initrd from companion files)9 + 13 + + + Configuration Extensions (synthesized initrd from companion files) + 9 + 12 +
@@ -371,13 +393,24 @@ StubPcrInitRDSysExts - 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. + 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. 13). This variable is set if a measurement was successfully completed, and remains unset otherwise. + + + StubPcrInitRDConfExts + + 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. + 12). This variable is set if a measurement was successfully completed, and remains + unset otherwise. + + + Note that some of the variables above may also be set by the boot loader. The stub will only set @@ -422,14 +455,23 @@ - /.extra/sysext/*.raw - System extension image files (suffix .raw) that are placed next to - the unified kernel image (as described above) are copied into the + /.extra/sysext/*.sysext.raw + System extension image files (suffix .sysext.raw) that are placed + next to the unified kernel image (as described above) are copied into the /.extra/sysext/ directory in the initrd execution environment. + + /.extra/confext/*.confext.raw + Configuration extension image files (suffix .confext.raw) that are + placed next to the unified kernel image (as described above) are copied into the + /.extra/confext/ directory in the initrd execution environment. + + + + /.extra/tpm2-pcr-signature.json The TPM2 PCR signature JSON object included in the .pcrsig PE diff --git a/src/boot/bootctl-status.c b/src/boot/bootctl-status.c index c8041c4bd1..337b3eb4b5 100644 --- a/src/boot/bootctl-status.c +++ b/src/boot/bootctl-status.c @@ -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; diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c index 5b90e17c41..1408d74bb6 100644 --- a/src/boot/efi/cpio.c +++ b/src/boot/efi/cpio.c @@ -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 */ diff --git a/src/boot/efi/cpio.h b/src/boot/efi/cpio.h index 26851e3c15..9d14fa15a2 100644 --- a/src/boot/efi/cpio.h +++ b/src/boot/efi/cpio.h @@ -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, diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 7ef3e76544..58586f942f 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -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); } diff --git a/src/fundamental/efivars-fundamental.h b/src/fundamental/efivars-fundamental.h index 2d25d2248f..01b18ec241 100644 --- a/src/fundamental/efivars-fundamental.h +++ b/src/fundamental/efivars-fundamental.h @@ -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,