]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stub: handle random seed like sd-boot does
authorJason A. Donenfeld <Jason@zx2c4.com>
Fri, 18 Nov 2022 01:49:16 +0000 (02:49 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 22 Nov 2022 23:56:45 +0000 (00:56 +0100)
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.

TODO
src/boot/bootctl.c
src/boot/efi/boot.c
src/boot/efi/meson.build
src/boot/efi/part-discovery.c [moved from src/boot/efi/xbootldr.c with 94% similarity]
src/boot/efi/part-discovery.h [new file with mode: 0644]
src/boot/efi/stub.c
src/boot/efi/xbootldr.h [deleted file]
src/fundamental/efivars-fundamental.h
units/systemd-boot-system-token.service

diff --git a/TODO b/TODO
index 6ad4778ddc9e8d634985dfded63bec3f90789dc1..8416dbcbbb089f1d115b9ea3ee3a88de11b3f40a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -146,8 +146,6 @@ Features:
 
 * bootctl: warn if ESP is mounted world-readable (and in particular the seed).
 
-* sd-stub: call process_random_seed() the same way sd-boot does.
-
 * maybe: systemd-loop-generator that sets up loopback devices if requested via kernel
   cmdline. usecase: include encrypted/verity root fs in UKI.
 
index 1e862018d43327e4c67845ec046701cde966bb10..0df456827c1977763ddafbf366a947386c0ff06e 100644 (file)
@@ -1808,6 +1808,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;
index caa2a69a6f48836c39b09bb5e333161381b19d2e..85e936b866d9488b8f06a44fcfe1c85a9f49d78f 100644 (file)
@@ -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
@@ -2241,7 +2241,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;
 
index 0de43993a4155f521476fd7797f32be6e996f231..2a7e457df33d7afa8ffd64e6604241a929818696 100644 (file)
@@ -360,6 +360,7 @@ efi_headers = files(
         'linux.h',
         'measure.h',
         'missing_efi.h',
+        'part-discovery.h',
         'pe.h',
         'random-seed.h',
         'secure-boot.h',
@@ -367,7 +368,6 @@ efi_headers = files(
         'splash.h',
         'ticks.h',
         'util.h',
-        'xbootldr.h',
 )
 
 common_sources = files(
@@ -379,7 +379,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',
@@ -388,10 +390,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(
similarity index 94%
rename from src/boot/efi/xbootldr.c
rename to src/boot/efi/part-discovery.c
index e5b9ca726848195f8b206475e447c29f263bd6fe..de6d6112a13280cc1d24c7db64f5e071c9ee6cb8 100644 (file)
@@ -4,8 +4,8 @@
 #include <efigpt.h>
 #include <efilib.h>
 
+#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);
@@ -231,8 +232,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) {
@@ -252,17 +252,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;
 
@@ -275,7 +276,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 (file)
index 0000000..5cc17f6
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <efi.h>
+
+#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);
index a842c5c6791fd279acab97b66154657a658825eb..6ece3cf7334cb0c4aaf7ac3927d01de3ad9e83f1 100644 (file)
@@ -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];
@@ -142,6 +145,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         _cleanup_free_ char *cmdline_owned = 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);
@@ -159,6 +163,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 (file)
index 205ce71..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include <efi.h>
-
-#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);
index fe34e6c714a10dd7ba8addcf8e71befaba9ae2a6..cf785f8b7de20102f984265337e6c9989f0566bc 100644 (file)
@@ -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,
index 689b902000582f6d75868d70e694f535204b0bf4..63e523bb3e8068ad60d9c2819622dc98cda5aa1c 100644 (file)
@@ -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