303 lines
12 KiB
Diff
303 lines
12 KiB
Diff
From 41f56ba9788c24ef66a5ca99ee1a92af697670ec Mon Sep 17 00:00:00 2001
|
|
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
|
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 <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);
|
|
@@ -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 <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);
|
|
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 <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);
|
|
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
|