From 41f56ba9788c24ef66a5ca99ee1a92af697670ec Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 18 Nov 2022 02:49:16 +0100 Subject: [PATCH] stub: handle random seed like sd-boot does sd-stub has an opportunity to handle the seed the same way sd-boot does, which would have benefits for UKIs when sd-boot is not in use. This commit wires that up. It refactors the XBOOTLDR partition discovery to also find the ESP partition, so that it access the random seed there. (cherry picked from commit 0a1d8ac77a21ae0741bdf4af08f3a71354805ff1) Related: RHEL-16952 --- src/boot/bootctl.c | 1 + src/boot/efi/boot.c | 4 ++-- src/boot/efi/meson.build | 8 ++++---- src/boot/efi/{xbootldr.c => part-discovery.c} | 20 ++++++++++--------- src/boot/efi/part-discovery.h | 11 ++++++++++ src/boot/efi/stub.c | 13 ++++++++++++ src/boot/efi/xbootldr.h | 9 --------- src/fundamental/efivars-fundamental.h | 1 + units/systemd-boot-system-token.service | 3 ++- 9 files changed, 45 insertions(+), 25 deletions(-) rename src/boot/efi/{xbootldr.c => part-discovery.c} (94%) create mode 100644 src/boot/efi/part-discovery.h delete mode 100644 src/boot/efi/xbootldr.h diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index d495c72bdd..c994be272b 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -1812,6 +1812,7 @@ static int verb_status(int argc, char *argv[], void *userdata) { { 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" }, }; _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/boot.c b/src/boot/efi/boot.c index 4a64c2402d..2e657a8bf9 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -15,6 +15,7 @@ #include "initrd.h" #include "linux.h" #include "measure.h" +#include "part-discovery.h" #include "pe.h" #include "vmm.h" #include "random-seed.h" @@ -22,7 +23,6 @@ #include "shim.h" #include "ticks.h" #include "util.h" -#include "xbootldr.h" #ifndef GNU_EFI_USE_MS_ABI /* We do not use uefi_call_wrapper() in systemd-boot. As such, we rely on the @@ -2239,7 +2239,7 @@ static void config_load_xbootldr( assert(config); assert(device); - err = xbootldr_open(device, &new_device, &root_dir); + err = partition_open(XBOOTLDR_GUID, device, &new_device, &root_dir); if (err != EFI_SUCCESS) return; diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 00f3361d66..8e96a33119 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -361,6 +361,7 @@ efi_headers = files( 'linux.h', 'measure.h', 'missing_efi.h', + 'part-discovery.h', 'pe.h', 'random-seed.h', 'secure-boot.h', @@ -368,7 +369,6 @@ efi_headers = files( 'splash.h', 'ticks.h', 'util.h', - 'xbootldr.h', ) common_sources = files( @@ -380,7 +380,9 @@ common_sources = files( 'graphics.c', 'initrd.c', 'measure.c', + 'part-discovery.c', 'pe.c', + 'random-seed.c', 'secure-boot.c', 'ticks.c', 'util.c', @@ -389,10 +391,8 @@ common_sources = files( systemd_boot_sources = files( 'boot.c', 'drivers.c', - 'random-seed.c', - 'vmm.c', 'shim.c', - 'xbootldr.c', + 'vmm.c', ) stub_sources = files( diff --git a/src/boot/efi/xbootldr.c b/src/boot/efi/part-discovery.c similarity index 94% rename from src/boot/efi/xbootldr.c rename to src/boot/efi/part-discovery.c index 7fef909312..14479c06ea 100644 --- a/src/boot/efi/xbootldr.c +++ b/src/boot/efi/part-discovery.c @@ -4,8 +4,8 @@ #include #include +#include "part-discovery.h" #include "util.h" -#include "xbootldr.h" union GptHeaderBuffer { EFI_PARTITION_TABLE_HEADER gpt_header; @@ -81,6 +81,7 @@ static bool verify_gpt(union GptHeaderBuffer *gpt_header_buffer, EFI_LBA lba_exp } static EFI_STATUS try_gpt( + const EFI_GUID *type, EFI_BLOCK_IO_PROTOCOL *block_io, EFI_LBA lba, EFI_LBA *ret_backup_lba, /* May be changed even on error! */ @@ -133,7 +134,7 @@ static EFI_STATUS try_gpt( EFI_PARTITION_ENTRY *entry = (EFI_PARTITION_ENTRY *) ((uint8_t *) entries + gpt.gpt_header.SizeOfPartitionEntry * i); - if (memcmp(&entry->PartitionTypeGUID, XBOOTLDR_GUID, sizeof(entry->PartitionTypeGUID)) != 0) + if (memcmp(&entry->PartitionTypeGUID, type, sizeof(entry->PartitionTypeGUID)) != 0) continue; if (entry->EndingLBA < entry->StartingLBA) /* Bogus? */ @@ -165,7 +166,7 @@ static EFI_STATUS try_gpt( return EFI_NOT_FOUND; } -static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_path) { +static EFI_STATUS find_device(const EFI_GUID *type, EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_path) { EFI_STATUS err; assert(device); @@ -235,8 +236,7 @@ static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_p continue; HARDDRIVE_DEVICE_PATH hd; - err = try_gpt( - block_io, lba, + err = try_gpt(type, block_io, lba, nr == 0 ? &backup_lba : NULL, /* Only get backup LBA location from first GPT header. */ &hd); if (err != EFI_SUCCESS) { @@ -256,17 +256,18 @@ static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_p return EFI_NOT_FOUND; } -EFI_STATUS xbootldr_open(EFI_HANDLE *device, EFI_HANDLE *ret_device, EFI_FILE **ret_root_dir) { +EFI_STATUS partition_open(const EFI_GUID *type, EFI_HANDLE *device, EFI_HANDLE *ret_device, + EFI_FILE **ret_root_dir) { _cleanup_free_ EFI_DEVICE_PATH *partition_path = NULL; EFI_HANDLE new_device; EFI_FILE *root_dir; EFI_STATUS err; + assert(type); assert(device); - assert(ret_device); assert(ret_root_dir); - err = find_device(device, &partition_path); + err = find_device(type, device, &partition_path); if (err != EFI_SUCCESS) return err; @@ -279,7 +280,8 @@ EFI_STATUS xbootldr_open(EFI_HANDLE *device, EFI_HANDLE *ret_device, EFI_FILE ** if (err != EFI_SUCCESS) return err; - *ret_device = new_device; + if (ret_device) + *ret_device = new_device; *ret_root_dir = root_dir; return EFI_SUCCESS; } diff --git a/src/boot/efi/part-discovery.h b/src/boot/efi/part-discovery.h new file mode 100644 index 0000000000..5cc17f6b3b --- /dev/null +++ b/src/boot/efi/part-discovery.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include + +#define XBOOTLDR_GUID \ + &(const EFI_GUID) { 0xbc13c2ff, 0x59e6, 0x4262, { 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72 } } +#define ESP_GUID \ + &(const EFI_GUID) { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } } + +EFI_STATUS partition_open(const EFI_GUID *type, EFI_HANDLE *device, EFI_HANDLE *ret_device, EFI_FILE **ret_root_dir); diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 7c42a16c70..023f8ae255 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -9,7 +9,9 @@ #include "graphics.h" #include "linux.h" #include "measure.h" +#include "part-discovery.h" #include "pe.h" +#include "random-seed.h" #include "secure-boot.h" #include "splash.h" #include "tpm-pcr.h" @@ -84,6 +86,7 @@ static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) { 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_THREE_PCRS | /* We can measure kernel image, parameters and sysext */ + EFI_STUB_FEATURE_RANDOM_SEED | /* We pass a random seed to the kernel */ 0; char16_t uuid[37]; @@ -188,6 +191,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { _cleanup_free_ char16_t *cmdline = NULL; int sections_measured = -1, parameters_measured = -1; bool sysext_measured = false, m; + uint64_t loader_features = 0; EFI_STATUS err; InitializeLib(image, sys_table); @@ -205,6 +209,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { if (err != EFI_SUCCESS) return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err); + if (efivar_get_uint64_le(LOADER_GUID, L"LoaderFeatures", &loader_features) != EFI_SUCCESS || + !FLAGS_SET(loader_features, EFI_LOADER_FEATURE_RANDOM_SEED)) { + _cleanup_(file_closep) EFI_FILE *esp_dir = NULL; + + err = partition_open(ESP_GUID, loaded_image->DeviceHandle, NULL, &esp_dir); + if (err == EFI_SUCCESS) /* Non-fatal on failure, so that we still boot without it. */ + (void) process_random_seed(esp_dir); + } + err = pe_memory_locate_sections(loaded_image->ImageBase, unified_sections, addrs, szs); if (err != EFI_SUCCESS || szs[UNIFIED_SECTION_LINUX] == 0) { if (err == EFI_SUCCESS) diff --git a/src/boot/efi/xbootldr.h b/src/boot/efi/xbootldr.h deleted file mode 100644 index 205ce71edf..0000000000 --- a/src/boot/efi/xbootldr.h +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include - -#define XBOOTLDR_GUID \ - &(const EFI_GUID) { 0xbc13c2ff, 0x59e6, 0x4262, { 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72 } } - -EFI_STATUS xbootldr_open(EFI_HANDLE *device, EFI_HANDLE *ret_device, EFI_FILE **ret_root_dir); diff --git a/src/fundamental/efivars-fundamental.h b/src/fundamental/efivars-fundamental.h index fe34e6c714..cf785f8b7d 100644 --- a/src/fundamental/efivars-fundamental.h +++ b/src/fundamental/efivars-fundamental.h @@ -22,6 +22,7 @@ #define EFI_STUB_FEATURE_PICK_UP_CREDENTIALS (UINT64_C(1) << 1) #define EFI_STUB_FEATURE_PICK_UP_SYSEXTS (UINT64_C(1) << 2) #define EFI_STUB_FEATURE_THREE_PCRS (UINT64_C(1) << 3) +#define EFI_STUB_FEATURE_RANDOM_SEED (UINT64_C(1) << 4) typedef enum SecureBootMode { SECURE_BOOT_UNSUPPORTED, diff --git a/units/systemd-boot-system-token.service b/units/systemd-boot-system-token.service index 689b902000..63e523bb3e 100644 --- a/units/systemd-boot-system-token.service +++ b/units/systemd-boot-system-token.service @@ -17,7 +17,8 @@ Conflicts=shutdown.target initrd-switch-root.target Before=shutdown.target initrd-switch-root.target # Only run this if the boot loader can support random seed initialization. -ConditionPathExists=/sys/firmware/efi/efivars/LoaderFeatures-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f +ConditionPathExists|=/sys/firmware/efi/efivars/LoaderFeatures-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f +ConditionPathExists|=/sys/firmware/efi/efivars/StubFeatures-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f # Only run this if there is no system token defined yet ConditionPathExists=!/sys/firmware/efi/efivars/LoaderSystemToken-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f