systemd-252-28
Resolves: RHEL-1086,RHEL-16952
This commit is contained in:
parent
e5f65c3fc6
commit
bed495948c
47
0653-random-seed-shorten-a-bit-may_credit.patch
Normal file
47
0653-random-seed-shorten-a-bit-may_credit.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From b433a32f0d4328afc7a3dddb7dbab82d206663f7 Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Wed, 19 Oct 2022 15:27:04 +0200
|
||||
Subject: [PATCH] random-seed: shorten a bit may_credit()
|
||||
|
||||
No functional change.
|
||||
|
||||
(cherry picked from commit 249d31b00a42aa016639bc0e9d708803d26f8f8f)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 19 ++++++++-----------
|
||||
1 file changed, 8 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 82c29d0d7f..569b916f4a 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -87,20 +87,17 @@ static CreditEntropy may_credit(int seed_fd) {
|
||||
/* Don't credit the random seed if we are in first-boot mode, because we are supposed to start from
|
||||
* scratch. This is a safety precaution for cases where we people ship "golden" images with empty
|
||||
* /etc but populated /var that contains a random seed. */
|
||||
- if (access("/run/systemd/first-boot", F_OK) < 0) {
|
||||
-
|
||||
- if (errno != ENOENT) {
|
||||
- log_warning_errno(errno, "Failed to check whether we are in first-boot mode, not crediting entropy: %m");
|
||||
- return CREDIT_ENTROPY_NO_WAY;
|
||||
- }
|
||||
-
|
||||
- /* If ENOENT all is good, we are not in first-boot mode. */
|
||||
- } else {
|
||||
- log_debug("Not crediting entropy, since booted in first-boot mode.");
|
||||
+ r = RET_NERRNO(access("/run/systemd/first-boot", F_OK));
|
||||
+ if (r == -ENOENT)
|
||||
+ /* All is good, we are not in first-boot mode. */
|
||||
+ return CREDIT_ENTROPY_YES_PLEASE;
|
||||
+ if (r < 0) {
|
||||
+ log_warning_errno(r, "Failed to check whether we are in first-boot mode, not crediting entropy: %m");
|
||||
return CREDIT_ENTROPY_NO_WAY;
|
||||
}
|
||||
|
||||
- return CREDIT_ENTROPY_YES_PLEASE;
|
||||
+ log_debug("Not crediting entropy, since booted in first-boot mode.");
|
||||
+ return CREDIT_ENTROPY_NO_WAY;
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
@ -0,0 +1,27 @@
|
||||
From b8859311bceb0cd63a64c2fcc8967f0c6466d736 Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Wed, 19 Oct 2022 15:28:27 +0200
|
||||
Subject: [PATCH] random-seed: make one more use of random_write_entropy()
|
||||
|
||||
No functional change.
|
||||
|
||||
(cherry picked from commit 141d1da021514be2cc7e7a903fa83b11f6054db6)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 569b916f4a..d94005bdde 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -197,7 +197,7 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to get machine ID, ignoring: %m");
|
||||
else {
|
||||
- r = loop_write(random_fd, &mid, sizeof(mid), false);
|
||||
+ r = random_write_entropy(random_fd, &mid, sizeof(mid), /* credit= */ false);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to write machine ID to /dev/urandom, ignoring: %m");
|
||||
}
|
207
0655-random-seed-use-getopt.patch
Normal file
207
0655-random-seed-use-getopt.patch
Normal file
@ -0,0 +1,207 @@
|
||||
From f6b55583600b4f8bfa2e7883d60685e2fb6c6b9d Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Wed, 19 Oct 2022 15:49:24 +0200
|
||||
Subject: [PATCH] random-seed: use getopt()
|
||||
|
||||
It's not really necessary since systemd-random-seed is an internal tool for the
|
||||
moment but this might change in future (to allow system installers to
|
||||
initialize a random seed file for example).
|
||||
|
||||
Also introducing new options will be easier.
|
||||
|
||||
(cherry picked from commit 0d0c6639d4d61ff6cee43bc059c56a5170a0d280)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 116 ++++++++++++++++++++++++++++++----
|
||||
1 file changed, 103 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index d94005bdde..2ca2181ddb 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
+#include <getopt.h>
|
||||
#include <linux/random.h>
|
||||
#include <sys/ioctl.h>
|
||||
#if USE_SYS_RANDOM_H
|
||||
@@ -22,20 +23,34 @@
|
||||
#include "missing_random.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mkdir.h"
|
||||
+#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
+#include "pretty-print.h"
|
||||
#include "random-util.h"
|
||||
+#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
+#include "strv.h"
|
||||
#include "sync-util.h"
|
||||
#include "sha256.h"
|
||||
+#include "terminal-util.h"
|
||||
#include "util.h"
|
||||
#include "xattr-util.h"
|
||||
|
||||
+typedef enum SeedAction {
|
||||
+ ACTION_LOAD,
|
||||
+ ACTION_SAVE,
|
||||
+ _ACTION_MAX,
|
||||
+ _ACTION_INVALID = -EINVAL,
|
||||
+} SeedAction;
|
||||
+
|
||||
typedef enum CreditEntropy {
|
||||
CREDIT_ENTROPY_NO_WAY,
|
||||
CREDIT_ENTROPY_YES_PLEASE,
|
||||
CREDIT_ENTROPY_YES_FORCED,
|
||||
} CreditEntropy;
|
||||
|
||||
+static SeedAction arg_action = _ACTION_INVALID;
|
||||
+
|
||||
static CreditEntropy may_credit(int seed_fd) {
|
||||
_cleanup_free_ char *creditable = NULL;
|
||||
const char *e;
|
||||
@@ -100,6 +115,78 @@ static CreditEntropy may_credit(int seed_fd) {
|
||||
return CREDIT_ENTROPY_NO_WAY;
|
||||
}
|
||||
|
||||
+static int help(int argc, char *argv[], void *userdata) {
|
||||
+ _cleanup_free_ char *link = NULL;
|
||||
+ int r;
|
||||
+
|
||||
+ r = terminal_urlify_man("systemd-random-seed", "8", &link);
|
||||
+ if (r < 0)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ printf("%1$s [OPTIONS...] COMMAND\n"
|
||||
+ "\n%5$sLoad and save the system random seed at boot and shutdown.%6$s\n"
|
||||
+ "\n%3$sCommands:%4$s\n"
|
||||
+ " load Load a random seed saved on disk into the kernel entropy pool\n"
|
||||
+ " save Save a new random seed on disk\n"
|
||||
+ "\n%3$sOptions:%4$s\n"
|
||||
+ " -h --help Show this help\n"
|
||||
+ " --version Show package version\n"
|
||||
+ "\nSee the %2$s for details.\n",
|
||||
+ program_invocation_short_name,
|
||||
+ link,
|
||||
+ ansi_underline(),
|
||||
+ ansi_normal(),
|
||||
+ ansi_highlight(),
|
||||
+ ansi_normal());
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const char* const seed_action_table[_ACTION_MAX] = {
|
||||
+ [ACTION_LOAD] = "load",
|
||||
+ [ACTION_SAVE] = "save",
|
||||
+};
|
||||
+
|
||||
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(seed_action, SeedAction);
|
||||
+
|
||||
+static int parse_argv(int argc, char *argv[]) {
|
||||
+ enum {
|
||||
+ ARG_VERSION = 0x100,
|
||||
+ };
|
||||
+
|
||||
+ static const struct option options[] = {
|
||||
+ { "help", no_argument, NULL, 'h' },
|
||||
+ { "version", no_argument, NULL, ARG_VERSION },
|
||||
+ };
|
||||
+
|
||||
+ int c;
|
||||
+
|
||||
+ assert(argc >= 0);
|
||||
+ assert(argv);
|
||||
+
|
||||
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
|
||||
+ switch (c) {
|
||||
+ case 'h':
|
||||
+ return help(0, NULL, NULL);
|
||||
+ case ARG_VERSION:
|
||||
+ return version();
|
||||
+ case '?':
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ default:
|
||||
+ assert_not_reached();
|
||||
+ }
|
||||
+
|
||||
+ if (optind + 1 != argc)
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires one argument.");
|
||||
+
|
||||
+ arg_action = seed_action_from_string(argv[optind]);
|
||||
+ if (arg_action < 0)
|
||||
+ return log_error_errno(arg_action, "Unknown action '%s'", argv[optind]);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int run(int argc, char *argv[]) {
|
||||
bool read_seed_file, write_seed_file, synchronous, hashed_old_seed = false;
|
||||
_cleanup_close_ int seed_fd = -1, random_fd = -1;
|
||||
@@ -112,9 +199,9 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
log_setup();
|
||||
|
||||
- if (argc != 2)
|
||||
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
- "This program requires one argument.");
|
||||
+ r = parse_argv(argc, argv);
|
||||
+ if (r <= 0)
|
||||
+ return r;
|
||||
|
||||
umask(0022);
|
||||
|
||||
@@ -124,11 +211,11 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m");
|
||||
|
||||
- /* When we load the seed we read it and write it to the device and then immediately update the saved seed with
|
||||
- * new data, to make sure the next boot gets seeded differently. */
|
||||
-
|
||||
- if (streq(argv[1], "load")) {
|
||||
+ /* When we load the seed we read it and write it to the device and then immediately update the saved
|
||||
+ * seed with new data, to make sure the next boot gets seeded differently. */
|
||||
|
||||
+ switch (arg_action) {
|
||||
+ case ACTION_LOAD:
|
||||
seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
|
||||
if (seed_fd < 0) {
|
||||
int open_rw_error = -errno;
|
||||
@@ -154,9 +241,9 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
read_seed_file = true;
|
||||
synchronous = true; /* make this invocation a synchronous barrier for random pool initialization */
|
||||
+ break;
|
||||
|
||||
- } else if (streq(argv[1], "save")) {
|
||||
-
|
||||
+ case ACTION_SAVE:
|
||||
random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (random_fd < 0)
|
||||
return log_error_errno(errno, "Failed to open /dev/urandom: %m");
|
||||
@@ -168,14 +255,17 @@ static int run(int argc, char *argv[]) {
|
||||
read_seed_file = false;
|
||||
write_seed_file = true;
|
||||
synchronous = false;
|
||||
- } else
|
||||
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
- "Unknown verb '%s'.", argv[1]);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ assert_not_reached();
|
||||
+ }
|
||||
|
||||
if (fstat(seed_fd, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat() seed file " RANDOM_SEED ": %m");
|
||||
|
||||
- /* If the seed file is larger than what we expect, then honour the existing size and save/restore as much as it says */
|
||||
+ /* If the seed file is larger than what we expect, then honour the existing size and save/restore as
|
||||
+ * much as it says */
|
||||
if ((uint64_t) st.st_size > buf_size)
|
||||
buf_size = MIN(st.st_size, RANDOM_POOL_SIZE_MAX);
|
||||
|
@ -0,0 +1,79 @@
|
||||
From b16d2d2da2d84552cfe7437d728ab8d65bacb03c Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Thu, 20 Oct 2022 08:45:02 +0200
|
||||
Subject: [PATCH] random-seed: make the logic to calculate the number of bytes
|
||||
read from the random seed file clearer
|
||||
|
||||
We want the size to lie within [/proc/sys/kernel/random/poolsize,RANDOM_POOL_SIZE_MAX]
|
||||
interval. Let's make it more obvious.
|
||||
|
||||
Also move the logic in a dedicated function.
|
||||
|
||||
(cherry picked from commit 205138d88abf2e087440803ee046128092b722c6)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 29 +++++++++++++++++++----------
|
||||
1 file changed, 19 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 2ca2181ddb..5b5629d817 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -115,6 +115,22 @@ static CreditEntropy may_credit(int seed_fd) {
|
||||
return CREDIT_ENTROPY_NO_WAY;
|
||||
}
|
||||
|
||||
+static int random_seed_size(int seed_fd, size_t *ret_size) {
|
||||
+ struct stat st;
|
||||
+
|
||||
+ assert(ret_size);
|
||||
+ assert(seed_fd >= 0);
|
||||
+
|
||||
+ if (fstat(seed_fd, &st) < 0)
|
||||
+ return log_error_errno(errno, "Failed to stat() seed file " RANDOM_SEED ": %m");
|
||||
+
|
||||
+ /* If the seed file is larger than what the kernel expects, then honour the existing size and
|
||||
+ * save/restore as much as it says */
|
||||
+
|
||||
+ *ret_size = CLAMP((uint64_t)st.st_size, random_pool_size(), RANDOM_POOL_SIZE_MAX);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int help(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
@@ -193,7 +209,6 @@ static int run(int argc, char *argv[]) {
|
||||
_cleanup_free_ void* buf = NULL;
|
||||
struct sha256_ctx hash_state;
|
||||
size_t buf_size;
|
||||
- struct stat st;
|
||||
ssize_t k, l;
|
||||
int r;
|
||||
|
||||
@@ -205,8 +220,6 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
umask(0022);
|
||||
|
||||
- buf_size = random_pool_size();
|
||||
-
|
||||
r = mkdir_parents(RANDOM_SEED, 0755);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m");
|
||||
@@ -261,13 +274,9 @@ static int run(int argc, char *argv[]) {
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
- if (fstat(seed_fd, &st) < 0)
|
||||
- return log_error_errno(errno, "Failed to stat() seed file " RANDOM_SEED ": %m");
|
||||
-
|
||||
- /* If the seed file is larger than what we expect, then honour the existing size and save/restore as
|
||||
- * much as it says */
|
||||
- if ((uint64_t) st.st_size > buf_size)
|
||||
- buf_size = MIN(st.st_size, RANDOM_POOL_SIZE_MAX);
|
||||
+ r = random_seed_size(seed_fd, &buf_size);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
|
||||
buf = malloc(buf_size);
|
||||
if (!buf)
|
@ -0,0 +1,30 @@
|
||||
From 494ebc9dc491ab378851ee75562796b32e9a98ea Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Thu, 20 Oct 2022 08:52:10 +0200
|
||||
Subject: [PATCH] random-seed: no need to pass 'mode' argument when opening
|
||||
/dev/urandom
|
||||
|
||||
The open() call is not supposed to create /dev/urandom.
|
||||
|
||||
No functional change.
|
||||
|
||||
(cherry picked from commit 4620c0af5dc7a46ed3e213568e99d8a82c44553d)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 5b5629d817..4b8138ca03 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -248,7 +248,7 @@ static int run(int argc, char *argv[]) {
|
||||
} else
|
||||
write_seed_file = true;
|
||||
|
||||
- random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
|
||||
+ random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY);
|
||||
if (random_fd < 0)
|
||||
return log_error_errno(errno, "Failed to open /dev/urandom: %m");
|
||||
|
372
0658-random-seed-split-out-run.patch
Normal file
372
0658-random-seed-split-out-run.patch
Normal file
@ -0,0 +1,372 @@
|
||||
From d424c00790f478790be7388827113853b968023e Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Thu, 20 Oct 2022 09:39:12 +0200
|
||||
Subject: [PATCH] random-seed: split out run()
|
||||
|
||||
No functional change.
|
||||
|
||||
(cherry picked from commit d3fa881aa1f4bffc097d63ed68d2e2a8ada813d0)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 327 +++++++++++++++++++---------------
|
||||
1 file changed, 184 insertions(+), 143 deletions(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 4b8138ca03..991e4b8ddd 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -131,6 +131,180 @@ static int random_seed_size(int seed_fd, size_t *ret_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int load_seed_file(
|
||||
+ int seed_fd,
|
||||
+ int urandom_fd,
|
||||
+ size_t seed_size,
|
||||
+ struct sha256_ctx **ret_hash_state) {
|
||||
+
|
||||
+ _cleanup_free_ void *buf = NULL;
|
||||
+ CreditEntropy lets_credit;
|
||||
+ sd_id128_t mid;
|
||||
+ ssize_t k;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(seed_fd >= 0);
|
||||
+ assert(urandom_fd >= 0);
|
||||
+
|
||||
+ /* First, let's write the machine ID into /dev/urandom, not crediting entropy. Why? As an extra
|
||||
+ * protection against "golden images" that are put together sloppily, i.e. images which are
|
||||
+ * duplicated on multiple systems but where the random seed file is not properly reset. Frequently
|
||||
+ * the machine ID is properly reset on those systems however (simply because it's easier to notice,
|
||||
+ * if it isn't due to address clashes and so on, while random seed equivalence is generally not
|
||||
+ * noticed easily), hence let's simply write the machined ID into the random pool too. */
|
||||
+ r = sd_id128_get_machine(&mid);
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to get machine ID, ignoring: %m");
|
||||
+ else {
|
||||
+ r = random_write_entropy(urandom_fd, &mid, sizeof(mid), /* credit= */ false);
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to write machine ID to /dev/urandom, ignoring: %m");
|
||||
+ }
|
||||
+
|
||||
+ buf = malloc(seed_size);
|
||||
+ if (!buf)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ k = loop_read(seed_fd, buf, seed_size, false);
|
||||
+ if (k < 0) {
|
||||
+ log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (k == 0) {
|
||||
+ log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* If we're going to later write out a seed file, initialize a hash state with the contents of the
|
||||
+ * seed file we just read, so that the new one can't regress in entropy. */
|
||||
+ if (ret_hash_state) {
|
||||
+ struct sha256_ctx *hash_state;
|
||||
+
|
||||
+ hash_state = malloc(sizeof(struct sha256_ctx));
|
||||
+ if (!hash_state)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ sha256_init_ctx(hash_state);
|
||||
+ sha256_process_bytes(&k, sizeof(k), hash_state); /* Hash length to distinguish from new seed. */
|
||||
+ sha256_process_bytes(buf, k, hash_state);
|
||||
+
|
||||
+ *ret_hash_state = hash_state;
|
||||
+ }
|
||||
+
|
||||
+ (void) lseek(seed_fd, 0, SEEK_SET);
|
||||
+
|
||||
+ lets_credit = may_credit(seed_fd);
|
||||
+
|
||||
+ /* Before we credit or use the entropy, let's make sure to securely drop the creditable xattr from
|
||||
+ * the file, so that we never credit the same random seed again. Note that further down we'll write a
|
||||
+ * new seed again, and likely mark it as credible again, hence this is just paranoia to close the
|
||||
+ * short time window between the time we upload the random seed into the kernel and download the new
|
||||
+ * one from it. */
|
||||
+
|
||||
+ if (fremovexattr(seed_fd, "user.random-seed-creditable") < 0) {
|
||||
+ if (!ERRNO_IS_XATTR_ABSENT(errno))
|
||||
+ log_warning_errno(errno, "Failed to remove extended attribute, ignoring: %m");
|
||||
+
|
||||
+ /* Otherwise, there was no creditable flag set, which is OK. */
|
||||
+ } else {
|
||||
+ r = fsync_full(seed_fd);
|
||||
+ if (r < 0) {
|
||||
+ log_warning_errno(r, "Failed to synchronize seed to disk, not crediting entropy: %m");
|
||||
+
|
||||
+ if (lets_credit == CREDIT_ENTROPY_YES_PLEASE)
|
||||
+ lets_credit = CREDIT_ENTROPY_NO_WAY;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ r = random_write_entropy(urandom_fd, buf, k,
|
||||
+ IN_SET(lets_credit, CREDIT_ENTROPY_YES_PLEASE, CREDIT_ENTROPY_YES_FORCED));
|
||||
+ if (r < 0)
|
||||
+ log_error_errno(r, "Failed to write seed to /dev/urandom: %m");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int save_seed_file(
|
||||
+ int seed_fd,
|
||||
+ int urandom_fd,
|
||||
+ size_t seed_size,
|
||||
+ bool synchronous,
|
||||
+ struct sha256_ctx *hash_state) {
|
||||
+
|
||||
+ _cleanup_free_ void *buf = NULL;
|
||||
+ bool getrandom_worked = false;
|
||||
+ ssize_t k, l;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(seed_fd >= 0);
|
||||
+ assert(urandom_fd >= 0);
|
||||
+
|
||||
+ /* This is just a safety measure. Given that we are root and most likely created the file ourselves
|
||||
+ * the mode and owner should be correct anyway. */
|
||||
+ r = fchmod_and_chown(seed_fd, 0600, 0, 0);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to adjust seed file ownership and access mode: %m");
|
||||
+
|
||||
+ buf = malloc(seed_size);
|
||||
+ if (!buf)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ /* Let's make this whole job asynchronous, i.e. let's make ourselves a barrier for proper
|
||||
+ * initialization of the random pool. */
|
||||
+ k = getrandom(buf, seed_size, GRND_NONBLOCK);
|
||||
+ if (k < 0 && errno == EAGAIN && synchronous) {
|
||||
+ log_notice("Kernel entropy pool is not initialized yet, waiting until it is.");
|
||||
+ k = getrandom(buf, seed_size, 0); /* retry synchronously */
|
||||
+ }
|
||||
+ if (k < 0)
|
||||
+ log_debug_errno(errno, "Failed to read random data with getrandom(), falling back to /dev/urandom: %m");
|
||||
+ else if ((size_t) k < seed_size)
|
||||
+ log_debug("Short read from getrandom(), falling back to /dev/urandom.");
|
||||
+ else
|
||||
+ getrandom_worked = true;
|
||||
+
|
||||
+ if (!getrandom_worked) {
|
||||
+ /* Retry with classic /dev/urandom */
|
||||
+ k = loop_read(urandom_fd, buf, seed_size, false);
|
||||
+ if (k < 0)
|
||||
+ return log_error_errno(k, "Failed to read new seed from /dev/urandom: %m");
|
||||
+ if (k == 0)
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Got EOF while reading from /dev/urandom.");
|
||||
+ }
|
||||
+
|
||||
+ /* If we previously read in a seed file, then hash the new seed into the old one, and replace the
|
||||
+ * last 32 bytes of the seed with the hash output, so that the new seed file can't regress in
|
||||
+ * entropy. */
|
||||
+ if (hash_state) {
|
||||
+ uint8_t hash[SHA256_DIGEST_SIZE];
|
||||
+
|
||||
+ sha256_process_bytes(&k, sizeof(k), hash_state); /* Hash length to distinguish from old seed. */
|
||||
+ sha256_process_bytes(buf, k, hash_state);
|
||||
+ sha256_finish_ctx(hash_state, hash);
|
||||
+ l = MIN((size_t)k, sizeof(hash));
|
||||
+ memcpy((uint8_t *)buf + k - l, hash, l);
|
||||
+ }
|
||||
+
|
||||
+ r = loop_write(seed_fd, buf, (size_t) k, false);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to write new random seed file: %m");
|
||||
+
|
||||
+ if (ftruncate(seed_fd, k) < 0)
|
||||
+ return log_error_errno(r, "Failed to truncate random seed file: %m");
|
||||
+
|
||||
+ r = fsync_full(seed_fd);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to synchronize seed file: %m");
|
||||
+
|
||||
+ /* If we got this random seed data from getrandom() the data is suitable for crediting entropy later
|
||||
+ * on. Let's keep that in mind by setting an extended attribute. on the file */
|
||||
+ if (getrandom_worked)
|
||||
+ if (fsetxattr(seed_fd, "user.random-seed-creditable", "1", 1, 0) < 0)
|
||||
+ log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno,
|
||||
+ "Failed to mark seed file as creditable, ignoring: %m");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int help(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
@@ -204,12 +378,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
- bool read_seed_file, write_seed_file, synchronous, hashed_old_seed = false;
|
||||
+ _cleanup_free_ struct sha256_ctx *hash_state = NULL;
|
||||
_cleanup_close_ int seed_fd = -1, random_fd = -1;
|
||||
- _cleanup_free_ void* buf = NULL;
|
||||
- struct sha256_ctx hash_state;
|
||||
- size_t buf_size;
|
||||
- ssize_t k, l;
|
||||
+ bool read_seed_file, write_seed_file, synchronous;
|
||||
+ size_t seed_size;
|
||||
int r;
|
||||
|
||||
log_setup();
|
||||
@@ -274,149 +446,18 @@ static int run(int argc, char *argv[]) {
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
- r = random_seed_size(seed_fd, &buf_size);
|
||||
+ r = random_seed_size(seed_fd, &seed_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- buf = malloc(buf_size);
|
||||
- if (!buf)
|
||||
- return log_oom();
|
||||
-
|
||||
- if (read_seed_file) {
|
||||
- sd_id128_t mid;
|
||||
-
|
||||
- /* First, let's write the machine ID into /dev/urandom, not crediting entropy. Why? As an
|
||||
- * extra protection against "golden images" that are put together sloppily, i.e. images which
|
||||
- * are duplicated on multiple systems but where the random seed file is not properly
|
||||
- * reset. Frequently the machine ID is properly reset on those systems however (simply
|
||||
- * because it's easier to notice, if it isn't due to address clashes and so on, while random
|
||||
- * seed equivalence is generally not noticed easily), hence let's simply write the machined
|
||||
- * ID into the random pool too. */
|
||||
- r = sd_id128_get_machine(&mid);
|
||||
- if (r < 0)
|
||||
- log_debug_errno(r, "Failed to get machine ID, ignoring: %m");
|
||||
- else {
|
||||
- r = random_write_entropy(random_fd, &mid, sizeof(mid), /* credit= */ false);
|
||||
- if (r < 0)
|
||||
- log_debug_errno(r, "Failed to write machine ID to /dev/urandom, ignoring: %m");
|
||||
- }
|
||||
-
|
||||
- k = loop_read(seed_fd, buf, buf_size, false);
|
||||
- if (k < 0)
|
||||
- log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m");
|
||||
- else if (k == 0)
|
||||
- log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding.");
|
||||
- else {
|
||||
- CreditEntropy lets_credit;
|
||||
-
|
||||
- /* If we're going to later write out a seed file, initialize a hash state with
|
||||
- * the contents of the seed file we just read, so that the new one can't regress
|
||||
- * in entropy. */
|
||||
- if (write_seed_file) {
|
||||
- sha256_init_ctx(&hash_state);
|
||||
- sha256_process_bytes(&k, sizeof(k), &hash_state); /* Hash length to distinguish from new seed. */
|
||||
- sha256_process_bytes(buf, k, &hash_state);
|
||||
- hashed_old_seed = true;
|
||||
- }
|
||||
-
|
||||
- (void) lseek(seed_fd, 0, SEEK_SET);
|
||||
-
|
||||
- lets_credit = may_credit(seed_fd);
|
||||
-
|
||||
- /* Before we credit or use the entropy, let's make sure to securely drop the
|
||||
- * creditable xattr from the file, so that we never credit the same random seed
|
||||
- * again. Note that further down we'll write a new seed again, and likely mark it as
|
||||
- * credible again, hence this is just paranoia to close the short time window between
|
||||
- * the time we upload the random seed into the kernel and download the new one from
|
||||
- * it. */
|
||||
-
|
||||
- if (fremovexattr(seed_fd, "user.random-seed-creditable") < 0) {
|
||||
- if (!ERRNO_IS_XATTR_ABSENT(errno))
|
||||
- log_warning_errno(errno, "Failed to remove extended attribute, ignoring: %m");
|
||||
+ if (read_seed_file)
|
||||
+ r = load_seed_file(seed_fd, random_fd, seed_size,
|
||||
+ write_seed_file ? &hash_state : NULL);
|
||||
|
||||
- /* Otherwise, there was no creditable flag set, which is OK. */
|
||||
- } else {
|
||||
- r = fsync_full(seed_fd);
|
||||
- if (r < 0) {
|
||||
- log_warning_errno(r, "Failed to synchronize seed to disk, not crediting entropy: %m");
|
||||
+ if (r >= 0 && write_seed_file)
|
||||
+ r = save_seed_file(seed_fd, random_fd, seed_size, synchronous, hash_state);
|
||||
|
||||
- if (lets_credit == CREDIT_ENTROPY_YES_PLEASE)
|
||||
- lets_credit = CREDIT_ENTROPY_NO_WAY;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- r = random_write_entropy(random_fd, buf, k,
|
||||
- IN_SET(lets_credit, CREDIT_ENTROPY_YES_PLEASE, CREDIT_ENTROPY_YES_FORCED));
|
||||
- if (r < 0)
|
||||
- log_error_errno(r, "Failed to write seed to /dev/urandom: %m");
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (write_seed_file) {
|
||||
- bool getrandom_worked = false;
|
||||
-
|
||||
- /* This is just a safety measure. Given that we are root and most likely created the file
|
||||
- * ourselves the mode and owner should be correct anyway. */
|
||||
- r = fchmod_and_chown(seed_fd, 0600, 0, 0);
|
||||
- if (r < 0)
|
||||
- return log_error_errno(r, "Failed to adjust seed file ownership and access mode: %m");
|
||||
-
|
||||
- /* Let's make this whole job asynchronous, i.e. let's make ourselves a barrier for
|
||||
- * proper initialization of the random pool. */
|
||||
- k = getrandom(buf, buf_size, GRND_NONBLOCK);
|
||||
- if (k < 0 && errno == EAGAIN && synchronous) {
|
||||
- log_notice("Kernel entropy pool is not initialized yet, waiting until it is.");
|
||||
- k = getrandom(buf, buf_size, 0); /* retry synchronously */
|
||||
- }
|
||||
- if (k < 0)
|
||||
- log_debug_errno(errno, "Failed to read random data with getrandom(), falling back to /dev/urandom: %m");
|
||||
- else if ((size_t) k < buf_size)
|
||||
- log_debug("Short read from getrandom(), falling back to /dev/urandom.");
|
||||
- else
|
||||
- getrandom_worked = true;
|
||||
-
|
||||
- if (!getrandom_worked) {
|
||||
- /* Retry with classic /dev/urandom */
|
||||
- k = loop_read(random_fd, buf, buf_size, false);
|
||||
- if (k < 0)
|
||||
- return log_error_errno(k, "Failed to read new seed from /dev/urandom: %m");
|
||||
- if (k == 0)
|
||||
- return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
- "Got EOF while reading from /dev/urandom.");
|
||||
- }
|
||||
-
|
||||
- /* If we previously read in a seed file, then hash the new seed into the old one,
|
||||
- * and replace the last 32 bytes of the seed with the hash output, so that the
|
||||
- * new seed file can't regress in entropy. */
|
||||
- if (hashed_old_seed) {
|
||||
- uint8_t hash[SHA256_DIGEST_SIZE];
|
||||
- sha256_process_bytes(&k, sizeof(k), &hash_state); /* Hash length to distinguish from old seed. */
|
||||
- sha256_process_bytes(buf, k, &hash_state);
|
||||
- sha256_finish_ctx(&hash_state, hash);
|
||||
- l = MIN((size_t)k, sizeof(hash));
|
||||
- memcpy((uint8_t *)buf + k - l, hash, l);
|
||||
- }
|
||||
-
|
||||
- r = loop_write(seed_fd, buf, (size_t) k, false);
|
||||
- if (r < 0)
|
||||
- return log_error_errno(r, "Failed to write new random seed file: %m");
|
||||
-
|
||||
- if (ftruncate(seed_fd, k) < 0)
|
||||
- return log_error_errno(r, "Failed to truncate random seed file: %m");
|
||||
-
|
||||
- r = fsync_full(seed_fd);
|
||||
- if (r < 0)
|
||||
- return log_error_errno(r, "Failed to synchronize seed file: %m");
|
||||
-
|
||||
- /* If we got this random seed data from getrandom() the data is suitable for crediting
|
||||
- * entropy later on. Let's keep that in mind by setting an extended attribute. on the file */
|
||||
- if (getrandom_worked)
|
||||
- if (fsetxattr(seed_fd, "user.random-seed-creditable", "1", 1, 0) < 0)
|
||||
- log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno,
|
||||
- "Failed to mark seed file as creditable, ignoring: %m");
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
+ return r;
|
||||
}
|
||||
|
||||
DEFINE_MAIN_FUNCTION(run);
|
34
0659-random_seed-minor-improvement-in-run.patch
Normal file
34
0659-random_seed-minor-improvement-in-run.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From 20eeade12a2e914d9b5451dbb1f8807cd6719eac Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Thu, 20 Oct 2022 15:03:20 +0200
|
||||
Subject: [PATCH] random_seed: minor improvement in run()
|
||||
|
||||
(cherry picked from commit 3f6fbfe6f1ae62b080c70dad6de5a65108e3d538)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 991e4b8ddd..05fb5bb157 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -410,12 +410,12 @@ static int run(int argc, char *argv[]) {
|
||||
seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (seed_fd < 0) {
|
||||
bool missing = errno == ENOENT;
|
||||
+ int level = missing ? LOG_DEBUG : LOG_ERR;
|
||||
|
||||
- log_full_errno(missing ? LOG_DEBUG : LOG_ERR,
|
||||
- open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m");
|
||||
- r = log_full_errno(missing ? LOG_DEBUG : LOG_ERR,
|
||||
- errno, "Failed to open " RANDOM_SEED " for reading: %m");
|
||||
- return missing ? 0 : r;
|
||||
+ log_full_errno(level, open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m");
|
||||
+ log_full_errno(level, errno, "Failed to open " RANDOM_SEED " for reading: %m");
|
||||
+
|
||||
+ return missing ? 0 : -errno;
|
||||
}
|
||||
} else
|
||||
write_seed_file = true;
|
37
0660-random-seed-downgrade-some-messages.patch
Normal file
37
0660-random-seed-downgrade-some-messages.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 8990010d76cd48f8c166f586a8c6ae07cb1a749d Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Fri, 21 Oct 2022 15:08:43 +0200
|
||||
Subject: [PATCH] random-seed: downgrade some messages
|
||||
|
||||
In these cases, we eat up the error and propagate success so we should log at
|
||||
warning level only.
|
||||
|
||||
(cherry picked from commit ea37e1edf9bdaa5a90050d69454a132dc5d60360)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 05fb5bb157..7782509572 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -167,7 +167,7 @@ static int load_seed_file(
|
||||
|
||||
k = loop_read(seed_fd, buf, seed_size, false);
|
||||
if (k < 0) {
|
||||
- log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m");
|
||||
+ log_warning_errno(k, "Failed to read seed from " RANDOM_SEED ": %m");
|
||||
return 0;
|
||||
}
|
||||
if (k == 0) {
|
||||
@@ -219,7 +219,7 @@ static int load_seed_file(
|
||||
r = random_write_entropy(urandom_fd, buf, k,
|
||||
IN_SET(lets_credit, CREDIT_ENTROPY_YES_PLEASE, CREDIT_ENTROPY_YES_FORCED));
|
||||
if (r < 0)
|
||||
- log_error_errno(r, "Failed to write seed to /dev/urandom: %m");
|
||||
+ log_warning_errno(r, "Failed to write seed to /dev/urandom: %m");
|
||||
|
||||
return 0;
|
||||
}
|
33
0661-random-seed-clarify-one-comment.patch
Normal file
33
0661-random-seed-clarify-one-comment.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From 22a598fa626bf440127c1dd2a6b116514869752a Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Tue, 25 Oct 2022 13:54:10 +0200
|
||||
Subject: [PATCH] random-seed: clarify one comment
|
||||
|
||||
(cherry picked from commit 46e0b5dca7fa5368bccbf30a7d2569d93d994a44)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 7782509572..22ddf659ae 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -249,12 +249,13 @@ static int save_seed_file(
|
||||
if (!buf)
|
||||
return log_oom();
|
||||
|
||||
- /* Let's make this whole job asynchronous, i.e. let's make ourselves a barrier for proper
|
||||
- * initialization of the random pool. */
|
||||
k = getrandom(buf, seed_size, GRND_NONBLOCK);
|
||||
if (k < 0 && errno == EAGAIN && synchronous) {
|
||||
+ /* If we're asked to make ourselves a barrier for proper initialization of the random pool
|
||||
+ * make this whole job synchronous by asking getrandom() to wait until the requested number
|
||||
+ * of random bytes is available. */
|
||||
log_notice("Kernel entropy pool is not initialized yet, waiting until it is.");
|
||||
- k = getrandom(buf, seed_size, 0); /* retry synchronously */
|
||||
+ k = getrandom(buf, seed_size, 0);
|
||||
}
|
||||
if (k < 0)
|
||||
log_debug_errno(errno, "Failed to read random data with getrandom(), falling back to /dev/urandom: %m");
|
100
0662-random-seed-make-sure-to-load-machine-id-even-if-the.patch
Normal file
100
0662-random-seed-make-sure-to-load-machine-id-even-if-the.patch
Normal file
@ -0,0 +1,100 @@
|
||||
From 3dcd5325c72f656fbf97b71331bea1edc486f2d2 Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Mon, 24 Oct 2022 11:30:29 +0200
|
||||
Subject: [PATCH] random-seed: make sure to load machine id even if the seed
|
||||
file is missing
|
||||
|
||||
(cherry picked from commit a2f0dbb81004685d17f71fed48dc50027ccadb82)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 49 +++++++++++++++++++++--------------
|
||||
1 file changed, 29 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 22ddf659ae..b548f92bbe 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -131,6 +131,27 @@ static int random_seed_size(int seed_fd, size_t *ret_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void load_machine_id(int urandom_fd) {
|
||||
+ sd_id128_t mid;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(urandom_fd >= 0);
|
||||
+
|
||||
+ /* As an extra protection against "golden images" that are put together sloppily, i.e. images which
|
||||
+ * are duplicated on multiple systems but where the random seed file is not properly
|
||||
+ * reset. Frequently the machine ID is properly reset on those systems however (simply because it's
|
||||
+ * easier to notice, if it isn't due to address clashes and so on, while random seed equivalence is
|
||||
+ * generally not noticed easily), hence let's simply write the machined ID into the random pool
|
||||
+ * too. */
|
||||
+ r = sd_id128_get_machine(&mid);
|
||||
+ if (r < 0)
|
||||
+ return (void) log_debug_errno(r, "Failed to get machine ID, ignoring: %m");
|
||||
+
|
||||
+ r = random_write_entropy(urandom_fd, &mid, sizeof(mid), /* credit= */ false);
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to write machine ID to /dev/urandom, ignoring: %m");
|
||||
+}
|
||||
+
|
||||
static int load_seed_file(
|
||||
int seed_fd,
|
||||
int urandom_fd,
|
||||
@@ -139,28 +160,12 @@ static int load_seed_file(
|
||||
|
||||
_cleanup_free_ void *buf = NULL;
|
||||
CreditEntropy lets_credit;
|
||||
- sd_id128_t mid;
|
||||
ssize_t k;
|
||||
int r;
|
||||
|
||||
assert(seed_fd >= 0);
|
||||
assert(urandom_fd >= 0);
|
||||
|
||||
- /* First, let's write the machine ID into /dev/urandom, not crediting entropy. Why? As an extra
|
||||
- * protection against "golden images" that are put together sloppily, i.e. images which are
|
||||
- * duplicated on multiple systems but where the random seed file is not properly reset. Frequently
|
||||
- * the machine ID is properly reset on those systems however (simply because it's easier to notice,
|
||||
- * if it isn't due to address clashes and so on, while random seed equivalence is generally not
|
||||
- * noticed easily), hence let's simply write the machined ID into the random pool too. */
|
||||
- r = sd_id128_get_machine(&mid);
|
||||
- if (r < 0)
|
||||
- log_debug_errno(r, "Failed to get machine ID, ignoring: %m");
|
||||
- else {
|
||||
- r = random_write_entropy(urandom_fd, &mid, sizeof(mid), /* credit= */ false);
|
||||
- if (r < 0)
|
||||
- log_debug_errno(r, "Failed to write machine ID to /dev/urandom, ignoring: %m");
|
||||
- }
|
||||
-
|
||||
buf = malloc(seed_size);
|
||||
if (!buf)
|
||||
return log_oom();
|
||||
@@ -402,6 +407,14 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
switch (arg_action) {
|
||||
case ACTION_LOAD:
|
||||
+ random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY);
|
||||
+ if (random_fd < 0)
|
||||
+ return log_error_errno(errno, "Failed to open /dev/urandom: %m");
|
||||
+
|
||||
+ /* First, let's write the machine ID into /dev/urandom, not crediting entropy. See
|
||||
+ * load_machine_id() for an explanation why. */
|
||||
+ load_machine_id(random_fd);
|
||||
+
|
||||
seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
|
||||
if (seed_fd < 0) {
|
||||
int open_rw_error = -errno;
|
||||
@@ -421,10 +434,6 @@ static int run(int argc, char *argv[]) {
|
||||
} else
|
||||
write_seed_file = true;
|
||||
|
||||
- random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY);
|
||||
- if (random_fd < 0)
|
||||
- return log_error_errno(errno, "Failed to open /dev/urandom: %m");
|
||||
-
|
||||
read_seed_file = true;
|
||||
synchronous = true; /* make this invocation a synchronous barrier for random pool initialization */
|
||||
break;
|
@ -0,0 +1,87 @@
|
||||
From 99294ed904d04eff1b1f05390e64d92f9d824853 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Fri, 11 Nov 2022 17:31:34 +0100
|
||||
Subject: [PATCH] chase-symlinks: add new flag for prohibiting any following of
|
||||
symlinks
|
||||
|
||||
This is useful when operating in the ESP, which is untrusted territory,
|
||||
and where under no circumstances we should be tricked by symlinks into
|
||||
doing anything we don't want to.
|
||||
|
||||
(cherry picked from commit d43e78b643535da398345d5ae680a96d7b65940e)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/basic/chase-symlinks.c | 18 ++++++++++++++++++
|
||||
src/basic/chase-symlinks.h | 1 +
|
||||
src/test/test-fs-util.c | 9 +++++++++
|
||||
3 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/src/basic/chase-symlinks.c b/src/basic/chase-symlinks.c
|
||||
index ac55311f4d..e10370d0d2 100644
|
||||
--- a/src/basic/chase-symlinks.c
|
||||
+++ b/src/basic/chase-symlinks.c
|
||||
@@ -57,6 +57,21 @@ static int log_autofs_mount_point(int fd, const char *path, ChaseSymlinksFlags f
|
||||
strna(n1), path);
|
||||
}
|
||||
|
||||
+static int log_prohibited_symlink(int fd, ChaseSymlinksFlags flags) {
|
||||
+ _cleanup_free_ char *n1 = NULL;
|
||||
+
|
||||
+ assert(fd >= 0);
|
||||
+
|
||||
+ if (!FLAGS_SET(flags, CHASE_WARN))
|
||||
+ return -EREMCHG;
|
||||
+
|
||||
+ (void) fd_get_path(fd, &n1);
|
||||
+
|
||||
+ return log_warning_errno(SYNTHETIC_ERRNO(EREMCHG),
|
||||
+ "Detected symlink where not symlink is allowed at %s, refusing.",
|
||||
+ strna(n1));
|
||||
+}
|
||||
+
|
||||
int chase_symlinks(
|
||||
const char *path,
|
||||
const char *original_root,
|
||||
@@ -302,6 +317,9 @@ int chase_symlinks(
|
||||
if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) {
|
||||
_cleanup_free_ char *destination = NULL;
|
||||
|
||||
+ if (flags & CHASE_PROHIBIT_SYMLINKS)
|
||||
+ return log_prohibited_symlink(child, flags);
|
||||
+
|
||||
/* This is a symlink, in this case read the destination. But let's make sure we
|
||||
* don't follow symlinks without bounds. */
|
||||
if (--max_follow <= 0)
|
||||
diff --git a/src/basic/chase-symlinks.h b/src/basic/chase-symlinks.h
|
||||
index a9ee58f9f7..8f69bf3eed 100644
|
||||
--- a/src/basic/chase-symlinks.h
|
||||
+++ b/src/basic/chase-symlinks.h
|
||||
@@ -17,6 +17,7 @@ typedef enum ChaseSymlinksFlags {
|
||||
* right-most component refers to symlink, return O_PATH fd of the symlink. */
|
||||
CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered.
|
||||
* Note: this may do an NSS lookup, hence this flag cannot be used in PID 1. */
|
||||
+ CHASE_PROHIBIT_SYMLINKS = 1 << 8, /* Refuse all symlinks */
|
||||
} ChaseSymlinksFlags;
|
||||
|
||||
bool unsafe_transition(const struct stat *a, const struct stat *b);
|
||||
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
|
||||
index 9c1ced7591..16f04d6889 100644
|
||||
--- a/src/test/test-fs-util.c
|
||||
+++ b/src/test/test-fs-util.c
|
||||
@@ -387,6 +387,15 @@ TEST(chase_symlinks) {
|
||||
assert_se(path_equal(path_startswith(result, p), "usr"));
|
||||
result = mfree(result);
|
||||
|
||||
+ /* Test CHASE_PROHIBIT_SYMLINKS */
|
||||
+
|
||||
+ assert_se(chase_symlinks("top/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, NULL, NULL) == -EREMCHG);
|
||||
+ assert_se(chase_symlinks("top/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_WARN, NULL, NULL) == -EREMCHG);
|
||||
+ assert_se(chase_symlinks("top/dotdot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, NULL, NULL) == -EREMCHG);
|
||||
+ assert_se(chase_symlinks("top/dotdot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_WARN, NULL, NULL) == -EREMCHG);
|
||||
+ assert_se(chase_symlinks("top/dot/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, NULL, NULL) == -EREMCHG);
|
||||
+ assert_se(chase_symlinks("top/dot/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_WARN, NULL, NULL) == -EREMCHG);
|
||||
+
|
||||
cleanup:
|
||||
assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
|
||||
}
|
141
0664-bootctl-bootspec-make-use-of-CHASE_PROHIBIT_SYMLINKS.patch
Normal file
141
0664-bootctl-bootspec-make-use-of-CHASE_PROHIBIT_SYMLINKS.patch
Normal file
@ -0,0 +1,141 @@
|
||||
From 466da97e11cebf84a293789d0f4f38779244a5b3 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Fri, 11 Nov 2022 17:36:29 +0100
|
||||
Subject: [PATCH] bootctl,bootspec: make use of CHASE_PROHIBIT_SYMLINKS
|
||||
whenever we access the ESP/XBOOTLDR
|
||||
|
||||
Let's make use of the new flag whenever we access the ESP or XBOOTLDR.
|
||||
The resources we make use of in these partitions can't possibly use
|
||||
symlinks (because UEFI knows no symlink concept), and they are untrusted
|
||||
territory, hence under no circumstances we should be tricked into
|
||||
following symlinks that shouldn't be there in the first place.
|
||||
|
||||
Of course, you might argue thta ESP/XBOOTLDR are VFAT and thus don#t
|
||||
know symlinks. But the thing is, they don#t have to be. Firmware can
|
||||
support other file systems too, and people can use efifs to gain access
|
||||
to arbitrary Linux file systems from EFI. Hence, let's better be safe
|
||||
than sorry.
|
||||
|
||||
(cherry picked from commit b353d5eee9e8df0aa2f4cbb1bfb0a46a963ba78f)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/bootctl.c | 18 +++++++++---------
|
||||
src/shared/bootspec.c | 8 ++++----
|
||||
2 files changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
|
||||
index a0ca2afec2..e830d45486 100644
|
||||
--- a/src/boot/bootctl.c
|
||||
+++ b/src/boot/bootctl.c
|
||||
@@ -485,7 +485,7 @@ static int enumerate_binaries(
|
||||
assert(previous);
|
||||
assert(is_first);
|
||||
|
||||
- r = chase_symlinks_and_opendir(path, esp_path, CHASE_PREFIX_ROOT, &p, &d);
|
||||
+ r = chase_symlinks_and_opendir(path, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &p, &d);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
@@ -918,10 +918,10 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) {
|
||||
if (!p)
|
||||
return log_oom();
|
||||
|
||||
- r = chase_symlinks(p, root, CHASE_PREFIX_ROOT, &source_path, NULL);
|
||||
+ r = chase_symlinks(p, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &source_path, NULL);
|
||||
/* If we had a root directory to try, we didn't find it and we are in auto mode, retry on the host */
|
||||
if (r == -ENOENT && root && arg_install_source == ARG_INSTALL_SOURCE_AUTO)
|
||||
- r = chase_symlinks(p, NULL, CHASE_PREFIX_ROOT, &source_path, NULL);
|
||||
+ r = chase_symlinks(p, NULL, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &source_path, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r,
|
||||
"Failed to resolve path %s%s%s: %m",
|
||||
@@ -933,7 +933,7 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) {
|
||||
if (!q)
|
||||
return log_oom();
|
||||
|
||||
- r = chase_symlinks(q, esp_path, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, &dest_path, NULL);
|
||||
+ r = chase_symlinks(q, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_NONEXISTENT, &dest_path, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to resolve path %s under directory %s: %m", q, esp_path);
|
||||
|
||||
@@ -950,7 +950,7 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) {
|
||||
v = strjoina("/EFI/BOOT/BOOT", e);
|
||||
ascii_strupper(strrchr(v, '/') + 1);
|
||||
|
||||
- r = chase_symlinks(v, esp_path, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, &default_dest_path, NULL);
|
||||
+ r = chase_symlinks(v, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_NONEXISTENT, &default_dest_path, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to resolve path %s under directory %s: %m", v, esp_path);
|
||||
|
||||
@@ -968,10 +968,10 @@ static int install_binaries(const char *esp_path, const char *arch, bool force)
|
||||
_cleanup_free_ char *path = NULL;
|
||||
int r;
|
||||
|
||||
- r = chase_symlinks_and_opendir(BOOTLIBDIR, root, CHASE_PREFIX_ROOT, &path, &d);
|
||||
+ r = chase_symlinks_and_opendir(BOOTLIBDIR, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &path, &d);
|
||||
/* If we had a root directory to try, we didn't find it and we are in auto mode, retry on the host */
|
||||
if (r == -ENOENT && root && arg_install_source == ARG_INSTALL_SOURCE_AUTO)
|
||||
- r = chase_symlinks_and_opendir(BOOTLIBDIR, NULL, CHASE_PREFIX_ROOT, &path, &d);
|
||||
+ r = chase_symlinks_and_opendir(BOOTLIBDIR, NULL, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &path, &d);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open boot loader directory %s%s: %m", strempty(root), BOOTLIBDIR);
|
||||
|
||||
@@ -1141,7 +1141,7 @@ static int install_variables(
|
||||
return 0;
|
||||
}
|
||||
|
||||
- r = chase_symlinks_and_access(path, esp_path, CHASE_PREFIX_ROOT, F_OK, NULL, NULL);
|
||||
+ r = chase_symlinks_and_access(path, esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, F_OK, NULL, NULL);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
@@ -1172,7 +1172,7 @@ static int remove_boot_efi(const char *esp_path) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r, c = 0;
|
||||
|
||||
- r = chase_symlinks_and_opendir("/EFI/BOOT", esp_path, CHASE_PREFIX_ROOT, &p, &d);
|
||||
+ r = chase_symlinks_and_opendir("/EFI/BOOT", esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &p, &d);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c
|
||||
index fe44b5e9d2..9352416af5 100644
|
||||
--- a/src/shared/bootspec.c
|
||||
+++ b/src/shared/bootspec.c
|
||||
@@ -507,7 +507,7 @@ static int boot_loader_read_conf_path(BootConfig *config, const char *root, cons
|
||||
assert(config);
|
||||
assert(path);
|
||||
|
||||
- r = chase_symlinks_and_fopen_unlocked(path, root, CHASE_PREFIX_ROOT, "re", &full, &f);
|
||||
+ r = chase_symlinks_and_fopen_unlocked(path, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, "re", &full, &f);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
@@ -609,7 +609,7 @@ static int boot_entries_find_type1(
|
||||
assert(root);
|
||||
assert(dir);
|
||||
|
||||
- dir_fd = chase_symlinks_and_open(dir, root, CHASE_PREFIX_ROOT, O_DIRECTORY|O_CLOEXEC, &full);
|
||||
+ dir_fd = chase_symlinks_and_open(dir, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, O_DIRECTORY|O_CLOEXEC, &full);
|
||||
if (dir_fd == -ENOENT)
|
||||
return 0;
|
||||
if (dir_fd < 0)
|
||||
@@ -869,7 +869,7 @@ static int boot_entries_find_unified(
|
||||
assert(config);
|
||||
assert(dir);
|
||||
|
||||
- r = chase_symlinks_and_opendir(dir, root, CHASE_PREFIX_ROOT, &full, &d);
|
||||
+ r = chase_symlinks_and_opendir(dir, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &full, &d);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
@@ -1282,7 +1282,7 @@ static void boot_entry_file_list(
|
||||
assert(p);
|
||||
assert(ret_status);
|
||||
|
||||
- int status = chase_symlinks_and_access(p, root, CHASE_PREFIX_ROOT, F_OK, NULL, NULL);
|
||||
+ int status = chase_symlinks_and_access(p, root, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, F_OK, NULL, NULL);
|
||||
|
||||
printf("%13s%s ", strempty(field), field ? ":" : " ");
|
||||
if (status < 0) {
|
863
0665-boot-implement-kernel-EFI-RNG-seed-protocol-with-pro.patch
Normal file
863
0665-boot-implement-kernel-EFI-RNG-seed-protocol-with-pro.patch
Normal file
@ -0,0 +1,863 @@
|
||||
From bd5fbc8566124744d94d5f040016b9f4404dc2dc Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Wed, 9 Nov 2022 12:44:37 +0100
|
||||
Subject: [PATCH] boot: implement kernel EFI RNG seed protocol with proper
|
||||
hashing
|
||||
|
||||
Rather than passing seeds up to userspace via EFI variables, pass seeds
|
||||
directly to the kernel's EFI stub loader, via LINUX_EFI_RANDOM_SEED_TABLE_GUID.
|
||||
EFI variables can potentially leak and suffer from forward secrecy
|
||||
issues, and processing these with userspace means that they are
|
||||
initialized much too late in boot to be useful. In contrast,
|
||||
LINUX_EFI_RANDOM_SEED_TABLE_GUID uses EFI configuration tables, and so
|
||||
is hidden from userspace entirely, and is parsed extremely early on by
|
||||
the kernel, so that every single call to get_random_bytes() by the
|
||||
kernel is seeded.
|
||||
|
||||
In order to do this properly, we use a bit more robust hashing scheme,
|
||||
and make sure that each input is properly memzeroed out after use. The
|
||||
scheme is:
|
||||
|
||||
key = HASH(LABEL || sizeof(input1) || input1 || ... || sizeof(inputN) || inputN)
|
||||
new_disk_seed = HASH(key || 0)
|
||||
seed_for_linux = HASH(key || 1)
|
||||
|
||||
The various inputs are:
|
||||
- LINUX_EFI_RANDOM_SEED_TABLE_GUID from prior bootloaders
|
||||
- 256 bits of seed from EFI's RNG
|
||||
- The (immutable) system token, from its EFI variable
|
||||
- The prior on-disk seed
|
||||
- The UEFI monotonic counter
|
||||
- A timestamp
|
||||
|
||||
This also adjusts the secure boot semantics, so that the operation is
|
||||
only aborted if it's not possible to get random bytes from EFI's RNG or
|
||||
a prior boot stage. With the proper hashing scheme, this should make
|
||||
boot seeds safe even on secure boot.
|
||||
|
||||
There is currently a bug in Linux's EFI stub in which if the EFI stub
|
||||
manages to generate random bytes on its own using EFI's RNG, it will
|
||||
ignore what the bootloader passes. That's annoying, but it means that
|
||||
either way, via systemd-boot or via EFI stub's mechanism, the RNG *does*
|
||||
get initialized in a good safe way. And this bug is now fixed in the
|
||||
efi.git tree, and will hopefully be backported to older kernels.
|
||||
|
||||
As the kernel recommends, the resultant seeds are 256 bits and are
|
||||
allocated using pool memory of type EfiACPIReclaimMemory, so that it
|
||||
gets freed at the right moment in boot.
|
||||
|
||||
(cherry picked from commit 0be72218f1c90af5755ab40f94d047ee6864aea8)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
.../UninitializedVariableWithCleanup.ql | 2 +-
|
||||
docs/BOOT_LOADER_INTERFACE.md | 9 +-
|
||||
docs/RANDOM_SEEDS.md | 51 +--
|
||||
man/systemd-boot.xml | 22 --
|
||||
src/basic/random-util.h | 1 +
|
||||
src/boot/bootctl.c | 30 +-
|
||||
src/boot/efi/efi-string.h | 1 +
|
||||
src/boot/efi/random-seed.c | 305 +++++++++---------
|
||||
src/core/efi-random.c | 82 +----
|
||||
src/core/efi-random.h | 2 +-
|
||||
src/core/main.c | 4 +-
|
||||
units/systemd-boot-system-token.service | 3 -
|
||||
12 files changed, 218 insertions(+), 294 deletions(-)
|
||||
|
||||
diff --git a/.github/codeql-queries/UninitializedVariableWithCleanup.ql b/.github/codeql-queries/UninitializedVariableWithCleanup.ql
|
||||
index e514111f28..dadc6cb1b5 100644
|
||||
--- a/.github/codeql-queries/UninitializedVariableWithCleanup.ql
|
||||
+++ b/.github/codeql-queries/UninitializedVariableWithCleanup.ql
|
||||
@@ -20,7 +20,7 @@ import semmle.code.cpp.controlflow.StackVariableReachability
|
||||
* since they don't do anything illegal even when the variable is uninitialized
|
||||
*/
|
||||
predicate cleanupFunctionDenyList(string fun) {
|
||||
- fun = "erase_char"
|
||||
+ fun = "erase_char" or fun = "erase_obj"
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/docs/BOOT_LOADER_INTERFACE.md b/docs/BOOT_LOADER_INTERFACE.md
|
||||
index fc9336085b..5be4d1ad17 100644
|
||||
--- a/docs/BOOT_LOADER_INTERFACE.md
|
||||
+++ b/docs/BOOT_LOADER_INTERFACE.md
|
||||
@@ -80,12 +80,6 @@ variables. All EFI variables use the vendor UUID
|
||||
* `1 << 5` → The boot loader supports looking for boot menu entries in the Extended Boot Loader Partition.
|
||||
* `1 << 6` → The boot loader supports passing a random seed to the OS.
|
||||
|
||||
-* The EFI variable `LoaderRandomSeed` contains a binary random seed if set. It
|
||||
- is set by the boot loader to pass an entropy seed read from the ESP to the OS.
|
||||
- The system manager then credits this seed to the kernel's entropy pool. It is
|
||||
- the responsibility of the boot loader to ensure the quality and integrity of
|
||||
- the random seed.
|
||||
-
|
||||
* The EFI variable `LoaderSystemToken` contains binary random data,
|
||||
persistently set by the OS installer. Boot loaders that support passing
|
||||
random seeds to the OS should use this data and combine it with the random
|
||||
@@ -107,8 +101,7 @@ that directory is empty, and only if no other file systems are mounted
|
||||
there. The `systemctl reboot --boot-loader-entry=…` and `systemctl reboot
|
||||
--boot-loader-menu=…` commands rely on the `LoaderFeatures` ,
|
||||
`LoaderConfigTimeoutOneShot`, `LoaderEntries`, `LoaderEntryOneShot`
|
||||
-variables. `LoaderRandomSeed` is read by PID during early boot and credited to
|
||||
-the kernel's random pool.
|
||||
+variables.
|
||||
|
||||
## Boot Loader Entry Identifiers
|
||||
|
||||
diff --git a/docs/RANDOM_SEEDS.md b/docs/RANDOM_SEEDS.md
|
||||
index 3dc27f5552..b7240f0d89 100644
|
||||
--- a/docs/RANDOM_SEEDS.md
|
||||
+++ b/docs/RANDOM_SEEDS.md
|
||||
@@ -197,28 +197,39 @@ boot, in order to ensure the entropy pool is filled up quickly.
|
||||
generate sufficient data), to generate a new random seed file to store in
|
||||
the ESP as well as a random seed to pass to the OS kernel. The new random
|
||||
seed file for the ESP is then written to the ESP, ensuring this is completed
|
||||
- before the OS is invoked. Very early during initialization PID 1 will read
|
||||
- the random seed provided in the EFI variable and credit it fully to the
|
||||
- kernel's entropy pool.
|
||||
-
|
||||
- This mechanism is able to safely provide an initialized entropy pool already
|
||||
- in the `initrd` and guarantees that different seeds are passed from the boot
|
||||
- loader to the OS on every boot (in a way that does not allow regeneration of
|
||||
- an old seed file from a new seed file). Moreover, when an OS image is
|
||||
- replicated between multiple images and the random seed is not reset, this
|
||||
- will still result in different random seeds being passed to the OS, as the
|
||||
- per-machine 'system token' is specific to the physical host, and not
|
||||
- included in OS disk images. If the 'system token' is properly initialized
|
||||
- and kept sufficiently secret it should not be possible to regenerate the
|
||||
- entropy pool of different machines, even if this seed is the only source of
|
||||
- entropy.
|
||||
+ before the OS is invoked.
|
||||
+
|
||||
+ The kernel then reads the random seed that the boot loader passes to it, via
|
||||
+ the EFI configuration table entry, `LINUX_EFI_RANDOM_SEED_TABLE_GUID`
|
||||
+ (1ce1e5bc-7ceb-42f2-81e5-8aadf180f57b), which is allocated with pool memory
|
||||
+ of type `EfiACPIReclaimMemory`. Its contents have the form:
|
||||
+ ```
|
||||
+ struct linux_efi_random_seed {
|
||||
+ u32 size; // of the 'seed' array in bytes
|
||||
+ u8 seed[];
|
||||
+ };
|
||||
+ ```
|
||||
+ The size field is generally set to 32 bytes, and the seed field includes a
|
||||
+ hashed representation of any prior seed in `LINUX_EFI_RANDOM_SEED_TABLE_GUID`
|
||||
+ together with the new seed.
|
||||
+
|
||||
+ This mechanism is able to safely provide an initialized entropy pool before
|
||||
+ userspace even starts and guarantees that different seeds are passed from
|
||||
+ the boot loader to the OS on every boot (in a way that does not allow
|
||||
+ regeneration of an old seed file from a new seed file). Moreover, when an OS
|
||||
+ image is replicated between multiple images and the random seed is not
|
||||
+ reset, this will still result in different random seeds being passed to the
|
||||
+ OS, as the per-machine 'system token' is specific to the physical host, and
|
||||
+ not included in OS disk images. If the 'system token' is properly
|
||||
+ initialized and kept sufficiently secret it should not be possible to
|
||||
+ regenerate the entropy pool of different machines, even if this seed is the
|
||||
+ only source of entropy.
|
||||
|
||||
Note that the writes to the ESP needed to maintain the random seed should be
|
||||
- minimal. The size of the random seed file is directly derived from the Linux
|
||||
- kernel's entropy pool size, which defaults to 512 bytes. This means updating
|
||||
- the random seed in the ESP should be doable safely with a single sector
|
||||
- write (since hard-disk sectors typically happen to be 512 bytes long, too),
|
||||
- which should be safe even with FAT file system drivers built into
|
||||
+ minimal. Because the size of the random seed file is generally set to 32 bytes,
|
||||
+ updating the random seed in the ESP should be doable safely with a single
|
||||
+ sector write (since hard-disk sectors typically happen to be 512 bytes long,
|
||||
+ too), which should be safe even with FAT file system drivers built into
|
||||
low-quality EFI firmwares.
|
||||
|
||||
As a special restriction: in virtualized environments PID 1 will refrain
|
||||
diff --git a/man/systemd-boot.xml b/man/systemd-boot.xml
|
||||
index 57b66803fa..f96c4c6512 100644
|
||||
--- a/man/systemd-boot.xml
|
||||
+++ b/man/systemd-boot.xml
|
||||
@@ -435,28 +435,6 @@
|
||||
to view this data. </para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
- <varlistentry>
|
||||
- <term><varname>LoaderRandomSeed</varname></term>
|
||||
-
|
||||
- <listitem><para>A binary random seed <command>systemd-boot</command> may optionally pass to the
|
||||
- OS. This is a volatile EFI variable that is hashed at boot from the combination of a random seed
|
||||
- stored in the ESP (in <filename>/loader/random-seed</filename>) and a "system token" persistently
|
||||
- stored in the EFI variable <varname>LoaderSystemToken</varname> (see below). During early OS boot the
|
||||
- system manager reads this variable and passes it to the OS kernel's random pool, crediting the full
|
||||
- entropy it contains. This is an efficient way to ensure the system starts up with a fully initialized
|
||||
- kernel random pool — as early as the initrd phase. <command>systemd-boot</command> reads
|
||||
- the random seed from the ESP, combines it with the "system token", and both derives a new random seed
|
||||
- to update in-place the seed stored in the ESP, and the random seed to pass to the OS from it via
|
||||
- SHA256 hashing in counter mode. This ensures that different physical systems that boot the same
|
||||
- "golden" OS image — i.e. containing the same random seed file in the ESP — will still pass a
|
||||
- different random seed to the OS. It is made sure the random seed stored in the ESP is fully
|
||||
- overwritten before the OS is booted, to ensure different random seed data is used between subsequent
|
||||
- boots.</para>
|
||||
-
|
||||
- <para>See <ulink url="https://systemd.io/RANDOM_SEEDS">Random Seeds</ulink> for
|
||||
- further information.</para></listitem>
|
||||
- </varlistentry>
|
||||
-
|
||||
<varlistentry>
|
||||
<term><varname>LoaderSystemToken</varname></term>
|
||||
|
||||
diff --git a/src/basic/random-util.h b/src/basic/random-util.h
|
||||
index 7e6f66df4d..08b1a3599a 100644
|
||||
--- a/src/basic/random-util.h
|
||||
+++ b/src/basic/random-util.h
|
||||
@@ -23,6 +23,7 @@ static inline uint32_t random_u32(void) {
|
||||
/* Some limits on the pool sizes when we deal with the kernel random pool */
|
||||
#define RANDOM_POOL_SIZE_MIN 1024U
|
||||
#define RANDOM_POOL_SIZE_MAX (10U*1024U*1024U)
|
||||
+#define RANDOM_EFI_SEED_SIZE 32U
|
||||
|
||||
size_t random_pool_size(void);
|
||||
|
||||
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
|
||||
index e830d45486..e23a72fd38 100644
|
||||
--- a/src/boot/bootctl.c
|
||||
+++ b/src/boot/bootctl.c
|
||||
@@ -1894,8 +1894,6 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
printf("\n");
|
||||
|
||||
printf("%sRandom Seed:%s\n", ansi_underline(), ansi_normal());
|
||||
- have = access(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderRandomSeed)), F_OK) >= 0;
|
||||
- printf(" Passed to OS: %s\n", yes_no(have));
|
||||
have = access(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderSystemToken)), F_OK) >= 0;
|
||||
printf(" System Token: %s\n", have ? "set" : "not set");
|
||||
|
||||
@@ -1985,10 +1983,10 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
||||
|
||||
static int install_random_seed(const char *esp) {
|
||||
_cleanup_(unlink_and_freep) char *tmp = NULL;
|
||||
- _cleanup_free_ void *buffer = NULL;
|
||||
+ unsigned char buffer[RANDOM_EFI_SEED_SIZE];
|
||||
_cleanup_free_ char *path = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
- size_t sz, token_size;
|
||||
+ size_t token_size;
|
||||
ssize_t n;
|
||||
int r;
|
||||
|
||||
@@ -1998,13 +1996,7 @@ static int install_random_seed(const char *esp) {
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
- sz = random_pool_size();
|
||||
-
|
||||
- buffer = malloc(sz);
|
||||
- if (!buffer)
|
||||
- return log_oom();
|
||||
-
|
||||
- r = crypto_random_bytes(buffer, sz);
|
||||
+ r = crypto_random_bytes(buffer, sizeof(buffer));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire random seed: %m");
|
||||
|
||||
@@ -2025,10 +2017,10 @@ static int install_random_seed(const char *esp) {
|
||||
return log_error_errno(fd, "Failed to open random seed file for writing: %m");
|
||||
}
|
||||
|
||||
- n = write(fd, buffer, sz);
|
||||
+ n = write(fd, buffer, sizeof(buffer));
|
||||
if (n < 0)
|
||||
return log_error_errno(errno, "Failed to write random seed file: %m");
|
||||
- if ((size_t) n != sz)
|
||||
+ if ((size_t) n != sizeof(buffer))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while writing random seed file.");
|
||||
|
||||
if (rename(tmp, path) < 0)
|
||||
@@ -2036,7 +2028,7 @@ static int install_random_seed(const char *esp) {
|
||||
|
||||
tmp = mfree(tmp);
|
||||
|
||||
- log_info("Random seed file %s successfully written (%zu bytes).", path, sz);
|
||||
+ log_info("Random seed file %s successfully written (%zu bytes).", path, sizeof(buffer));
|
||||
|
||||
if (!arg_touch_variables)
|
||||
return 0;
|
||||
@@ -2088,16 +2080,16 @@ static int install_random_seed(const char *esp) {
|
||||
if (r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to test system token validity: %m");
|
||||
} else {
|
||||
- if (token_size >= sz) {
|
||||
+ if (token_size >= sizeof(buffer)) {
|
||||
/* Let's avoid writes if we can, and initialize this only once. */
|
||||
log_debug("System token already written, not updating.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
- log_debug("Existing system token size (%zu) does not match our expectations (%zu), replacing.", token_size, sz);
|
||||
+ log_debug("Existing system token size (%zu) does not match our expectations (%zu), replacing.", token_size, sizeof(buffer));
|
||||
}
|
||||
|
||||
- r = crypto_random_bytes(buffer, sz);
|
||||
+ r = crypto_random_bytes(buffer, sizeof(buffer));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire random seed: %m");
|
||||
|
||||
@@ -2105,7 +2097,7 @@ static int install_random_seed(const char *esp) {
|
||||
* and possibly get identification information or too much insight into the kernel's entropy pool
|
||||
* state. */
|
||||
RUN_WITH_UMASK(0077) {
|
||||
- r = efi_set_variable(EFI_LOADER_VARIABLE(LoaderSystemToken), buffer, sz);
|
||||
+ r = efi_set_variable(EFI_LOADER_VARIABLE(LoaderSystemToken), buffer, sizeof(buffer));
|
||||
if (r < 0) {
|
||||
if (!arg_graceful)
|
||||
return log_error_errno(r, "Failed to write 'LoaderSystemToken' EFI variable: %m");
|
||||
@@ -2115,7 +2107,7 @@ static int install_random_seed(const char *esp) {
|
||||
else
|
||||
log_warning_errno(r, "Unable to write 'LoaderSystemToken' EFI variable, ignoring: %m");
|
||||
} else
|
||||
- log_info("Successfully initialized system token in EFI variable with %zu bytes.", sz);
|
||||
+ log_info("Successfully initialized system token in EFI variable with %zu bytes.", sizeof(buffer));
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/src/boot/efi/efi-string.h b/src/boot/efi/efi-string.h
|
||||
index 9b2a9ad1c5..25931a7d6e 100644
|
||||
--- a/src/boot/efi/efi-string.h
|
||||
+++ b/src/boot/efi/efi-string.h
|
||||
@@ -124,6 +124,7 @@ static inline void *mempcpy(void * restrict dest, const void * restrict src, siz
|
||||
memcpy(dest, src, n);
|
||||
return (uint8_t *) dest + n;
|
||||
}
|
||||
+
|
||||
#else
|
||||
/* For unit testing. */
|
||||
int efi_memcmp(const void *p1, const void *p2, size_t n);
|
||||
diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c
|
||||
index 3c9df5bb54..c723160c0f 100644
|
||||
--- a/src/boot/efi/random-seed.c
|
||||
+++ b/src/boot/efi/random-seed.c
|
||||
@@ -15,11 +15,24 @@
|
||||
|
||||
#define EFI_RNG_GUID &(const EFI_GUID) EFI_RNG_PROTOCOL_GUID
|
||||
|
||||
+struct linux_efi_random_seed {
|
||||
+ uint32_t size;
|
||||
+ uint8_t seed[];
|
||||
+};
|
||||
+
|
||||
+#define LINUX_EFI_RANDOM_SEED_TABLE_GUID \
|
||||
+ { 0x1ce1e5bc, 0x7ceb, 0x42f2, { 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b } }
|
||||
+
|
||||
/* SHA256 gives us 256/8=32 bytes */
|
||||
#define HASH_VALUE_SIZE 32
|
||||
|
||||
-static EFI_STATUS acquire_rng(UINTN size, void **ret) {
|
||||
- _cleanup_free_ void *data = NULL;
|
||||
+/* Linux's RNG is 256 bits, so let's provide this much */
|
||||
+#define DESIRED_SEED_SIZE 32
|
||||
+
|
||||
+/* Some basic domain separation in case somebody uses this data elsewhere */
|
||||
+#define HASH_LABEL "systemd-boot random seed label v1"
|
||||
+
|
||||
+static EFI_STATUS acquire_rng(void *ret, UINTN size) {
|
||||
EFI_RNG_PROTOCOL *rng;
|
||||
EFI_STATUS err;
|
||||
|
||||
@@ -33,126 +46,9 @@ static EFI_STATUS acquire_rng(UINTN size, void **ret) {
|
||||
if (!rng)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
- data = xmalloc(size);
|
||||
-
|
||||
- err = rng->GetRNG(rng, NULL, size, data);
|
||||
+ err = rng->GetRNG(rng, NULL, size, ret);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Failed to acquire RNG data: %r", err);
|
||||
-
|
||||
- *ret = TAKE_PTR(data);
|
||||
- return EFI_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-static void hash_once(
|
||||
- const void *old_seed,
|
||||
- const void *rng,
|
||||
- UINTN size,
|
||||
- const void *system_token,
|
||||
- UINTN system_token_size,
|
||||
- uint64_t uefi_monotonic_counter,
|
||||
- UINTN counter,
|
||||
- uint8_t ret[static HASH_VALUE_SIZE]) {
|
||||
-
|
||||
- /* This hashes together:
|
||||
- *
|
||||
- * 1. The contents of the old seed file
|
||||
- * 2. Some random data acquired from the UEFI RNG (optional)
|
||||
- * 3. Some 'system token' the installer installed as EFI variable (optional)
|
||||
- * 4. The UEFI "monotonic counter" that increases with each boot
|
||||
- * 5. A supplied counter value
|
||||
- *
|
||||
- * And writes the result to the specified buffer.
|
||||
- */
|
||||
-
|
||||
- struct sha256_ctx hash;
|
||||
-
|
||||
- assert(old_seed);
|
||||
- assert(system_token_size == 0 || system_token);
|
||||
-
|
||||
- sha256_init_ctx(&hash);
|
||||
- sha256_process_bytes(old_seed, size, &hash);
|
||||
- if (rng)
|
||||
- sha256_process_bytes(rng, size, &hash);
|
||||
- if (system_token_size > 0)
|
||||
- sha256_process_bytes(system_token, system_token_size, &hash);
|
||||
- sha256_process_bytes(&uefi_monotonic_counter, sizeof(uefi_monotonic_counter), &hash);
|
||||
- sha256_process_bytes(&counter, sizeof(counter), &hash);
|
||||
- sha256_finish_ctx(&hash, ret);
|
||||
-}
|
||||
-
|
||||
-static EFI_STATUS hash_many(
|
||||
- const void *old_seed,
|
||||
- const void *rng,
|
||||
- UINTN size,
|
||||
- const void *system_token,
|
||||
- UINTN system_token_size,
|
||||
- uint64_t uefi_monotonic_counter,
|
||||
- UINTN counter_start,
|
||||
- UINTN n,
|
||||
- void **ret) {
|
||||
-
|
||||
- _cleanup_free_ void *output = NULL;
|
||||
-
|
||||
- assert(old_seed);
|
||||
- assert(system_token_size == 0 || system_token);
|
||||
- assert(ret);
|
||||
-
|
||||
- /* Hashes the specified parameters in counter mode, generating n hash values, with the counter in the
|
||||
- * range counter_start…counter_start+n-1. */
|
||||
-
|
||||
- output = xmalloc_multiply(HASH_VALUE_SIZE, n);
|
||||
-
|
||||
- for (UINTN i = 0; i < n; i++)
|
||||
- hash_once(old_seed, rng, size,
|
||||
- system_token, system_token_size,
|
||||
- uefi_monotonic_counter,
|
||||
- counter_start + i,
|
||||
- (uint8_t*) output + (i * HASH_VALUE_SIZE));
|
||||
-
|
||||
- *ret = TAKE_PTR(output);
|
||||
- return EFI_SUCCESS;
|
||||
-}
|
||||
-
|
||||
-static EFI_STATUS mangle_random_seed(
|
||||
- const void *old_seed,
|
||||
- const void *rng,
|
||||
- UINTN size,
|
||||
- const void *system_token,
|
||||
- UINTN system_token_size,
|
||||
- uint64_t uefi_monotonic_counter,
|
||||
- void **ret_new_seed,
|
||||
- void **ret_for_kernel) {
|
||||
-
|
||||
- _cleanup_free_ void *new_seed = NULL, *for_kernel = NULL;
|
||||
- EFI_STATUS err;
|
||||
- UINTN n;
|
||||
-
|
||||
- assert(old_seed);
|
||||
- assert(system_token_size == 0 || system_token);
|
||||
- assert(ret_new_seed);
|
||||
- assert(ret_for_kernel);
|
||||
-
|
||||
- /* This takes the old seed file contents, an (optional) random number acquired from the UEFI RNG, an
|
||||
- * (optional) system 'token' installed once by the OS installer in an EFI variable, and hashes them
|
||||
- * together in counter mode, generating a new seed (to replace the file on disk) and the seed for the
|
||||
- * kernel. To keep things simple, the new seed and kernel data have the same size as the old seed and
|
||||
- * RNG data. */
|
||||
-
|
||||
- n = (size + HASH_VALUE_SIZE - 1) / HASH_VALUE_SIZE;
|
||||
-
|
||||
- /* Begin hashing in counter mode at counter 0 for the new seed for the disk */
|
||||
- err = hash_many(old_seed, rng, size, system_token, system_token_size, uefi_monotonic_counter, 0, n, &new_seed);
|
||||
- if (err != EFI_SUCCESS)
|
||||
- return err;
|
||||
-
|
||||
- /* Continue counting at 'n' for the seed for the kernel */
|
||||
- err = hash_many(old_seed, rng, size, system_token, system_token_size, uefi_monotonic_counter, n, n, &for_kernel);
|
||||
- if (err != EFI_SUCCESS)
|
||||
- return err;
|
||||
-
|
||||
- *ret_new_seed = TAKE_PTR(new_seed);
|
||||
- *ret_for_kernel = TAKE_PTR(for_kernel);
|
||||
-
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -164,6 +60,7 @@ static EFI_STATUS acquire_system_token(void **ret, UINTN *ret_size) {
|
||||
assert(ret);
|
||||
assert(ret_size);
|
||||
|
||||
+ *ret_size = 0;
|
||||
err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size);
|
||||
if (err != EFI_SUCCESS) {
|
||||
if (err != EFI_NOT_FOUND)
|
||||
@@ -221,32 +118,88 @@ static void validate_sha256(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
-EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
|
||||
- _cleanup_free_ void *seed = NULL, *new_seed = NULL, *rng = NULL, *for_kernel = NULL, *system_token = NULL;
|
||||
+EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
+ uint8_t random_bytes[DESIRED_SEED_SIZE], hash_key[HASH_VALUE_SIZE];
|
||||
+ _cleanup_free_ struct linux_efi_random_seed *new_seed_table = NULL;
|
||||
+ struct linux_efi_random_seed *previous_seed_table = NULL;
|
||||
+ _cleanup_free_ void *seed = NULL, *system_token = NULL;
|
||||
_cleanup_(file_closep) EFI_FILE *handle = NULL;
|
||||
- UINTN size, rsize, wsize, system_token_size = 0;
|
||||
_cleanup_free_ EFI_FILE_INFO *info = NULL;
|
||||
+ struct sha256_ctx hash;
|
||||
uint64_t uefi_monotonic_counter = 0;
|
||||
+ size_t size, rsize, wsize;
|
||||
+ bool seeded_by_efi = false;
|
||||
EFI_STATUS err;
|
||||
+ EFI_TIME now;
|
||||
+
|
||||
+ CLEANUP_ERASE(random_bytes);
|
||||
+ CLEANUP_ERASE(hash_key);
|
||||
+ CLEANUP_ERASE(hash);
|
||||
|
||||
assert(root_dir);
|
||||
+ assert_cc(DESIRED_SEED_SIZE == HASH_VALUE_SIZE);
|
||||
|
||||
validate_sha256();
|
||||
|
||||
if (mode == RANDOM_SEED_OFF)
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
- /* Let's better be safe than sorry, and for now disable this logic in SecureBoot mode, so that we
|
||||
- * don't credit a random seed that is not authenticated. */
|
||||
- if (secure_boot_enabled())
|
||||
- return EFI_NOT_FOUND;
|
||||
+ /* hash = LABEL || sizeof(input1) || input1 || ... || sizeof(inputN) || inputN */
|
||||
+ sha256_init_ctx(&hash);
|
||||
+
|
||||
+ /* Some basic domain separation in case somebody uses this data elsewhere */
|
||||
+ sha256_process_bytes(HASH_LABEL, sizeof(HASH_LABEL) - 1, &hash);
|
||||
+
|
||||
+ for (size_t i = 0; i < ST->NumberOfTableEntries; ++i)
|
||||
+ if (memcmp(&(const EFI_GUID)LINUX_EFI_RANDOM_SEED_TABLE_GUID,
|
||||
+ &ST->ConfigurationTable[i].VendorGuid, sizeof(EFI_GUID)) == 0) {
|
||||
+ previous_seed_table = ST->ConfigurationTable[i].VendorTable;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (!previous_seed_table) {
|
||||
+ size = 0;
|
||||
+ sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
+ } else {
|
||||
+ size = previous_seed_table->size;
|
||||
+ seeded_by_efi = size >= DESIRED_SEED_SIZE;
|
||||
+ sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
+ sha256_process_bytes(previous_seed_table->seed, size, &hash);
|
||||
+
|
||||
+ /* Zero and free the previous seed table only at the end after we've managed to install a new
|
||||
+ * one, so that in case this function fails or aborts, Linux still receives whatever the
|
||||
+ * previous bootloader chain set. So, the next line of this block is not an explicit_bzero()
|
||||
+ * call. */
|
||||
+ }
|
||||
+
|
||||
+ /* Request some random data from the UEFI RNG. We don't need this to work safely, but it's a good
|
||||
+ * idea to use it because it helps us for cases where users mistakenly include a random seed in
|
||||
+ * golden master images that are replicated many times. */
|
||||
+ err = acquire_rng(random_bytes, sizeof(random_bytes));
|
||||
+ if (err != EFI_SUCCESS) {
|
||||
+ size = 0;
|
||||
+ /* If we can't get any randomness from EFI itself, then we'll only be relying on what's in
|
||||
+ * ESP. But ESP is mutable, so if secure boot is enabled, we probably shouldn't trust that
|
||||
+ * alone, in which case we bail out early. */
|
||||
+ if (!seeded_by_efi && secure_boot_enabled())
|
||||
+ return EFI_NOT_FOUND;
|
||||
+ } else {
|
||||
+ seeded_by_efi = true;
|
||||
+ size = sizeof(random_bytes);
|
||||
+ }
|
||||
+ sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
+ sha256_process_bytes(random_bytes, size, &hash);
|
||||
|
||||
/* Get some system specific seed that the installer might have placed in an EFI variable. We include
|
||||
* it in our hash. This is protection against golden master image sloppiness, and it remains on the
|
||||
* system, even when disk images are duplicated or swapped out. */
|
||||
- err = acquire_system_token(&system_token, &system_token_size);
|
||||
- if (mode != RANDOM_SEED_ALWAYS && err != EFI_SUCCESS)
|
||||
+ err = acquire_system_token(&system_token, &size);
|
||||
+ if (mode != RANDOM_SEED_ALWAYS && (err != EFI_SUCCESS || size < DESIRED_SEED_SIZE) && !seeded_by_efi)
|
||||
return err;
|
||||
+ sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
+ if (system_token) {
|
||||
+ sha256_process_bytes(system_token, size, &hash);
|
||||
+ explicit_bzero_safe(system_token, size);
|
||||
+ }
|
||||
|
||||
err = root_dir->Open(
|
||||
root_dir,
|
||||
@@ -262,7 +215,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
|
||||
|
||||
err = get_file_info_harder(handle, &info, NULL);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to get file info for random seed: %r");
|
||||
+ return log_error_status_stall(err, L"Failed to get file info for random seed: %r", err);
|
||||
|
||||
size = info->FileSize;
|
||||
if (size < RANDOM_MAX_SIZE_MIN)
|
||||
@@ -272,51 +225,105 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
|
||||
return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too large.");
|
||||
|
||||
seed = xmalloc(size);
|
||||
-
|
||||
rsize = size;
|
||||
err = handle->Read(handle, &rsize, seed);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Failed to read random seed file: %r", err);
|
||||
- if (rsize != size)
|
||||
+ if (rsize != size) {
|
||||
+ explicit_bzero_safe(seed, rsize);
|
||||
return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short read on random seed file.");
|
||||
+ }
|
||||
+
|
||||
+ sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
+ sha256_process_bytes(seed, size, &hash);
|
||||
+ explicit_bzero_safe(seed, size);
|
||||
|
||||
err = handle->SetPosition(handle, 0);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err);
|
||||
|
||||
- /* Request some random data from the UEFI RNG. We don't need this to work safely, but it's a good
|
||||
- * idea to use it because it helps us for cases where users mistakenly include a random seed in
|
||||
- * golden master images that are replicated many times. */
|
||||
- (void) acquire_rng(size, &rng); /* It's fine if this fails */
|
||||
-
|
||||
/* Let's also include the UEFI monotonic counter (which is supposedly increasing on every single
|
||||
* boot) in the hash, so that even if the changes to the ESP for some reason should not be
|
||||
* persistent, the random seed we generate will still be different on every single boot. */
|
||||
err = BS->GetNextMonotonicCount(&uefi_monotonic_counter);
|
||||
- if (err != EFI_SUCCESS)
|
||||
+ if (err != EFI_SUCCESS && !seeded_by_efi)
|
||||
return log_error_status_stall(err, L"Failed to acquire UEFI monotonic counter: %r", err);
|
||||
-
|
||||
- /* Calculate new random seed for the disk and what to pass to the kernel */
|
||||
- err = mangle_random_seed(seed, rng, size, system_token, system_token_size, uefi_monotonic_counter, &new_seed, &for_kernel);
|
||||
- if (err != EFI_SUCCESS)
|
||||
- return err;
|
||||
-
|
||||
+ size = sizeof(uefi_monotonic_counter);
|
||||
+ sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
+ sha256_process_bytes(&uefi_monotonic_counter, size, &hash);
|
||||
+ err = RT->GetTime(&now, NULL);
|
||||
+ size = err == EFI_SUCCESS ? sizeof(now) : 0; /* Known to be flaky, so don't bark on error. */
|
||||
+ sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
+ sha256_process_bytes(&now, size, &hash);
|
||||
+
|
||||
+ /* hash_key = HASH(hash) */
|
||||
+ sha256_finish_ctx(&hash, hash_key);
|
||||
+
|
||||
+ /* hash = hash_key || 0 */
|
||||
+ sha256_init_ctx(&hash);
|
||||
+ sha256_process_bytes(hash_key, sizeof(hash_key), &hash);
|
||||
+ sha256_process_bytes(&(const uint8_t){ 0 }, sizeof(uint8_t), &hash);
|
||||
+ /* random_bytes = HASH(hash) */
|
||||
+ sha256_finish_ctx(&hash, random_bytes);
|
||||
+
|
||||
+ size = sizeof(random_bytes);
|
||||
+ /* If the file size is too large, zero out the remaining bytes on disk, and then truncate. */
|
||||
+ if (size < info->FileSize) {
|
||||
+ err = handle->SetPosition(handle, size);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status_stall(err, L"Failed to seek to offset of random seed file: %r", err);
|
||||
+ wsize = info->FileSize - size;
|
||||
+ err = handle->Write(handle, &wsize, seed /* All zeros now */);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status_stall(err, L"Failed to write random seed file: %r", err);
|
||||
+ if (wsize != info->FileSize - size)
|
||||
+ return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short write on random seed file.");
|
||||
+ err = handle->Flush(handle);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status_stall(err, L"Failed to flush random seed file: %r", err);
|
||||
+ err = handle->SetPosition(handle, 0);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err);
|
||||
+ info->FileSize = size;
|
||||
+ err = handle->SetInfo(handle, &GenericFileInfo, info->Size, info);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status_stall(err, L"Failed to truncate random seed file: %r", err);
|
||||
+ }
|
||||
/* Update the random seed on disk before we use it */
|
||||
wsize = size;
|
||||
- err = handle->Write(handle, &wsize, new_seed);
|
||||
+ err = handle->Write(handle, &wsize, random_bytes);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Failed to write random seed file: %r", err);
|
||||
if (wsize != size)
|
||||
return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short write on random seed file.");
|
||||
-
|
||||
err = handle->Flush(handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Failed to flush random seed file: %r", err);
|
||||
|
||||
- /* We are good to go */
|
||||
- err = efivar_set_raw(LOADER_GUID, L"LoaderRandomSeed", for_kernel, size, 0);
|
||||
+ err = BS->AllocatePool(EfiACPIReclaimMemory, sizeof(*new_seed_table) + DESIRED_SEED_SIZE,
|
||||
+ (void **) &new_seed_table);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status_stall(err, L"Failed to allocate EFI table for random seed: %r", err);
|
||||
+ new_seed_table->size = DESIRED_SEED_SIZE;
|
||||
+
|
||||
+ /* hash = hash_key || 1 */
|
||||
+ sha256_init_ctx(&hash);
|
||||
+ sha256_process_bytes(hash_key, sizeof(hash_key), &hash);
|
||||
+ sha256_process_bytes(&(const uint8_t){ 1 }, sizeof(uint8_t), &hash);
|
||||
+ /* new_seed_table->seed = HASH(hash) */
|
||||
+ sha256_finish_ctx(&hash, new_seed_table->seed);
|
||||
+
|
||||
+ err = BS->InstallConfigurationTable(&(EFI_GUID)LINUX_EFI_RANDOM_SEED_TABLE_GUID, new_seed_table);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to write random seed to EFI variable: %r", err);
|
||||
+ return log_error_status_stall(err, L"Failed to install EFI table for random seed: %r", err);
|
||||
+ TAKE_PTR(new_seed_table);
|
||||
+
|
||||
+ if (previous_seed_table) {
|
||||
+ /* Now that we've succeeded in installing the new table, we can safely nuke the old one. */
|
||||
+ explicit_bzero_safe(previous_seed_table->seed, previous_seed_table->size);
|
||||
+ explicit_bzero_safe(previous_seed_table, sizeof(*previous_seed_table));
|
||||
+ free(previous_seed_table);
|
||||
+ }
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
diff --git a/src/core/efi-random.c b/src/core/efi-random.c
|
||||
index 4086b12739..61516775fc 100644
|
||||
--- a/src/core/efi-random.c
|
||||
+++ b/src/core/efi-random.c
|
||||
@@ -12,79 +12,23 @@
|
||||
#include "random-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
-/* If a random seed was passed by the boot loader in the LoaderRandomSeed EFI variable, let's credit it to
|
||||
- * the kernel's random pool, but only once per boot. If this is run very early during initialization we can
|
||||
- * instantly boot up with a filled random pool.
|
||||
- *
|
||||
- * This makes no judgement on the entropy passed, it's the job of the boot loader to only pass us a seed that
|
||||
- * is suitably validated. */
|
||||
-
|
||||
-static void lock_down_efi_variables(void) {
|
||||
+void lock_down_efi_variables(void) {
|
||||
+ _cleanup_close_ int fd = -1;
|
||||
int r;
|
||||
|
||||
+ fd = open(EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderSystemToken)), O_RDONLY|O_CLOEXEC);
|
||||
+ if (fd < 0) {
|
||||
+ if (errno != ENOENT)
|
||||
+ log_warning_errno(errno, "Unable to open LoaderSystemToken EFI variable, ignoring: %m");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* Paranoia: let's restrict access modes of these a bit, so that unprivileged users can't use them to
|
||||
* identify the system or gain too much insight into what we might have credited to the entropy
|
||||
* pool. */
|
||||
- FOREACH_STRING(path,
|
||||
- EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderRandomSeed)),
|
||||
- EFIVAR_PATH(EFI_LOADER_VARIABLE(LoaderSystemToken))) {
|
||||
-
|
||||
- r = chattr_path(path, 0, FS_IMMUTABLE_FL, NULL);
|
||||
- if (r == -ENOENT)
|
||||
- continue;
|
||||
- if (r < 0)
|
||||
- log_warning_errno(r, "Failed to drop FS_IMMUTABLE_FL from %s, ignoring: %m", path);
|
||||
-
|
||||
- if (chmod(path, 0600) < 0)
|
||||
- log_warning_errno(errno, "Failed to reduce access mode of %s, ignoring: %m", path);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-int efi_take_random_seed(void) {
|
||||
- _cleanup_free_ void *value = NULL;
|
||||
- size_t size;
|
||||
- int r;
|
||||
-
|
||||
- /* Paranoia comes first. */
|
||||
- lock_down_efi_variables();
|
||||
-
|
||||
- if (access("/run/systemd/efi-random-seed-taken", F_OK) < 0) {
|
||||
- if (errno != ENOENT) {
|
||||
- log_warning_errno(errno, "Failed to determine whether we already used the random seed token, not using it.");
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- /* ENOENT means we haven't used it yet. */
|
||||
- } else {
|
||||
- log_debug("EFI random seed already used, not using again.");
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- r = efi_get_variable(EFI_LOADER_VARIABLE(LoaderRandomSeed), NULL, &value, &size);
|
||||
- if (r == -EOPNOTSUPP) {
|
||||
- log_debug_errno(r, "System lacks EFI support, not initializing random seed from EFI variable.");
|
||||
- return 0;
|
||||
- }
|
||||
- if (r == -ENOENT) {
|
||||
- log_debug_errno(r, "Boot loader did not pass LoaderRandomSeed EFI variable, not crediting any entropy.");
|
||||
- return 0;
|
||||
- }
|
||||
+ r = chattr_fd(fd, 0, FS_IMMUTABLE_FL, NULL);
|
||||
if (r < 0)
|
||||
- return log_warning_errno(r, "Failed to read LoaderRandomSeed EFI variable, ignoring: %m");
|
||||
-
|
||||
- if (size == 0)
|
||||
- return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Random seed passed from boot loader has zero size? Ignoring.");
|
||||
-
|
||||
- /* Before we use the seed, let's mark it as used, so that we never credit it twice. Also, it's a nice
|
||||
- * way to let users known that we successfully acquired entropy from the boot loader. */
|
||||
- r = touch("/run/systemd/efi-random-seed-taken");
|
||||
- if (r < 0)
|
||||
- return log_warning_errno(r, "Unable to mark EFI random seed as used, not using it: %m");
|
||||
-
|
||||
- r = random_write_entropy(-1, value, size, true);
|
||||
- if (r < 0)
|
||||
- return log_warning_errno(errno, "Failed to credit entropy, ignoring: %m");
|
||||
-
|
||||
- log_info("Successfully credited entropy passed from boot loader.");
|
||||
- return 1;
|
||||
+ log_warning_errno(r, "Failed to drop FS_IMMUTABLE_FL from LoaderSystemToken EFI variable, ignoring: %m");
|
||||
+ if (fchmod(fd, 0600) < 0)
|
||||
+ log_warning_errno(errno, "Failed to reduce access mode of LoaderSystemToken EFI variable, ignoring: %m");
|
||||
}
|
||||
diff --git a/src/core/efi-random.h b/src/core/efi-random.h
|
||||
index 7d20fff57d..87166c9e3f 100644
|
||||
--- a/src/core/efi-random.h
|
||||
+++ b/src/core/efi-random.h
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
-int efi_take_random_seed(void);
|
||||
+void lock_down_efi_variables(void);
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index 126a4bce8c..e7b8e98bca 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -2840,8 +2840,8 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
- /* The efivarfs is now mounted, let's read the random seed off it */
|
||||
- (void) efi_take_random_seed();
|
||||
+ /* The efivarfs is now mounted, let's lock down the system token. */
|
||||
+ lock_down_efi_variables();
|
||||
|
||||
/* Cache command-line options passed from EFI variables */
|
||||
if (!skip_setup)
|
||||
diff --git a/units/systemd-boot-system-token.service b/units/systemd-boot-system-token.service
|
||||
index 662a1fda04..5a56d7c331 100644
|
||||
--- a/units/systemd-boot-system-token.service
|
||||
+++ b/units/systemd-boot-system-token.service
|
||||
@@ -26,9 +26,6 @@ ConditionPathExists=/sys/firmware/efi/efivars/LoaderFeatures-4a67b082-0a4c-41cf-
|
||||
# Only run this if there is no system token defined yet, or …
|
||||
ConditionPathExists=|!/sys/firmware/efi/efivars/LoaderSystemToken-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
|
||||
|
||||
-# … if the boot loader didn't pass the OS a random seed (and thus probably was missing the random seed file)
|
||||
-ConditionPathExists=|!/sys/firmware/efi/efivars/LoaderRandomSeed-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
|
||||
-
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
213
0666-random-seed-refresh-EFI-boot-seed-when-writing-a-new.patch
Normal file
213
0666-random-seed-refresh-EFI-boot-seed-when-writing-a-new.patch
Normal file
@ -0,0 +1,213 @@
|
||||
From 461ba7436d539258744d03400490ef100095e093 Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Fri, 11 Nov 2022 15:22:35 +0100
|
||||
Subject: [PATCH] random-seed: refresh EFI boot seed when writing a new seed
|
||||
|
||||
Since this runs at shutdown to write a new seed, we should also keep the
|
||||
bootloader's seed maximally fresh by doing the same. So we follow the
|
||||
same pattern - hash some new random bytes with the old seed to make a
|
||||
new seed. We let this fail without warning, because it's just an
|
||||
opportunistic thing. If the user happens to have set up the random seed
|
||||
with bootctl, and the RNG is initialized, then things should be fine. If
|
||||
not, we create a new seed if systemd-boot is in use. And if not, then we
|
||||
just don't do anything.
|
||||
|
||||
(cherry picked from commit f913c784ad4c93894fd6cb2590738113dff5a694)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/random-seed/random-seed.c | 123 +++++++++++++++++++++++++++++++---
|
||||
1 file changed, 112 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index b548f92bbe..54ec3aa7d5 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -15,7 +15,11 @@
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
+#include "build.h"
|
||||
+#include "chase-symlinks.h"
|
||||
+#include "efi-loader.h"
|
||||
#include "fd-util.h"
|
||||
+#include "find-esp.h"
|
||||
#include "fs-util.h"
|
||||
#include "io-util.h"
|
||||
#include "log.h"
|
||||
@@ -25,6 +29,7 @@
|
||||
#include "mkdir.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
+#include "path-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "random-util.h"
|
||||
#include "string-table.h"
|
||||
@@ -185,7 +190,7 @@ static int load_seed_file(
|
||||
if (ret_hash_state) {
|
||||
struct sha256_ctx *hash_state;
|
||||
|
||||
- hash_state = malloc(sizeof(struct sha256_ctx));
|
||||
+ hash_state = new(struct sha256_ctx, 1);
|
||||
if (!hash_state)
|
||||
return log_oom();
|
||||
|
||||
@@ -311,6 +316,101 @@ static int save_seed_file(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int refresh_boot_seed(void) {
|
||||
+ uint8_t buffer[RANDOM_EFI_SEED_SIZE];
|
||||
+ struct sha256_ctx hash_state;
|
||||
+ _cleanup_free_ void *seed_file_bytes = NULL;
|
||||
+ _cleanup_free_ char *esp_path = NULL;
|
||||
+ _cleanup_close_ int seed_fd = -1;
|
||||
+ size_t len;
|
||||
+ ssize_t r;
|
||||
+
|
||||
+ assert_cc(RANDOM_EFI_SEED_SIZE == SHA256_DIGEST_SIZE);
|
||||
+
|
||||
+ r = find_esp_and_warn(NULL, NULL, /* unprivileged_mode= */ false, &esp_path,
|
||||
+ NULL, NULL, NULL, NULL, NULL);
|
||||
+ if (r < 0) {
|
||||
+ if (r == -ENOKEY) {
|
||||
+ log_debug_errno(r, "Couldn't find any ESP, so not updating ESP random seed.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return r; /* find_esp_and_warn() already logged */
|
||||
+ }
|
||||
+
|
||||
+ seed_fd = chase_symlinks_and_open("/loader/random-seed", esp_path,
|
||||
+ CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS,
|
||||
+ O_RDWR|O_CLOEXEC|O_NOCTTY, NULL);
|
||||
+ if (seed_fd == -ENOENT) {
|
||||
+ uint64_t features;
|
||||
+
|
||||
+ r = efi_loader_get_features(&features);
|
||||
+ if (r == 0 && FLAGS_SET(features, EFI_LOADER_FEATURE_RANDOM_SEED)) {
|
||||
+ int dir_fd = chase_symlinks_and_open("/loader", esp_path,
|
||||
+ CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS,
|
||||
+ O_DIRECTORY|O_CLOEXEC|O_NOCTTY, NULL);
|
||||
+ if (dir_fd >= 0) {
|
||||
+ seed_fd = openat(dir_fd, "random-seed", O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
|
||||
+ close(dir_fd);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (seed_fd < 0) {
|
||||
+ log_debug_errno(seed_fd, "Failed to open EFI seed path: %m");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ r = random_seed_size(seed_fd, &len);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to determine EFI seed path length: %m");
|
||||
+ seed_file_bytes = malloc(len);
|
||||
+ if (!seed_file_bytes)
|
||||
+ return log_oom();
|
||||
+ r = loop_read(seed_fd, seed_file_bytes, len, false);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to read EFI seed file: %m");
|
||||
+
|
||||
+ /* Hash the old seed in so that we never regress in entropy. */
|
||||
+ sha256_init_ctx(&hash_state);
|
||||
+ sha256_process_bytes(&r, sizeof(r), &hash_state);
|
||||
+ sha256_process_bytes(seed_file_bytes, r, &hash_state);
|
||||
+
|
||||
+ /* We're doing this opportunistically, so if the seeding dance before didn't manage to initialize the
|
||||
+ * RNG, there's no point in doing it here. Secondly, getrandom(GRND_NONBLOCK) has been around longer
|
||||
+ * than EFI seeding anyway, so there's no point in having non-getrandom() fallbacks here. So if this
|
||||
+ * fails, just return early to cut our losses. */
|
||||
+ r = getrandom(buffer, sizeof(buffer), GRND_NONBLOCK);
|
||||
+ if (r < 0) {
|
||||
+ if (errno == EAGAIN) {
|
||||
+ log_debug_errno(errno, "Random pool not initialized yet, so skipping EFI seed update");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (errno == ENOSYS) {
|
||||
+ log_debug_errno(errno, "getrandom() not available, so skipping EFI seed update");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return log_error_errno(errno, "Failed to generate random bytes for EFI seed: %m");
|
||||
+ }
|
||||
+ assert(r == sizeof(buffer));
|
||||
+
|
||||
+ /* Hash the new seed into the state containing the old one to generate our final seed. */
|
||||
+ sha256_process_bytes(&r, sizeof(r), &hash_state);
|
||||
+ sha256_process_bytes(buffer, r, &hash_state);
|
||||
+ sha256_finish_ctx(&hash_state, buffer);
|
||||
+
|
||||
+ if (lseek(seed_fd, 0, SEEK_SET) < 0)
|
||||
+ return log_error_errno(errno, "Failed to seek to beginning of EFI seed file: %m");
|
||||
+ r = loop_write(seed_fd, buffer, sizeof(buffer), false);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to write new EFI seed file: %m");
|
||||
+ if (ftruncate(seed_fd, sizeof(buffer)) < 0)
|
||||
+ return log_error_errno(errno, "Failed to truncate EFI seed file: %m");
|
||||
+ r = fsync_full(seed_fd);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(errno, "Failed to fsync EFI seed file: %m");
|
||||
+
|
||||
+ log_debug("Updated random seed in ESP");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int help(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
@@ -402,15 +502,15 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m");
|
||||
|
||||
+ random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY);
|
||||
+ if (random_fd < 0)
|
||||
+ return log_error_errno(errno, "Failed to open /dev/urandom: %m");
|
||||
+
|
||||
/* When we load the seed we read it and write it to the device and then immediately update the saved
|
||||
* seed with new data, to make sure the next boot gets seeded differently. */
|
||||
|
||||
switch (arg_action) {
|
||||
case ACTION_LOAD:
|
||||
- random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY);
|
||||
- if (random_fd < 0)
|
||||
- return log_error_errno(errno, "Failed to open /dev/urandom: %m");
|
||||
-
|
||||
/* First, let's write the machine ID into /dev/urandom, not crediting entropy. See
|
||||
* load_machine_id() for an explanation why. */
|
||||
load_machine_id(random_fd);
|
||||
@@ -428,8 +528,10 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
log_full_errno(level, open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m");
|
||||
log_full_errno(level, errno, "Failed to open " RANDOM_SEED " for reading: %m");
|
||||
+ r = -errno;
|
||||
|
||||
- return missing ? 0 : -errno;
|
||||
+ (void) refresh_boot_seed();
|
||||
+ return missing ? 0 : r;
|
||||
}
|
||||
} else
|
||||
write_seed_file = true;
|
||||
@@ -439,10 +541,7 @@ static int run(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ACTION_SAVE:
|
||||
- random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
- if (random_fd < 0)
|
||||
- return log_error_errno(errno, "Failed to open /dev/urandom: %m");
|
||||
-
|
||||
+ (void) refresh_boot_seed();
|
||||
seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
|
||||
if (seed_fd < 0)
|
||||
return log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m");
|
||||
@@ -460,9 +559,11 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- if (read_seed_file)
|
||||
+ if (read_seed_file) {
|
||||
r = load_seed_file(seed_fd, random_fd, seed_size,
|
||||
write_seed_file ? &hash_state : NULL);
|
||||
+ (void) refresh_boot_seed();
|
||||
+ }
|
||||
|
||||
if (r >= 0 && write_seed_file)
|
||||
r = save_seed_file(seed_fd, random_fd, seed_size, synchronous, hash_state);
|
181
0667-random-seed-handle-post-merge-review-nits.patch
Normal file
181
0667-random-seed-handle-post-merge-review-nits.patch
Normal file
@ -0,0 +1,181 @@
|
||||
From 4c15a3931701cca73d78bb09953e439e7125e020 Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Wed, 16 Nov 2022 19:27:50 +0100
|
||||
Subject: [PATCH] random-seed: handle post-merge review nits
|
||||
|
||||
These are various misc things that came up after merging.
|
||||
|
||||
(cherry picked from commit 3daeef088410cdddef622007f95b0a1b4a439532)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/bootctl.c | 2 +-
|
||||
src/boot/efi/random-seed.c | 6 ++--
|
||||
src/random-seed/random-seed.c | 61 ++++++++++++++++++-----------------
|
||||
3 files changed, 36 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
|
||||
index e23a72fd38..8d45e11c2b 100644
|
||||
--- a/src/boot/bootctl.c
|
||||
+++ b/src/boot/bootctl.c
|
||||
@@ -1983,7 +1983,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
||||
|
||||
static int install_random_seed(const char *esp) {
|
||||
_cleanup_(unlink_and_freep) char *tmp = NULL;
|
||||
- unsigned char buffer[RANDOM_EFI_SEED_SIZE];
|
||||
+ uint8_t buffer[RANDOM_EFI_SEED_SIZE];
|
||||
_cleanup_free_ char *path = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
size_t token_size;
|
||||
diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c
|
||||
index c723160c0f..e11e345e88 100644
|
||||
--- a/src/boot/efi/random-seed.c
|
||||
+++ b/src/boot/efi/random-seed.c
|
||||
@@ -60,7 +60,6 @@ static EFI_STATUS acquire_system_token(void **ret, UINTN *ret_size) {
|
||||
assert(ret);
|
||||
assert(ret_size);
|
||||
|
||||
- *ret_size = 0;
|
||||
err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size);
|
||||
if (err != EFI_SUCCESS) {
|
||||
if (err != EFI_NOT_FOUND)
|
||||
@@ -192,6 +191,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
/* Get some system specific seed that the installer might have placed in an EFI variable. We include
|
||||
* it in our hash. This is protection against golden master image sloppiness, and it remains on the
|
||||
* system, even when disk images are duplicated or swapped out. */
|
||||
+ size = 0;
|
||||
err = acquire_system_token(&system_token, &size);
|
||||
if (mode != RANDOM_SEED_ALWAYS && (err != EFI_SUCCESS || size < DESIRED_SEED_SIZE) && !seeded_by_efi)
|
||||
return err;
|
||||
@@ -251,6 +251,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
size = sizeof(uefi_monotonic_counter);
|
||||
sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
sha256_process_bytes(&uefi_monotonic_counter, size, &hash);
|
||||
+
|
||||
err = RT->GetTime(&now, NULL);
|
||||
size = err == EFI_SUCCESS ? sizeof(now) : 0; /* Known to be flaky, so don't bark on error. */
|
||||
sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
@@ -300,7 +301,8 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Failed to flush random seed file: %r", err);
|
||||
|
||||
- err = BS->AllocatePool(EfiACPIReclaimMemory, sizeof(*new_seed_table) + DESIRED_SEED_SIZE,
|
||||
+ err = BS->AllocatePool(EfiACPIReclaimMemory,
|
||||
+ offsetof(struct linux_efi_random_seed, seed) + DESIRED_SEED_SIZE,
|
||||
(void **) &new_seed_table);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Failed to allocate EFI table for random seed: %r", err);
|
||||
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
|
||||
index 54ec3aa7d5..ab1f942289 100644
|
||||
--- a/src/random-seed/random-seed.c
|
||||
+++ b/src/random-seed/random-seed.c
|
||||
@@ -321,9 +321,10 @@ static int refresh_boot_seed(void) {
|
||||
struct sha256_ctx hash_state;
|
||||
_cleanup_free_ void *seed_file_bytes = NULL;
|
||||
_cleanup_free_ char *esp_path = NULL;
|
||||
- _cleanup_close_ int seed_fd = -1;
|
||||
+ _cleanup_close_ int seed_fd = -1, dir_fd = -1;
|
||||
size_t len;
|
||||
- ssize_t r;
|
||||
+ ssize_t n;
|
||||
+ int r;
|
||||
|
||||
assert_cc(RANDOM_EFI_SEED_SIZE == SHA256_DIGEST_SIZE);
|
||||
|
||||
@@ -337,48 +338,48 @@ static int refresh_boot_seed(void) {
|
||||
return r; /* find_esp_and_warn() already logged */
|
||||
}
|
||||
|
||||
- seed_fd = chase_symlinks_and_open("/loader/random-seed", esp_path,
|
||||
- CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS,
|
||||
- O_RDWR|O_CLOEXEC|O_NOCTTY, NULL);
|
||||
- if (seed_fd == -ENOENT) {
|
||||
+ r = chase_symlinks("/loader", esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, NULL, &dir_fd);
|
||||
+ if (r < 0) {
|
||||
+ if (r == -ENOENT) {
|
||||
+ log_debug_errno(r, "Couldn't find ESP loader directory, so not updating ESP random seed.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return log_error_errno(r, "Failed to open ESP loader directory: %m");
|
||||
+ }
|
||||
+ seed_fd = openat(dir_fd, "random-seed", O_NOFOLLOW|O_RDWR|O_CLOEXEC|O_NOCTTY);
|
||||
+ if (seed_fd < 0 && errno == ENOENT) {
|
||||
uint64_t features;
|
||||
-
|
||||
r = efi_loader_get_features(&features);
|
||||
- if (r == 0 && FLAGS_SET(features, EFI_LOADER_FEATURE_RANDOM_SEED)) {
|
||||
- int dir_fd = chase_symlinks_and_open("/loader", esp_path,
|
||||
- CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS,
|
||||
- O_DIRECTORY|O_CLOEXEC|O_NOCTTY, NULL);
|
||||
- if (dir_fd >= 0) {
|
||||
- seed_fd = openat(dir_fd, "random-seed", O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
|
||||
- close(dir_fd);
|
||||
- }
|
||||
+ if (r == 0 && FLAGS_SET(features, EFI_LOADER_FEATURE_RANDOM_SEED))
|
||||
+ seed_fd = openat(dir_fd, "random-seed", O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
|
||||
+ else {
|
||||
+ log_debug_errno(seed_fd, "Couldn't find ESP random seed, and not booted with systemd-boot, so not updating ESP random seed.");
|
||||
+ return 0;
|
||||
}
|
||||
}
|
||||
- if (seed_fd < 0) {
|
||||
- log_debug_errno(seed_fd, "Failed to open EFI seed path: %m");
|
||||
- return 0;
|
||||
- }
|
||||
+ if (seed_fd < 0)
|
||||
+ return log_error_errno(errno, "Failed to open EFI seed path: %m");
|
||||
r = random_seed_size(seed_fd, &len);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine EFI seed path length: %m");
|
||||
seed_file_bytes = malloc(len);
|
||||
if (!seed_file_bytes)
|
||||
return log_oom();
|
||||
- r = loop_read(seed_fd, seed_file_bytes, len, false);
|
||||
- if (r < 0)
|
||||
- return log_error_errno(r, "Failed to read EFI seed file: %m");
|
||||
+ n = loop_read(seed_fd, seed_file_bytes, len, false);
|
||||
+ if (n < 0)
|
||||
+ return log_error_errno(n, "Failed to read EFI seed file: %m");
|
||||
|
||||
/* Hash the old seed in so that we never regress in entropy. */
|
||||
sha256_init_ctx(&hash_state);
|
||||
- sha256_process_bytes(&r, sizeof(r), &hash_state);
|
||||
- sha256_process_bytes(seed_file_bytes, r, &hash_state);
|
||||
+ sha256_process_bytes(&n, sizeof(n), &hash_state);
|
||||
+ sha256_process_bytes(seed_file_bytes, n, &hash_state);
|
||||
|
||||
/* We're doing this opportunistically, so if the seeding dance before didn't manage to initialize the
|
||||
* RNG, there's no point in doing it here. Secondly, getrandom(GRND_NONBLOCK) has been around longer
|
||||
* than EFI seeding anyway, so there's no point in having non-getrandom() fallbacks here. So if this
|
||||
* fails, just return early to cut our losses. */
|
||||
- r = getrandom(buffer, sizeof(buffer), GRND_NONBLOCK);
|
||||
- if (r < 0) {
|
||||
+ n = getrandom(buffer, sizeof(buffer), GRND_NONBLOCK);
|
||||
+ if (n < 0) {
|
||||
if (errno == EAGAIN) {
|
||||
log_debug_errno(errno, "Random pool not initialized yet, so skipping EFI seed update");
|
||||
return 0;
|
||||
@@ -389,11 +390,11 @@ static int refresh_boot_seed(void) {
|
||||
}
|
||||
return log_error_errno(errno, "Failed to generate random bytes for EFI seed: %m");
|
||||
}
|
||||
- assert(r == sizeof(buffer));
|
||||
+ assert(n == sizeof(buffer));
|
||||
|
||||
/* Hash the new seed into the state containing the old one to generate our final seed. */
|
||||
- sha256_process_bytes(&r, sizeof(r), &hash_state);
|
||||
- sha256_process_bytes(buffer, r, &hash_state);
|
||||
+ sha256_process_bytes(&n, sizeof(n), &hash_state);
|
||||
+ sha256_process_bytes(buffer, n, &hash_state);
|
||||
sha256_finish_ctx(&hash_state, buffer);
|
||||
|
||||
if (lseek(seed_fd, 0, SEEK_SET) < 0)
|
||||
@@ -405,7 +406,7 @@ static int refresh_boot_seed(void) {
|
||||
return log_error_errno(errno, "Failed to truncate EFI seed file: %m");
|
||||
r = fsync_full(seed_fd);
|
||||
if (r < 0)
|
||||
- return log_error_errno(errno, "Failed to fsync EFI seed file: %m");
|
||||
+ return log_error_errno(r, "Failed to fsync EFI seed file: %m");
|
||||
|
||||
log_debug("Updated random seed in ESP");
|
||||
return 0;
|
50
0668-boot-do-not-truncate-random-seed-file.patch
Normal file
50
0668-boot-do-not-truncate-random-seed-file.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 2d6ce79b1d727cd85d3504706da9c2eca6dc72fe Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Wed, 16 Nov 2022 19:34:53 +0100
|
||||
Subject: [PATCH] boot: do not truncate random seed file
|
||||
|
||||
There are concerns about the FAT file system driver exploding if we try
|
||||
to do this, so just leave the bytes zeroed out instead.
|
||||
|
||||
(cherry picked from commit 5d29d07b342397a8ecc4bea96f53595a03dd94f1)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/random-seed.c | 17 ++++++++++++-----
|
||||
1 file changed, 12 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c
|
||||
index e11e345e88..471398fbf1 100644
|
||||
--- a/src/boot/efi/random-seed.c
|
||||
+++ b/src/boot/efi/random-seed.c
|
||||
@@ -268,7 +268,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
sha256_finish_ctx(&hash, random_bytes);
|
||||
|
||||
size = sizeof(random_bytes);
|
||||
- /* If the file size is too large, zero out the remaining bytes on disk, and then truncate. */
|
||||
+ /* If the file size is too large, zero out the remaining bytes on disk. */
|
||||
if (size < info->FileSize) {
|
||||
err = handle->SetPosition(handle, size);
|
||||
if (err != EFI_SUCCESS)
|
||||
@@ -285,10 +285,17 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
err = handle->SetPosition(handle, 0);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err);
|
||||
- info->FileSize = size;
|
||||
- err = handle->SetInfo(handle, &GenericFileInfo, info->Size, info);
|
||||
- if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to truncate random seed file: %r", err);
|
||||
+
|
||||
+ /* We could truncate the file here with something like:
|
||||
+ *
|
||||
+ * info->FileSize = size;
|
||||
+ * err = handle->SetInfo(handle, &GenericFileInfo, info->Size, info);
|
||||
+ * if (err != EFI_SUCCESS)
|
||||
+ * return log_error_status_stall(err, L"Failed to truncate random seed file: %r", err);
|
||||
+ *
|
||||
+ * But this is considered slightly risky, because EFI filesystem drivers are a little bit
|
||||
+ * flimsy. So instead we rely on userspace eventually truncating this when it writes a new
|
||||
+ * seed. For now the best we do is zero it. */
|
||||
}
|
||||
/* Update the random seed on disk before we use it */
|
||||
wsize = size;
|
117
0669-bootctl-install-system-token-on-virtualized-systems.patch
Normal file
117
0669-bootctl-install-system-token-on-virtualized-systems.patch
Normal file
@ -0,0 +1,117 @@
|
||||
From 36e71ba28d490bb3dba34df8eef472c1560e3772 Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Thu, 17 Nov 2022 16:11:44 +0100
|
||||
Subject: [PATCH] bootctl: install system token on virtualized systems
|
||||
|
||||
Removing the virtualization check might not be the worst thing in the
|
||||
world, and would potentially get many, many more systems properly seeded
|
||||
rather than not seeded. There are a few reasons to consider this:
|
||||
|
||||
- In most QEMU setups and most guides on how to setup QEMU, a separate
|
||||
pflash file is used for nvram variables, and this generally isn't
|
||||
copied around.
|
||||
|
||||
- We're now hashing in a timestamp, which should provide some level of
|
||||
differentiation, given that EFI_TIME has a nanoseconds field.
|
||||
|
||||
- The kernel itself will additionally hash in: a high resolution time
|
||||
stamp, a cycle counter, RDRAND output, the VMGENID uniquely
|
||||
identifying the virtual machine, any other seeds from the hypervisor
|
||||
(like from FDT or setup_data).
|
||||
|
||||
- During early boot, the RNG is reseeded quite frequently to account for
|
||||
the importance of early differentiation.
|
||||
|
||||
So maybe the mitigating factors make the actual feared problem
|
||||
significantly less likely and therefore the pros of having file-based
|
||||
seeding might outweigh the cons of weird misconfigured setups having a
|
||||
hypothetical problem on first boot.
|
||||
|
||||
(cherry picked from commit a4eea6038c1c7f88adc6d6584d18ea60ea11b08f)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
docs/RANDOM_SEEDS.md | 15 ++++-----------
|
||||
src/boot/bootctl.c | 20 --------------------
|
||||
units/systemd-boot-system-token.service | 8 ++------
|
||||
3 files changed, 6 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/docs/RANDOM_SEEDS.md b/docs/RANDOM_SEEDS.md
|
||||
index b7240f0d89..a1134d6417 100644
|
||||
--- a/docs/RANDOM_SEEDS.md
|
||||
+++ b/docs/RANDOM_SEEDS.md
|
||||
@@ -232,17 +232,10 @@ boot, in order to ensure the entropy pool is filled up quickly.
|
||||
too), which should be safe even with FAT file system drivers built into
|
||||
low-quality EFI firmwares.
|
||||
|
||||
- As a special restriction: in virtualized environments PID 1 will refrain
|
||||
- from using this mechanism, for safety reasons. This is because on VM
|
||||
- environments the EFI variable space and the disk space is generally not
|
||||
- maintained physically separate (for example, `qemu` in EFI mode stores the
|
||||
- variables in the ESP itself). The robustness towards sloppy OS image
|
||||
- generation is the main purpose of maintaining the 'system token' however,
|
||||
- and if the EFI variable storage is not kept physically separate from the OS
|
||||
- image there's no point in it. That said, OS builders that know that they are
|
||||
- not going to replicate the built image on multiple systems may opt to turn
|
||||
- off the 'system token' concept by setting `random-seed-mode always` in the
|
||||
- ESP's
|
||||
+ If the system token is not desired but this seeding mechanism still is, OS
|
||||
+ builders that know that they are not going to replicate the built image on
|
||||
+ multiple systems may opt to turn off the 'system token' concept by setting
|
||||
+ `random-seed-mode always` in the ESP's
|
||||
[`/loader/loader.conf`](https://www.freedesktop.org/software/systemd/man/loader.conf.html)
|
||||
file. If done, `systemd-boot` will use the random seed file even if no
|
||||
system token is found in EFI variables.
|
||||
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
|
||||
index 8d45e11c2b..d495c72bdd 100644
|
||||
--- a/src/boot/bootctl.c
|
||||
+++ b/src/boot/bootctl.c
|
||||
@@ -2048,26 +2048,6 @@ static int install_random_seed(const char *esp) {
|
||||
if (r < 0) {
|
||||
if (r != -ENXIO)
|
||||
log_warning_errno(r, "Failed to parse $SYSTEMD_WRITE_SYSTEM_TOKEN, ignoring.");
|
||||
-
|
||||
- if (detect_vm() > 0) {
|
||||
- /* Let's not write a system token if we detect we are running in a VM
|
||||
- * environment. Why? Our default security model for the random seed uses the system
|
||||
- * token as a mechanism to ensure we are not vulnerable to golden master sloppiness
|
||||
- * issues, i.e. that people initialize the random seed file, then copy the image to
|
||||
- * many systems and end up with the same random seed in each that is assumed to be
|
||||
- * valid but in reality is the same for all machines. By storing a system token in
|
||||
- * the EFI variable space we can make sure that even though the random seeds on disk
|
||||
- * are all the same they will be different on each system under the assumption that
|
||||
- * the EFI variable space is maintained separate from the random seed storage. That
|
||||
- * is generally the case on physical systems, as the ESP is stored on persistent
|
||||
- * storage, and the EFI variables in NVRAM. However in virtualized environments this
|
||||
- * is generally not true: the EFI variable set is typically stored along with the
|
||||
- * disk image itself. For example, using the OVMF EFI firmware the EFI variables are
|
||||
- * stored in a file in the ESP itself. */
|
||||
-
|
||||
- log_notice("Not installing system token, since we are running in a virtualized environment.");
|
||||
- return 0;
|
||||
- }
|
||||
} else if (r == 0) {
|
||||
log_notice("Not writing system token, because $SYSTEMD_WRITE_SYSTEM_TOKEN is set to false.");
|
||||
return 0;
|
||||
diff --git a/units/systemd-boot-system-token.service b/units/systemd-boot-system-token.service
|
||||
index 5a56d7c331..689b902000 100644
|
||||
--- a/units/systemd-boot-system-token.service
|
||||
+++ b/units/systemd-boot-system-token.service
|
||||
@@ -16,15 +16,11 @@ After=local-fs.target systemd-random-seed.service
|
||||
Conflicts=shutdown.target initrd-switch-root.target
|
||||
Before=shutdown.target initrd-switch-root.target
|
||||
|
||||
-# Don't run this in a VM environment, because there EFI variables are not
|
||||
-# actually stored in NVRAM, independent of regular storage.
|
||||
-ConditionVirtualization=no
|
||||
-
|
||||
# Only run this if the boot loader can support random seed initialization.
|
||||
ConditionPathExists=/sys/firmware/efi/efivars/LoaderFeatures-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
|
||||
|
||||
-# Only run this if there is no system token defined yet, or …
|
||||
-ConditionPathExists=|!/sys/firmware/efi/efivars/LoaderSystemToken-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
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
221
0670-boot-remove-random-seed-mode.patch
Normal file
221
0670-boot-remove-random-seed-mode.patch
Normal file
@ -0,0 +1,221 @@
|
||||
From 44f9f0e2e416b67c2ca46e9e36184f4a0bf1f1b0 Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Mon, 21 Nov 2022 16:40:24 +0100
|
||||
Subject: [PATCH] boot: remove random-seed-mode
|
||||
|
||||
Now that the random seed is used on virtualized systems, there's no
|
||||
point in having a random-seed-mode toggle switch. Let's just always
|
||||
require it now, with the existing logic already being there to allow not
|
||||
having it if EFI itself has an RNG. In other words, the logic for this
|
||||
can now be automatic.
|
||||
|
||||
(cherry picked from commit 47b3e96647e18e8ca219c4792ab769344eea11bb)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
docs/RANDOM_SEEDS.md | 8 --------
|
||||
man/loader.conf.xml | 19 -------------------
|
||||
src/boot/efi/boot.c | 26 +-------------------------
|
||||
src/boot/efi/random-seed.c | 5 +----
|
||||
src/boot/efi/random-seed.h | 18 +-----------------
|
||||
src/shared/bootspec.c | 3 +--
|
||||
src/shared/bootspec.h | 1 -
|
||||
7 files changed, 4 insertions(+), 76 deletions(-)
|
||||
|
||||
diff --git a/docs/RANDOM_SEEDS.md b/docs/RANDOM_SEEDS.md
|
||||
index a1134d6417..4cb2bb9cfa 100644
|
||||
--- a/docs/RANDOM_SEEDS.md
|
||||
+++ b/docs/RANDOM_SEEDS.md
|
||||
@@ -232,14 +232,6 @@ boot, in order to ensure the entropy pool is filled up quickly.
|
||||
too), which should be safe even with FAT file system drivers built into
|
||||
low-quality EFI firmwares.
|
||||
|
||||
- If the system token is not desired but this seeding mechanism still is, OS
|
||||
- builders that know that they are not going to replicate the built image on
|
||||
- multiple systems may opt to turn off the 'system token' concept by setting
|
||||
- `random-seed-mode always` in the ESP's
|
||||
- [`/loader/loader.conf`](https://www.freedesktop.org/software/systemd/man/loader.conf.html)
|
||||
- file. If done, `systemd-boot` will use the random seed file even if no
|
||||
- system token is found in EFI variables.
|
||||
-
|
||||
4. A kernel command line option `systemd.random_seed=` may be used to pass in a
|
||||
base64 encoded seed to initialize the kernel's entropy pool from during
|
||||
early service manager initialization. This option is only safe in testing
|
||||
diff --git a/man/loader.conf.xml b/man/loader.conf.xml
|
||||
index 7f173aec61..d937583da9 100644
|
||||
--- a/man/loader.conf.xml
|
||||
+++ b/man/loader.conf.xml
|
||||
@@ -309,25 +309,6 @@ sign-efi-sig-list -c KEK.crt -k KEK.key db db.esl db.auth
|
||||
encrypted drive to change. If PCR 4 is not measured, this setting can be disabled to speed
|
||||
up booting into Windows.</para></listitem>
|
||||
</varlistentry>
|
||||
-
|
||||
- <varlistentry>
|
||||
- <term>random-seed-mode</term>
|
||||
-
|
||||
- <listitem><para>Takes one of <literal>off</literal>, <literal>with-system-token</literal> and
|
||||
- <literal>always</literal>. If <literal>off</literal> no random seed data is read off the ESP, nor
|
||||
- passed to the OS. If <literal>with-system-token</literal> (the default)
|
||||
- <command>systemd-boot</command> will read a random seed from the ESP (from the file
|
||||
- <filename>/loader/random-seed</filename>) only if the <varname>LoaderSystemToken</varname> EFI
|
||||
- variable is set, and then derive the random seed to pass to the OS from the combination. If
|
||||
- <literal>always</literal> the boot loader will do so even if <varname>LoaderSystemToken</varname> is
|
||||
- not set. This mode is useful in environments where protection against OS image reuse is not a
|
||||
- concern, and the random seed shall be used even with no further setup in place. Use <command>bootctl
|
||||
- random-seed</command> to initialize both the random seed file in the ESP and the system token EFI
|
||||
- variable.</para>
|
||||
-
|
||||
- <para>See <ulink url="https://systemd.io/RANDOM_SEEDS">Random Seeds</ulink> for further
|
||||
- information.</para></listitem>
|
||||
- </varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
|
||||
index 5944451e6a..4a64c2402d 100644
|
||||
--- a/src/boot/efi/boot.c
|
||||
+++ b/src/boot/efi/boot.c
|
||||
@@ -97,7 +97,6 @@ typedef struct {
|
||||
bool beep;
|
||||
int64_t console_mode;
|
||||
int64_t console_mode_efivar;
|
||||
- RandomSeedMode random_seed_mode;
|
||||
} Config;
|
||||
|
||||
/* These values have been chosen so that the transitions the user sees could
|
||||
@@ -529,7 +528,6 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
|
||||
ps_bool(L" auto-firmware: %s\n", config->auto_firmware);
|
||||
ps_bool(L" beep: %s\n", config->beep);
|
||||
ps_bool(L" reboot-for-bitlocker: %s\n", config->reboot_for_bitlocker);
|
||||
- ps_string(L" random-seed-mode: %s\n", random_seed_modes_table[config->random_seed_mode]);
|
||||
|
||||
switch (config->secure_boot_enroll) {
|
||||
case ENROLL_OFF:
|
||||
@@ -1273,27 +1271,6 @@ static void config_defaults_load_from_file(Config *config, char *content) {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
-
|
||||
- if (streq8(key, "random-seed-mode")) {
|
||||
- if (streq8(value, "off"))
|
||||
- config->random_seed_mode = RANDOM_SEED_OFF;
|
||||
- else if (streq8(value, "with-system-token"))
|
||||
- config->random_seed_mode = RANDOM_SEED_WITH_SYSTEM_TOKEN;
|
||||
- else if (streq8(value, "always"))
|
||||
- config->random_seed_mode = RANDOM_SEED_ALWAYS;
|
||||
- else {
|
||||
- bool on;
|
||||
-
|
||||
- err = parse_boolean(value, &on);
|
||||
- if (err != EFI_SUCCESS) {
|
||||
- log_error_stall(L"Error parsing 'random-seed-mode' config option: %a", value);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- config->random_seed_mode = on ? RANDOM_SEED_ALWAYS : RANDOM_SEED_OFF;
|
||||
- }
|
||||
- continue;
|
||||
- }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1584,7 +1561,6 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
.auto_firmware = true,
|
||||
.reboot_for_bitlocker = false,
|
||||
.secure_boot_enroll = ENROLL_MANUAL,
|
||||
- .random_seed_mode = RANDOM_SEED_WITH_SYSTEM_TOKEN,
|
||||
.idx_default_efivar = IDX_INVALID,
|
||||
.console_mode = CONSOLE_MODE_KEEP,
|
||||
.console_mode_efivar = CONSOLE_MODE_KEEP,
|
||||
@@ -2735,7 +2711,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
save_selected_entry(&config, entry);
|
||||
|
||||
/* Optionally, read a random seed off the ESP and pass it to the OS */
|
||||
- (void) process_random_seed(root_dir, config.random_seed_mode);
|
||||
+ (void) process_random_seed(root_dir);
|
||||
|
||||
err = image_start(image, entry);
|
||||
if (err != EFI_SUCCESS)
|
||||
diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c
|
||||
index 471398fbf1..4fc56d9356 100644
|
||||
--- a/src/boot/efi/random-seed.c
|
||||
+++ b/src/boot/efi/random-seed.c
|
||||
@@ -140,9 +140,6 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
|
||||
validate_sha256();
|
||||
|
||||
- if (mode == RANDOM_SEED_OFF)
|
||||
- return EFI_NOT_FOUND;
|
||||
-
|
||||
/* hash = LABEL || sizeof(input1) || input1 || ... || sizeof(inputN) || inputN */
|
||||
sha256_init_ctx(&hash);
|
||||
|
||||
@@ -193,7 +190,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
* system, even when disk images are duplicated or swapped out. */
|
||||
size = 0;
|
||||
err = acquire_system_token(&system_token, &size);
|
||||
- if (mode != RANDOM_SEED_ALWAYS && (err != EFI_SUCCESS || size < DESIRED_SEED_SIZE) && !seeded_by_efi)
|
||||
+ if ((err != EFI_SUCCESS || size < DESIRED_SEED_SIZE) && !seeded_by_efi)
|
||||
return err;
|
||||
sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
if (system_token) {
|
||||
diff --git a/src/boot/efi/random-seed.h b/src/boot/efi/random-seed.h
|
||||
index 6aa1cc5288..40aaf85860 100644
|
||||
--- a/src/boot/efi/random-seed.h
|
||||
+++ b/src/boot/efi/random-seed.h
|
||||
@@ -2,21 +2,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <efi.h>
|
||||
-#include <errno.h>
|
||||
-#include <uchar.h>
|
||||
|
||||
-typedef enum RandomSeedMode {
|
||||
- RANDOM_SEED_OFF,
|
||||
- RANDOM_SEED_WITH_SYSTEM_TOKEN,
|
||||
- RANDOM_SEED_ALWAYS,
|
||||
- _RANDOM_SEED_MODE_MAX,
|
||||
- _RANDOM_SEED_MODE_INVALID = -EINVAL,
|
||||
-} RandomSeedMode;
|
||||
-
|
||||
-static const char16_t * const random_seed_modes_table[_RANDOM_SEED_MODE_MAX] = {
|
||||
- [RANDOM_SEED_OFF] = L"off",
|
||||
- [RANDOM_SEED_WITH_SYSTEM_TOKEN] = L"with-system-token",
|
||||
- [RANDOM_SEED_ALWAYS] = L"always",
|
||||
-};
|
||||
-
|
||||
-EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode);
|
||||
+EFI_STATUS process_random_seed(EFI_FILE *root_dir);
|
||||
diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c
|
||||
index 9352416af5..61e20c40a8 100644
|
||||
--- a/src/shared/bootspec.c
|
||||
+++ b/src/shared/bootspec.c
|
||||
@@ -418,7 +418,6 @@ void boot_config_free(BootConfig *config) {
|
||||
free(config->auto_entries);
|
||||
free(config->auto_firmware);
|
||||
free(config->console_mode);
|
||||
- free(config->random_seed_mode);
|
||||
free(config->beep);
|
||||
|
||||
free(config->entry_oneshot);
|
||||
@@ -485,7 +484,7 @@ int boot_loader_read_conf(BootConfig *config, FILE *file, const char *path) {
|
||||
else if (streq(field, "console-mode"))
|
||||
r = free_and_strdup(&config->console_mode, p);
|
||||
else if (streq(field, "random-seed-mode"))
|
||||
- r = free_and_strdup(&config->random_seed_mode, p);
|
||||
+ log_syntax(NULL, LOG_WARNING, path, line, 0, "'random-seed-mode' has been deprecated, ignoring.");
|
||||
else if (streq(field, "beep"))
|
||||
r = free_and_strdup(&config->beep, p);
|
||||
else {
|
||||
diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h
|
||||
index 7f5d496b95..ac4d1890b0 100644
|
||||
--- a/src/shared/bootspec.h
|
||||
+++ b/src/shared/bootspec.h
|
||||
@@ -57,7 +57,6 @@ typedef struct BootConfig {
|
||||
char *auto_entries;
|
||||
char *auto_firmware;
|
||||
char *console_mode;
|
||||
- char *random_seed_mode;
|
||||
char *beep;
|
||||
|
||||
char *entry_oneshot;
|
302
0671-stub-handle-random-seed-like-sd-boot-does.patch
Normal file
302
0671-stub-handle-random-seed-like-sd-boot-does.patch
Normal file
@ -0,0 +1,302 @@
|
||||
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
|
90
0672-efi-add-efi_guid_equal-helper.patch
Normal file
90
0672-efi-add-efi_guid_equal-helper.patch
Normal file
@ -0,0 +1,90 @@
|
||||
From a30f647ef87e352502dde5ca67ad99927611108a Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Fri, 11 Nov 2022 16:05:03 +0100
|
||||
Subject: [PATCH] efi: add efi_guid_equal() helper
|
||||
|
||||
(cherry picked from commit 50b0b0d351e892d57a562a28dd8362b1e8cd76a9)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/devicetree.c | 2 +-
|
||||
src/boot/efi/part-discovery.c | 2 +-
|
||||
src/boot/efi/random-seed.c | 3 +--
|
||||
src/boot/efi/util.h | 4 ++++
|
||||
src/boot/efi/vmm.c | 4 ++--
|
||||
5 files changed, 9 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/devicetree.c b/src/boot/efi/devicetree.c
|
||||
index 0312670613..daba5582aa 100644
|
||||
--- a/src/boot/efi/devicetree.c
|
||||
+++ b/src/boot/efi/devicetree.c
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
static void *get_dtb_table(void) {
|
||||
for (UINTN i = 0; i < ST->NumberOfTableEntries; i++)
|
||||
- if (memcmp(&EfiDtbTableGuid, &ST->ConfigurationTable[i].VendorGuid, sizeof(EfiDtbTableGuid)) == 0)
|
||||
+ if (efi_guid_equal(&ST->ConfigurationTable[i].VendorGuid, &EfiDtbTableGuid))
|
||||
return ST->ConfigurationTable[i].VendorTable;
|
||||
return NULL;
|
||||
}
|
||||
diff --git a/src/boot/efi/part-discovery.c b/src/boot/efi/part-discovery.c
|
||||
index 14479c06ea..2659a5b6b4 100644
|
||||
--- a/src/boot/efi/part-discovery.c
|
||||
+++ b/src/boot/efi/part-discovery.c
|
||||
@@ -134,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, type, sizeof(entry->PartitionTypeGUID)) != 0)
|
||||
+ if (!efi_guid_equal(&entry->PartitionTypeGUID, type))
|
||||
continue;
|
||||
|
||||
if (entry->EndingLBA < entry->StartingLBA) /* Bogus? */
|
||||
diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c
|
||||
index 4fc56d9356..6070145778 100644
|
||||
--- a/src/boot/efi/random-seed.c
|
||||
+++ b/src/boot/efi/random-seed.c
|
||||
@@ -147,8 +147,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
sha256_process_bytes(HASH_LABEL, sizeof(HASH_LABEL) - 1, &hash);
|
||||
|
||||
for (size_t i = 0; i < ST->NumberOfTableEntries; ++i)
|
||||
- if (memcmp(&(const EFI_GUID)LINUX_EFI_RANDOM_SEED_TABLE_GUID,
|
||||
- &ST->ConfigurationTable[i].VendorGuid, sizeof(EFI_GUID)) == 0) {
|
||||
+ if (efi_guid_equal(&ST->ConfigurationTable[i].VendorGuid, &(const EFI_GUID) LINUX_EFI_RANDOM_SEED_TABLE_GUID)) {
|
||||
previous_seed_table = ST->ConfigurationTable[i].VendorTable;
|
||||
break;
|
||||
}
|
||||
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
|
||||
index f58d24fce1..a076f48dba 100644
|
||||
--- a/src/boot/efi/util.h
|
||||
+++ b/src/boot/efi/util.h
|
||||
@@ -217,3 +217,7 @@ static inline bool in_hypervisor(void) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+static inline bool efi_guid_equal(const EFI_GUID *a, const EFI_GUID *b) {
|
||||
+ return memcmp(a, b, sizeof(EFI_GUID)) == 0;
|
||||
+}
|
||||
diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c
|
||||
index 2260b217b7..10d4a75ab2 100644
|
||||
--- a/src/boot/efi/vmm.c
|
||||
+++ b/src/boot/efi/vmm.c
|
||||
@@ -18,7 +18,7 @@
|
||||
/* detect direct boot */
|
||||
bool is_direct_boot(EFI_HANDLE device) {
|
||||
EFI_STATUS err;
|
||||
- VENDOR_DEVICE_PATH *dp;
|
||||
+ VENDOR_DEVICE_PATH *dp; /* NB: Alignment of this structure might be quirky! */
|
||||
|
||||
err = BS->HandleProtocol(device, &DevicePathProtocol, (void **) &dp);
|
||||
if (err != EFI_SUCCESS)
|
||||
@@ -27,7 +27,7 @@ bool is_direct_boot(EFI_HANDLE device) {
|
||||
/* 'qemu -kernel systemd-bootx64.efi' */
|
||||
if (dp->Header.Type == MEDIA_DEVICE_PATH &&
|
||||
dp->Header.SubType == MEDIA_VENDOR_DP &&
|
||||
- memcmp(&dp->Guid, &(EFI_GUID)QEMU_KERNEL_LOADER_FS_MEDIA_GUID, sizeof(EFI_GUID)) == 0)
|
||||
+ memcmp(&dp->Guid, &(EFI_GUID)QEMU_KERNEL_LOADER_FS_MEDIA_GUID, sizeof(EFI_GUID)) == 0) /* Don't change to efi_guid_equal() because EFI device path objects are not necessarily aligned! */
|
||||
return true;
|
||||
|
||||
/* loaded from firmware volume (sd-boot added to ovmf) */
|
@ -0,0 +1,95 @@
|
||||
From bbf8235eb297047521ac83b594389d70ecfb38df Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 14 Dec 2022 18:48:52 +0100
|
||||
Subject: [PATCH] efi: add common implementation for loop finding EFI
|
||||
configuration tables
|
||||
|
||||
(cherry picked from commit a04709c1ac81b28b1a4144166991ac56be94cfcd)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/devicetree.c | 11 ++---------
|
||||
src/boot/efi/random-seed.c | 6 +-----
|
||||
src/boot/efi/util.c | 8 ++++++++
|
||||
src/boot/efi/util.h | 2 ++
|
||||
4 files changed, 13 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/devicetree.c b/src/boot/efi/devicetree.c
|
||||
index daba5582aa..12015fce6b 100644
|
||||
--- a/src/boot/efi/devicetree.c
|
||||
+++ b/src/boot/efi/devicetree.c
|
||||
@@ -8,13 +8,6 @@
|
||||
|
||||
#define FDT_V1_SIZE (7*4)
|
||||
|
||||
-static void *get_dtb_table(void) {
|
||||
- for (UINTN i = 0; i < ST->NumberOfTableEntries; i++)
|
||||
- if (efi_guid_equal(&ST->ConfigurationTable[i].VendorGuid, &EfiDtbTableGuid))
|
||||
- return ST->ConfigurationTable[i].VendorTable;
|
||||
- return NULL;
|
||||
-}
|
||||
-
|
||||
static EFI_STATUS devicetree_allocate(struct devicetree_state *state, UINTN size) {
|
||||
UINTN pages = DIV_ROUND_UP(size, EFI_PAGE_SIZE);
|
||||
EFI_STATUS err;
|
||||
@@ -81,7 +74,7 @@ EFI_STATUS devicetree_install(struct devicetree_state *state, EFI_FILE *root_dir
|
||||
assert(root_dir);
|
||||
assert(name);
|
||||
|
||||
- state->orig = get_dtb_table();
|
||||
+ state->orig = find_configuration_table(&EfiDtbTableGuid);
|
||||
if (!state->orig)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
@@ -121,7 +114,7 @@ EFI_STATUS devicetree_install_from_memory(struct devicetree_state *state,
|
||||
assert(state);
|
||||
assert(dtb_buffer && dtb_length > 0);
|
||||
|
||||
- state->orig = get_dtb_table();
|
||||
+ state->orig = find_configuration_table(&EfiDtbTableGuid);
|
||||
if (!state->orig)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c
|
||||
index 6070145778..332f537d91 100644
|
||||
--- a/src/boot/efi/random-seed.c
|
||||
+++ b/src/boot/efi/random-seed.c
|
||||
@@ -146,11 +146,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
/* Some basic domain separation in case somebody uses this data elsewhere */
|
||||
sha256_process_bytes(HASH_LABEL, sizeof(HASH_LABEL) - 1, &hash);
|
||||
|
||||
- for (size_t i = 0; i < ST->NumberOfTableEntries; ++i)
|
||||
- if (efi_guid_equal(&ST->ConfigurationTable[i].VendorGuid, &(const EFI_GUID) LINUX_EFI_RANDOM_SEED_TABLE_GUID)) {
|
||||
- previous_seed_table = ST->ConfigurationTable[i].VendorTable;
|
||||
- break;
|
||||
- }
|
||||
+ previous_seed_table = find_configuration_table(&(const EFI_GUID) LINUX_EFI_RANDOM_SEED_TABLE_GUID);
|
||||
if (!previous_seed_table) {
|
||||
size = 0;
|
||||
sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
|
||||
index 1f07fbc38c..0a6bb59dce 100644
|
||||
--- a/src/boot/efi/util.c
|
||||
+++ b/src/boot/efi/util.c
|
||||
@@ -747,3 +747,11 @@ bool in_hypervisor(void) {
|
||||
return !!(ecx & 0x80000000U);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+void *find_configuration_table(const EFI_GUID *guid) {
|
||||
+ for (UINTN i = 0; i < ST->NumberOfTableEntries; i++)
|
||||
+ if (efi_guid_equal(&ST->ConfigurationTable[i].VendorGuid, guid))
|
||||
+ return ST->ConfigurationTable[i].VendorTable;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
|
||||
index a076f48dba..88fc60c17e 100644
|
||||
--- a/src/boot/efi/util.h
|
||||
+++ b/src/boot/efi/util.h
|
||||
@@ -221,3 +221,5 @@ static inline bool in_hypervisor(void) {
|
||||
static inline bool efi_guid_equal(const EFI_GUID *a, const EFI_GUID *b) {
|
||||
return memcmp(a, b, sizeof(EFI_GUID)) == 0;
|
||||
}
|
||||
+
|
||||
+void *find_configuration_table(const EFI_GUID *guid);
|
310
0674-boot-Detect-hypervisors-using-SMBIOS-info.patch
Normal file
310
0674-boot-Detect-hypervisors-using-SMBIOS-info.patch
Normal file
@ -0,0 +1,310 @@
|
||||
From 4fad2ae3115ee9cedc61fffaf920fbd08fabc267 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Tue, 10 Jan 2023 14:44:29 +0100
|
||||
Subject: [PATCH] boot: Detect hypervisors using SMBIOS info
|
||||
|
||||
This allows skipping secure boot enrollment wait time on other arches.
|
||||
|
||||
(cherry picked from commit ba2793927461b82216f56aa8a800cf53fac28d37)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/meson.build | 4 +-
|
||||
src/boot/efi/secure-boot.c | 3 +-
|
||||
src/boot/efi/ticks.c | 1 +
|
||||
src/boot/efi/util.c | 17 ----
|
||||
src/boot/efi/util.h | 8 --
|
||||
src/boot/efi/vmm.c | 156 +++++++++++++++++++++++++++++++++++++
|
||||
src/boot/efi/vmm.h | 2 +
|
||||
7 files changed, 163 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
|
||||
index 8e96a33119..ab2d7595f3 100644
|
||||
--- a/src/boot/efi/meson.build
|
||||
+++ b/src/boot/efi/meson.build
|
||||
@@ -375,6 +375,7 @@ common_sources = files(
|
||||
'assert.c',
|
||||
'console.c',
|
||||
'devicetree.c',
|
||||
+ 'drivers.c',
|
||||
'disk.c',
|
||||
'efi-string.c',
|
||||
'graphics.c',
|
||||
@@ -386,13 +387,12 @@ common_sources = files(
|
||||
'secure-boot.c',
|
||||
'ticks.c',
|
||||
'util.c',
|
||||
+ 'vmm.c',
|
||||
)
|
||||
|
||||
systemd_boot_sources = files(
|
||||
'boot.c',
|
||||
- 'drivers.c',
|
||||
'shim.c',
|
||||
- 'vmm.c',
|
||||
)
|
||||
|
||||
stub_sources = files(
|
||||
diff --git a/src/boot/efi/secure-boot.c b/src/boot/efi/secure-boot.c
|
||||
index 6212868134..55c9ba5d4c 100644
|
||||
--- a/src/boot/efi/secure-boot.c
|
||||
+++ b/src/boot/efi/secure-boot.c
|
||||
@@ -1,9 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
+#include "console.h"
|
||||
#include "sbat.h"
|
||||
#include "secure-boot.h"
|
||||
-#include "console.h"
|
||||
#include "util.h"
|
||||
+#include "vmm.h"
|
||||
|
||||
bool secure_boot_enabled(void) {
|
||||
bool secure = false; /* avoid false maybe-uninitialized warning */
|
||||
diff --git a/src/boot/efi/ticks.c b/src/boot/efi/ticks.c
|
||||
index 1b74ba15d0..2f6ff878ca 100644
|
||||
--- a/src/boot/efi/ticks.c
|
||||
+++ b/src/boot/efi/ticks.c
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "ticks.h"
|
||||
#include "util.h"
|
||||
+#include "vmm.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
static uint64_t ticks_read(void) {
|
||||
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
|
||||
index 0a6bb59dce..dfe2fe791d 100644
|
||||
--- a/src/boot/efi/util.c
|
||||
+++ b/src/boot/efi/util.c
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
-#if defined(__i386__) || defined(__x86_64__)
|
||||
-# include <cpuid.h>
|
||||
-#endif
|
||||
|
||||
#include "ticks.h"
|
||||
#include "util.h"
|
||||
@@ -734,20 +731,6 @@ EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
-#if defined(__i386__) || defined(__x86_64__)
|
||||
-bool in_hypervisor(void) {
|
||||
- uint32_t eax, ebx, ecx, edx;
|
||||
-
|
||||
- /* This is a dumbed down version of src/basic/virt.c's detect_vm() that safely works in the UEFI
|
||||
- * environment. */
|
||||
-
|
||||
- if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0)
|
||||
- return false;
|
||||
-
|
||||
- return !!(ecx & 0x80000000U);
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
void *find_configuration_table(const EFI_GUID *guid) {
|
||||
for (UINTN i = 0; i < ST->NumberOfTableEntries; i++)
|
||||
if (efi_guid_equal(&ST->ConfigurationTable[i].VendorGuid, guid))
|
||||
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
|
||||
index 88fc60c17e..d688f392fc 100644
|
||||
--- a/src/boot/efi/util.h
|
||||
+++ b/src/boot/efi/util.h
|
||||
@@ -210,14 +210,6 @@ EFI_STATUS open_volume(EFI_HANDLE device, EFI_FILE **ret_file);
|
||||
EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp);
|
||||
EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret);
|
||||
|
||||
-#if defined(__i386__) || defined(__x86_64__)
|
||||
-bool in_hypervisor(void);
|
||||
-#else
|
||||
-static inline bool in_hypervisor(void) {
|
||||
- return false;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
static inline bool efi_guid_equal(const EFI_GUID *a, const EFI_GUID *b) {
|
||||
return memcmp(a, b, sizeof(EFI_GUID)) == 0;
|
||||
}
|
||||
diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c
|
||||
index 10d4a75ab2..3dfa92b58d 100644
|
||||
--- a/src/boot/efi/vmm.c
|
||||
+++ b/src/boot/efi/vmm.c
|
||||
@@ -3,6 +3,9 @@
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
#include <stdbool.h>
|
||||
+#if defined(__i386__) || defined(__x86_64__)
|
||||
+# include <cpuid.h>
|
||||
+#endif
|
||||
|
||||
#include "drivers.h"
|
||||
#include "efi-string.h"
|
||||
@@ -132,3 +135,156 @@ EFI_STATUS vmm_open(EFI_HANDLE *ret_vmm_dev, EFI_FILE **ret_vmm_dir) {
|
||||
}
|
||||
assert_not_reached();
|
||||
}
|
||||
+
|
||||
+static bool cpuid_in_hypervisor(void) {
|
||||
+#if defined(__i386__) || defined(__x86_64__)
|
||||
+ unsigned eax, ebx, ecx, edx;
|
||||
+
|
||||
+ /* This is a dumbed down version of src/basic/virt.c's detect_vm() that safely works in the UEFI
|
||||
+ * environment. */
|
||||
+
|
||||
+ if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0)
|
||||
+ return false;
|
||||
+
|
||||
+ if (FLAGS_SET(ecx, 0x80000000U))
|
||||
+ return true;
|
||||
+#endif
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint8_t anchor_string[4];
|
||||
+ uint8_t entry_point_structure_checksum;
|
||||
+ uint8_t entry_point_length;
|
||||
+ uint8_t major_version;
|
||||
+ uint8_t minor_version;
|
||||
+ uint16_t max_structure_size;
|
||||
+ uint8_t entry_point_revision;
|
||||
+ uint8_t formatted_area[5];
|
||||
+ uint8_t intermediate_anchor_string[5];
|
||||
+ uint8_t intermediate_checksum;
|
||||
+ uint16_t table_length;
|
||||
+ uint32_t table_address;
|
||||
+ uint16_t number_of_smbios_structures;
|
||||
+ uint8_t smbios_bcd_revision;
|
||||
+} _packed_ SmbiosEntryPoint;
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint8_t anchor_string[5];
|
||||
+ uint8_t entry_point_structure_checksum;
|
||||
+ uint8_t entry_point_length;
|
||||
+ uint8_t major_version;
|
||||
+ uint8_t minor_version;
|
||||
+ uint8_t docrev;
|
||||
+ uint8_t entry_point_revision;
|
||||
+ uint8_t reserved;
|
||||
+ uint32_t table_maximum_size;
|
||||
+ uint64_t table_address;
|
||||
+} _packed_ Smbios3EntryPoint;
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint8_t type;
|
||||
+ uint8_t length;
|
||||
+ uint8_t handle[2];
|
||||
+} _packed_ SmbiosHeader;
|
||||
+
|
||||
+typedef struct {
|
||||
+ SmbiosHeader header;
|
||||
+ uint8_t vendor;
|
||||
+ uint8_t bios_version;
|
||||
+ uint16_t bios_segment;
|
||||
+ uint8_t bios_release_date;
|
||||
+ uint8_t bios_size;
|
||||
+ uint64_t bios_characteristics;
|
||||
+ uint8_t bios_characteristics_ext[2];
|
||||
+} _packed_ SmbiosTableType0;
|
||||
+
|
||||
+static void *find_smbios_configuration_table(uint64_t *ret_size) {
|
||||
+ assert(ret_size);
|
||||
+
|
||||
+ Smbios3EntryPoint *entry3 = find_configuration_table(&(EFI_GUID) SMBIOS3_TABLE_GUID);
|
||||
+ if (entry3 && memcmp(entry3->anchor_string, "_SM3_", 5) == 0 &&
|
||||
+ entry3->entry_point_length <= sizeof(*entry3)) {
|
||||
+ *ret_size = entry3->table_maximum_size;
|
||||
+ return PHYSICAL_ADDRESS_TO_POINTER(entry3->table_address);
|
||||
+ }
|
||||
+
|
||||
+ SmbiosEntryPoint *entry = find_configuration_table(&(EFI_GUID) SMBIOS_TABLE_GUID);
|
||||
+ if (entry && memcmp(entry->anchor_string, "_SM_", 4) == 0 &&
|
||||
+ entry->entry_point_length <= sizeof(*entry)) {
|
||||
+ *ret_size = entry->table_length;
|
||||
+ return PHYSICAL_ADDRESS_TO_POINTER(entry->table_address);
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static SmbiosHeader *get_smbios_table(uint8_t type) {
|
||||
+ uint64_t size = 0;
|
||||
+ uint8_t *p = find_smbios_configuration_table(&size);
|
||||
+ if (!p)
|
||||
+ return false;
|
||||
+
|
||||
+ for (;;) {
|
||||
+ if (size < sizeof(SmbiosHeader))
|
||||
+ return NULL;
|
||||
+
|
||||
+ SmbiosHeader *header = (SmbiosHeader *) p;
|
||||
+
|
||||
+ /* End of table. */
|
||||
+ if (header->type == 127)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (size < header->length)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (header->type == type)
|
||||
+ return header; /* Yay! */
|
||||
+
|
||||
+ /* Skip over formatted area. */
|
||||
+ size -= header->length;
|
||||
+ p += header->length;
|
||||
+
|
||||
+ /* Skip over string table. */
|
||||
+ for (;;) {
|
||||
+ while (size > 0 && *p != '\0') {
|
||||
+ p++;
|
||||
+ size--;
|
||||
+ }
|
||||
+ if (size == 0)
|
||||
+ return NULL;
|
||||
+ p++;
|
||||
+ size--;
|
||||
+
|
||||
+ /* Double NUL terminates string table. */
|
||||
+ if (*p == '\0') {
|
||||
+ if (size == 0)
|
||||
+ return NULL;
|
||||
+ p++;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static bool smbios_in_hypervisor(void) {
|
||||
+ /* Look up BIOS Information (Type 0). */
|
||||
+ SmbiosTableType0 *type0 = (SmbiosTableType0 *) get_smbios_table(0);
|
||||
+ if (!type0 || type0->header.length < sizeof(SmbiosTableType0))
|
||||
+ return false;
|
||||
+
|
||||
+ /* Bit 4 of 2nd BIOS characteristics extension bytes indicates virtualization. */
|
||||
+ return FLAGS_SET(type0->bios_characteristics_ext[1], 1 << 4);
|
||||
+}
|
||||
+
|
||||
+bool in_hypervisor(void) {
|
||||
+ static int cache = -1;
|
||||
+ if (cache >= 0)
|
||||
+ return cache;
|
||||
+
|
||||
+ cache = cpuid_in_hypervisor() || smbios_in_hypervisor();
|
||||
+ return cache;
|
||||
+}
|
||||
diff --git a/src/boot/efi/vmm.h b/src/boot/efi/vmm.h
|
||||
index 7bac1a324a..e98ec74af1 100644
|
||||
--- a/src/boot/efi/vmm.h
|
||||
+++ b/src/boot/efi/vmm.h
|
||||
@@ -6,3 +6,5 @@
|
||||
|
||||
bool is_direct_boot(EFI_HANDLE device);
|
||||
EFI_STATUS vmm_open(EFI_HANDLE *ret_qemu_dev, EFI_FILE **ret_qemu_dir);
|
||||
+
|
||||
+bool in_hypervisor(void);
|
83
0675-boot-Skip-soft-brick-warning-when-in-a-VM.patch
Normal file
83
0675-boot-Skip-soft-brick-warning-when-in-a-VM.patch
Normal file
@ -0,0 +1,83 @@
|
||||
From 72089d78ba9e0c0d4c4b83c8f447adbfb32809ed Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Mon, 16 Jan 2023 16:22:17 +0100
|
||||
Subject: [PATCH] boot: Skip soft-brick warning when in a VM
|
||||
|
||||
This part of the warning is annoying to look at not really true when
|
||||
running inside of a VM.
|
||||
|
||||
(cherry picked from commit 3e87a057a796b57bf9540b948823fbefef6693d7)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/secure-boot.c | 56 ++++++++++++++++++++------------------
|
||||
1 file changed, 29 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/secure-boot.c b/src/boot/efi/secure-boot.c
|
||||
index 55c9ba5d4c..3f3a222b5e 100644
|
||||
--- a/src/boot/efi/secure-boot.c
|
||||
+++ b/src/boot/efi/secure-boot.c
|
||||
@@ -44,34 +44,36 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) {
|
||||
|
||||
clear_screen(COLOR_NORMAL);
|
||||
|
||||
- Print(L"Enrolling secure boot keys from directory: %s\n"
|
||||
- L"Warning: Enrolling custom Secure Boot keys might soft-brick your machine!\n",
|
||||
- path);
|
||||
-
|
||||
- unsigned timeout_sec = 15;
|
||||
- for(;;) {
|
||||
- /* Enrolling secure boot keys is safe to do in virtualized environments as there is nothing
|
||||
- * we can brick there. */
|
||||
- if (in_hypervisor())
|
||||
- break;
|
||||
-
|
||||
- PrintAt(0, ST->ConOut->Mode->CursorRow, L"Enrolling in %2u s, press any key to abort.", timeout_sec);
|
||||
-
|
||||
- uint64_t key;
|
||||
- err = console_key_read(&key, 1000 * 1000);
|
||||
- if (err == EFI_NOT_READY)
|
||||
- continue;
|
||||
- if (err == EFI_TIMEOUT) {
|
||||
- if (timeout_sec == 0) /* continue enrolling keys */
|
||||
- break;
|
||||
- timeout_sec--;
|
||||
- continue;
|
||||
+ Print(u"Enrolling secure boot keys from directory: %s\n");
|
||||
+
|
||||
+ /* Enrolling secure boot keys is safe to do in virtualized environments as there is nothing
|
||||
+ * we can brick there. */
|
||||
+ if (!in_hypervisor()) {
|
||||
+ Print(u"Warning: Enrolling custom Secure Boot keys might soft-brick your machine!\n", path);
|
||||
+
|
||||
+ unsigned timeout_sec = 15;
|
||||
+ for (;;) {
|
||||
+ Print(u"\rEnrolling in %2u s, press any key to abort.", timeout_sec);
|
||||
+
|
||||
+ uint64_t key;
|
||||
+ err = console_key_read(&key, 1000 * 1000);
|
||||
+ if (err == EFI_NOT_READY)
|
||||
+ continue;
|
||||
+ if (err == EFI_TIMEOUT) {
|
||||
+ if (timeout_sec == 0) /* continue enrolling keys */
|
||||
+ break;
|
||||
+ timeout_sec--;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status_stall(
|
||||
+ err,
|
||||
+ L"Error waiting for user input to enroll Secure Boot keys: %r",
|
||||
+ err);
|
||||
+
|
||||
+ /* user aborted, returning EFI_SUCCESS here allows the user to go back to the menu */
|
||||
+ return EFI_SUCCESS;
|
||||
}
|
||||
- if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error waiting for user input to enroll Secure Boot keys: %r", err);
|
||||
-
|
||||
- /* user aborted, returning EFI_SUCCESS here allows the user to go back to the menu */
|
||||
- return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
_cleanup_(file_closep) EFI_FILE *dir = NULL;
|
1577
0676-boot-Replace-UINTN-with-size_t.patch
Normal file
1577
0676-boot-Replace-UINTN-with-size_t.patch
Normal file
File diff suppressed because it is too large
Load Diff
42
0677-boot-Use-unsigned-for-beep-counting.patch
Normal file
42
0677-boot-Use-unsigned-for-beep-counting.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From a8a487d886f701b1a1e8991074d84ddacf41fcd0 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Wed, 25 Jan 2023 15:23:49 +0100
|
||||
Subject: [PATCH] boot: Use unsigned for beep counting
|
||||
|
||||
(cherry picked from commit 54d9ecc380360e925ef5ca7886c8546424ddf4fe)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/util.c | 2 +-
|
||||
src/boot/efi/util.h | 4 ++--
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
|
||||
index 2be18936b0..7596bc3edc 100644
|
||||
--- a/src/boot/efi/util.c
|
||||
+++ b/src/boot/efi/util.c
|
||||
@@ -587,7 +587,7 @@ static inline void outb(uint16_t port, uint8_t value) {
|
||||
asm volatile("outb %0, %1" : : "a"(value), "Nd"(port));
|
||||
}
|
||||
|
||||
-void beep(UINTN beep_count) {
|
||||
+void beep(unsigned beep_count) {
|
||||
enum {
|
||||
PITCH = 500,
|
||||
BEEP_DURATION_USEC = 100 * 1000,
|
||||
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
|
||||
index 33472a5b6a..b97dc9768c 100644
|
||||
--- a/src/boot/efi/util.h
|
||||
+++ b/src/boot/efi/util.h
|
||||
@@ -201,9 +201,9 @@ void hexdump(const char16_t *prefix, const void *data, UINTN size);
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
-void beep(UINTN beep_count);
|
||||
+void beep(unsigned beep_count);
|
||||
#else
|
||||
-static inline void beep(UINTN beep_count) {}
|
||||
+static inline void beep(unsigned beep_count) {}
|
||||
#endif
|
||||
|
||||
EFI_STATUS open_volume(EFI_HANDLE device, EFI_FILE **ret_file);
|
316
0678-boot-Use-unicode-literals.patch
Normal file
316
0678-boot-Use-unicode-literals.patch
Normal file
@ -0,0 +1,316 @@
|
||||
From 4280dc5179071758294e661600b37e3d5c7658c9 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Fri, 9 Dec 2022 11:15:41 +0100
|
||||
Subject: [PATCH] boot: Use unicode literals
|
||||
|
||||
No changes in behavior.
|
||||
|
||||
(cherry picked from commit a083aed03fc4a2bf64b2c41df508a47e3ceba91c)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/boot.c | 54 +++++++++++++++++++-------------------
|
||||
src/boot/efi/drivers.c | 4 +--
|
||||
src/boot/efi/random-seed.c | 2 +-
|
||||
src/boot/efi/stub.c | 18 ++++++-------
|
||||
4 files changed, 39 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
|
||||
index 385cfd563a..a39c356158 100644
|
||||
--- a/src/boot/efi/boot.c
|
||||
+++ b/src/boot/efi/boot.c
|
||||
@@ -427,7 +427,7 @@ static bool unicode_supported(void) {
|
||||
if (cache < 0)
|
||||
/* Basic unicode box drawing support is mandated by the spec, but it does
|
||||
* not hurt to make sure it works. */
|
||||
- cache = ST->ConOut->TestString(ST->ConOut, (char16_t *) L"─") == EFI_SUCCESS;
|
||||
+ cache = ST->ConOut->TestString(ST->ConOut, (char16_t *) u"─") == EFI_SUCCESS;
|
||||
|
||||
return cache;
|
||||
}
|
||||
@@ -728,7 +728,7 @@ static bool menu_run(
|
||||
print_at(x_start,
|
||||
y_start + i - idx_first,
|
||||
i == idx_highlight ? COLOR_HIGHLIGHT : COLOR_ENTRY,
|
||||
- unicode_supported() ? L" ►" : L"=>");
|
||||
+ unicode_supported() ? u" ►" : u"=>");
|
||||
}
|
||||
refresh = false;
|
||||
} else if (highlight) {
|
||||
@@ -738,12 +738,12 @@ static bool menu_run(
|
||||
print_at(x_start,
|
||||
y_start + idx_highlight_prev - idx_first,
|
||||
COLOR_ENTRY,
|
||||
- unicode_supported() ? L" ►" : L"=>");
|
||||
+ unicode_supported() ? u" ►" : u"=>");
|
||||
if (idx_highlight == config->idx_default_efivar)
|
||||
print_at(x_start,
|
||||
y_start + idx_highlight - idx_first,
|
||||
COLOR_HIGHLIGHT,
|
||||
- unicode_supported() ? L" ►" : L"=>");
|
||||
+ unicode_supported() ? u" ►" : u"=>");
|
||||
highlight = false;
|
||||
}
|
||||
|
||||
@@ -1504,7 +1504,7 @@ static void config_entry_add_type1(
|
||||
|
||||
config_add_entry(config, entry);
|
||||
|
||||
- config_entry_parse_tries(entry, path, file, L".conf");
|
||||
+ config_entry_parse_tries(entry, path, file, u".conf");
|
||||
TAKE_PTR(entry);
|
||||
}
|
||||
|
||||
@@ -1556,7 +1556,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
.timeout_sec_efivar = TIMEOUT_UNSET,
|
||||
};
|
||||
|
||||
- err = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content, NULL);
|
||||
+ err = file_read(root_dir, u"\\loader\\loader.conf", 0, 0, &content, NULL);
|
||||
if (err == EFI_SUCCESS)
|
||||
config_defaults_load_from_file(config, content);
|
||||
|
||||
@@ -1591,8 +1591,8 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
strtolower16(config->entry_oneshot);
|
||||
strtolower16(config->entry_saved);
|
||||
|
||||
- config->use_saved_entry = streq16(config->entry_default_config, L"@saved");
|
||||
- config->use_saved_entry_efivar = streq16(config->entry_default_efivar, L"@saved");
|
||||
+ config->use_saved_entry = streq16(config->entry_default_config, u"@saved");
|
||||
+ config->use_saved_entry_efivar = streq16(config->entry_default_efivar, u"@saved");
|
||||
if (config->use_saved_entry || config->use_saved_entry_efivar)
|
||||
(void) efivar_get(LOADER_GUID, L"LoaderEntryLastBooted", &config->entry_saved);
|
||||
}
|
||||
@@ -1614,7 +1614,7 @@ static void config_load_entries(
|
||||
|
||||
/* Adds Boot Loader Type #1 entries (i.e. /loader/entries/….conf) */
|
||||
|
||||
- err = open_directory(root_dir, L"\\loader\\entries", &entries_dir);
|
||||
+ err = open_directory(root_dir, u"\\loader\\entries", &entries_dir);
|
||||
if (err != EFI_SUCCESS)
|
||||
return;
|
||||
|
||||
@@ -1630,14 +1630,14 @@ static void config_load_entries(
|
||||
if (FLAGS_SET(f->Attribute, EFI_FILE_DIRECTORY))
|
||||
continue;
|
||||
|
||||
- if (!endswith_no_case(f->FileName, L".conf"))
|
||||
+ if (!endswith_no_case(f->FileName, u".conf"))
|
||||
continue;
|
||||
- if (startswith(f->FileName, L"auto-"))
|
||||
+ if (startswith(f->FileName, u"auto-"))
|
||||
continue;
|
||||
|
||||
err = file_read(entries_dir, f->FileName, 0, 0, &content, NULL);
|
||||
if (err == EFI_SUCCESS)
|
||||
- config_entry_add_type1(config, device, root_dir, L"\\loader\\entries", f->FileName, content, loaded_image_path);
|
||||
+ config_entry_add_type1(config, device, root_dir, u"\\loader\\entries", f->FileName, content, loaded_image_path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1876,7 +1876,7 @@ static ConfigEntry *config_entry_add_loader_auto(
|
||||
return NULL;
|
||||
|
||||
if (!loader) {
|
||||
- loader = L"\\EFI\\BOOT\\BOOT" EFI_MACHINE_TYPE_NAME ".efi";
|
||||
+ loader = u"\\EFI\\BOOT\\BOOT" EFI_MACHINE_TYPE_NAME ".efi";
|
||||
|
||||
/* We are trying to add the default EFI loader here,
|
||||
* but we do not want to do that if that would be us.
|
||||
@@ -1885,7 +1885,7 @@ static ConfigEntry *config_entry_add_loader_auto(
|
||||
* chainload GRUBX64.EFI in that case, which might be us.*/
|
||||
if (strcaseeq16(loader, loaded_image_path) ||
|
||||
is_sd_boot(root_dir, loader) ||
|
||||
- is_sd_boot(root_dir, L"\\EFI\\BOOT\\GRUB" EFI_MACHINE_TYPE_NAME L".EFI"))
|
||||
+ is_sd_boot(root_dir, u"\\EFI\\BOOT\\GRUB" EFI_MACHINE_TYPE_NAME u".EFI"))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1936,10 +1936,10 @@ static void config_entry_add_osx(Config *config) {
|
||||
handles[i],
|
||||
root,
|
||||
NULL,
|
||||
- L"auto-osx",
|
||||
+ u"auto-osx",
|
||||
'a',
|
||||
- L"macOS",
|
||||
- L"\\System\\Library\\CoreServices\\boot.efi"))
|
||||
+ u"macOS",
|
||||
+ u"\\System\\Library\\CoreServices\\boot.efi"))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2008,7 +2008,7 @@ static EFI_STATUS boot_windows_bitlocker(void) {
|
||||
if (buf_size < offset + sizeof(char16_t))
|
||||
continue;
|
||||
|
||||
- if (streq16((char16_t *) (buf + offset), L"Windows Boot Manager")) {
|
||||
+ if (streq16((char16_t *) (buf + offset), u"Windows Boot Manager")) {
|
||||
err = efivar_set_raw(
|
||||
EFI_GLOBAL_GUID,
|
||||
L"BootNext",
|
||||
@@ -2040,13 +2040,13 @@ static void config_entry_add_windows(Config *config, EFI_HANDLE *device, EFI_FIL
|
||||
return;
|
||||
|
||||
/* Try to find a better title. */
|
||||
- err = file_read(root_dir, L"\\EFI\\Microsoft\\Boot\\BCD", 0, 100*1024, &bcd, &len);
|
||||
+ err = file_read(root_dir, u"\\EFI\\Microsoft\\Boot\\BCD", 0, 100*1024, &bcd, &len);
|
||||
if (err == EFI_SUCCESS)
|
||||
title = get_bcd_title((uint8_t *) bcd, len);
|
||||
|
||||
ConfigEntry *e = config_entry_add_loader_auto(config, device, root_dir, NULL,
|
||||
- L"auto-windows", 'w', title ?: L"Windows Boot Manager",
|
||||
- L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
|
||||
+ u"auto-windows", 'w', title ?: u"Windows Boot Manager",
|
||||
+ u"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
|
||||
|
||||
if (config->reboot_for_bitlocker)
|
||||
e->call = boot_windows_bitlocker;
|
||||
@@ -2069,7 +2069,7 @@ static void config_entry_add_unified(
|
||||
assert(device);
|
||||
assert(root_dir);
|
||||
|
||||
- err = open_directory(root_dir, L"\\EFI\\Linux", &linux_dir);
|
||||
+ err = open_directory(root_dir, u"\\EFI\\Linux", &linux_dir);
|
||||
if (err != EFI_SUCCESS)
|
||||
return;
|
||||
|
||||
@@ -2101,9 +2101,9 @@ static void config_entry_add_unified(
|
||||
continue;
|
||||
if (FLAGS_SET(f->Attribute, EFI_FILE_DIRECTORY))
|
||||
continue;
|
||||
- if (!endswith_no_case(f->FileName, L".efi"))
|
||||
+ if (!endswith_no_case(f->FileName, u".efi"))
|
||||
continue;
|
||||
- if (startswith(f->FileName, L"auto-"))
|
||||
+ if (startswith(f->FileName, u"auto-"))
|
||||
continue;
|
||||
|
||||
/* look for .osrel and .cmdline sections in the .efi binary */
|
||||
@@ -2196,7 +2196,7 @@ static void config_entry_add_unified(
|
||||
|
||||
strtolower16(entry->id);
|
||||
config_add_entry(config, entry);
|
||||
- config_entry_parse_tries(entry, L"\\EFI\\Linux", f->FileName, L".efi");
|
||||
+ config_entry_parse_tries(entry, u"\\EFI\\Linux", f->FileName, u".efi");
|
||||
|
||||
if (szs[SECTION_CMDLINE] == 0)
|
||||
continue;
|
||||
@@ -2571,9 +2571,9 @@ static void config_load_all_entries(
|
||||
config_entry_add_osx(config);
|
||||
config_entry_add_windows(config, loaded_image->DeviceHandle, root_dir);
|
||||
config_entry_add_loader_auto(config, loaded_image->DeviceHandle, root_dir, NULL,
|
||||
- L"auto-efi-shell", 's', L"EFI Shell", L"\\shell" EFI_MACHINE_TYPE_NAME ".efi");
|
||||
+ u"auto-efi-shell", 's', u"EFI Shell", u"\\shell" EFI_MACHINE_TYPE_NAME ".efi");
|
||||
config_entry_add_loader_auto(config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
|
||||
- L"auto-efi-default", '\0', L"EFI Default Loader", NULL);
|
||||
+ u"auto-efi-default", '\0', u"EFI Default Loader", NULL);
|
||||
|
||||
if (config->auto_firmware && FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) {
|
||||
ConfigEntry *entry = xnew(ConfigEntry, 1);
|
||||
diff --git a/src/boot/efi/drivers.c b/src/boot/efi/drivers.c
|
||||
index c073e1a4f2..41a7d8fe15 100644
|
||||
--- a/src/boot/efi/drivers.c
|
||||
+++ b/src/boot/efi/drivers.c
|
||||
@@ -82,7 +82,7 @@ EFI_STATUS load_drivers(
|
||||
|
||||
err = open_directory(
|
||||
root_dir,
|
||||
- L"\\EFI\\systemd\\drivers",
|
||||
+ u"\\EFI\\systemd\\drivers",
|
||||
&drivers_dir);
|
||||
if (err == EFI_NOT_FOUND)
|
||||
return EFI_SUCCESS;
|
||||
@@ -100,7 +100,7 @@ EFI_STATUS load_drivers(
|
||||
continue;
|
||||
if (FLAGS_SET(dirent->Attribute, EFI_FILE_DIRECTORY))
|
||||
continue;
|
||||
- if (!endswith_no_case(dirent->FileName, EFI_MACHINE_TYPE_NAME L".efi"))
|
||||
+ if (!endswith_no_case(dirent->FileName, EFI_MACHINE_TYPE_NAME u".efi"))
|
||||
continue;
|
||||
|
||||
err = load_one_driver(parent_image, loaded_image, dirent->FileName);
|
||||
diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c
|
||||
index 5d7459d87e..a52934a901 100644
|
||||
--- a/src/boot/efi/random-seed.c
|
||||
+++ b/src/boot/efi/random-seed.c
|
||||
@@ -196,7 +196,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
err = root_dir->Open(
|
||||
root_dir,
|
||||
&handle,
|
||||
- (char16_t *) L"\\loader\\random-seed",
|
||||
+ (char16_t *) u"\\loader\\random-seed",
|
||||
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
|
||||
0);
|
||||
if (err != EFI_SUCCESS) {
|
||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
||||
index e3b97164a8..433fef548c 100644
|
||||
--- a/src/boot/efi/stub.c
|
||||
+++ b/src/boot/efi/stub.c
|
||||
@@ -286,27 +286,27 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
|
||||
if (pack_cpio(loaded_image,
|
||||
NULL,
|
||||
- L".cred",
|
||||
+ u".cred",
|
||||
".extra/credentials",
|
||||
/* dir_mode= */ 0500,
|
||||
/* access_mode= */ 0400,
|
||||
/* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT },
|
||||
/* n_tpm_pcr= */ 2,
|
||||
- L"Credentials initrd",
|
||||
+ u"Credentials initrd",
|
||||
&credential_initrd,
|
||||
&credential_initrd_size,
|
||||
&m) == EFI_SUCCESS)
|
||||
parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m);
|
||||
|
||||
if (pack_cpio(loaded_image,
|
||||
- L"\\loader\\credentials",
|
||||
- L".cred",
|
||||
+ u"\\loader\\credentials",
|
||||
+ u".cred",
|
||||
".extra/global_credentials",
|
||||
/* dir_mode= */ 0500,
|
||||
/* access_mode= */ 0400,
|
||||
/* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT },
|
||||
/* n_tpm_pcr= */ 2,
|
||||
- L"Global credentials initrd",
|
||||
+ u"Global credentials initrd",
|
||||
&global_credential_initrd,
|
||||
&global_credential_initrd_size,
|
||||
&m) == EFI_SUCCESS)
|
||||
@@ -314,13 +314,13 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
|
||||
if (pack_cpio(loaded_image,
|
||||
NULL,
|
||||
- L".raw",
|
||||
+ u".raw",
|
||||
".extra/sysext",
|
||||
/* dir_mode= */ 0555,
|
||||
/* access_mode= */ 0444,
|
||||
/* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_INITRD_SYSEXTS },
|
||||
/* n_tpm_pcr= */ 1,
|
||||
- L"System extension initrd",
|
||||
+ u"System extension initrd",
|
||||
&sysext_initrd,
|
||||
&sysext_initrd_size,
|
||||
&m) == EFI_SUCCESS)
|
||||
@@ -341,7 +341,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
(uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_PCRSIG],
|
||||
szs[UNIFIED_SECTION_PCRSIG],
|
||||
".extra",
|
||||
- L"tpm2-pcr-signature.json",
|
||||
+ u"tpm2-pcr-signature.json",
|
||||
/* dir_mode= */ 0555,
|
||||
/* access_mode= */ 0444,
|
||||
/* tpm_pcr= */ NULL,
|
||||
@@ -360,7 +360,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
(uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_PCRPKEY],
|
||||
szs[UNIFIED_SECTION_PCRPKEY],
|
||||
".extra",
|
||||
- L"tpm2-pcr-public-key.pem",
|
||||
+ u"tpm2-pcr-public-key.pem",
|
||||
/* dir_mode= */ 0555,
|
||||
/* access_mode= */ 0444,
|
||||
/* tpm_pcr= */ NULL,
|
106
0679-macro-add-generic-IS_ALIGNED32-anf-friends.patch
Normal file
106
0679-macro-add-generic-IS_ALIGNED32-anf-friends.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From 925a5adafed2d17c4f2c50460d4e571ca509f54e Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 7 Dec 2022 18:31:27 +0100
|
||||
Subject: [PATCH] macro: add generic IS_ALIGNED32() anf friends
|
||||
|
||||
Let's generalize (and invert) the UNALIGNED32_P() macro from the sha256
|
||||
code, and let's add a test for it.
|
||||
|
||||
(cherry picked from commit 4f07388360a3513b9fc8d2773568b8def941f4a4)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/fundamental/macro-fundamental.h | 9 +++++
|
||||
src/test/test-macro.c | 53 +++++++++++++++++++++++++++++
|
||||
2 files changed, 62 insertions(+)
|
||||
|
||||
diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h
|
||||
index e0665d9dcb..dd0de328cb 100644
|
||||
--- a/src/fundamental/macro-fundamental.h
|
||||
+++ b/src/fundamental/macro-fundamental.h
|
||||
@@ -334,14 +334,23 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
|
||||
return ((l + ali - 1) & ~(ali - 1));
|
||||
}
|
||||
|
||||
+#define ALIGN2(l) ALIGN_TO(l, 2)
|
||||
#define ALIGN4(l) ALIGN_TO(l, 4)
|
||||
#define ALIGN8(l) ALIGN_TO(l, 8)
|
||||
+#define ALIGN2_PTR(p) ((void*) ALIGN2((uintptr_t) p))
|
||||
+#define ALIGN4_PTR(p) ((void*) ALIGN4((uintptr_t) p))
|
||||
+#define ALIGN8_PTR(p) ((void*) ALIGN8((uintptr_t) p))
|
||||
#ifndef SD_BOOT
|
||||
/* libefi also provides ALIGN, and we do not use them in sd-boot explicitly. */
|
||||
#define ALIGN(l) ALIGN_TO(l, sizeof(void*))
|
||||
#define ALIGN_PTR(p) ((void*) ALIGN((uintptr_t) (p)))
|
||||
#endif
|
||||
|
||||
+/* Checks if the specified pointer is aligned as appropriate for the specific type */
|
||||
+#define IS_ALIGNED16(p) (((uintptr_t) p) % __alignof__(uint16_t) == 0)
|
||||
+#define IS_ALIGNED32(p) (((uintptr_t) p) % __alignof__(uint32_t) == 0)
|
||||
+#define IS_ALIGNED64(p) (((uintptr_t) p) % __alignof__(uint64_t) == 0)
|
||||
+
|
||||
/* Same as ALIGN_TO but callable in constant contexts. */
|
||||
#define CONST_ALIGN_TO(l, ali) \
|
||||
__builtin_choose_expr( \
|
||||
diff --git a/src/test/test-macro.c b/src/test/test-macro.c
|
||||
index bb79ea0dbe..a1618c3105 100644
|
||||
--- a/src/test/test-macro.c
|
||||
+++ b/src/test/test-macro.c
|
||||
@@ -755,4 +755,57 @@ TEST(FOREACH_ARRAY) {
|
||||
assert_se(n == 0);
|
||||
}
|
||||
|
||||
+TEST(ALIGNED) {
|
||||
+ assert_se(IS_ALIGNED16(NULL));
|
||||
+ assert_se(IS_ALIGNED32(NULL));
|
||||
+ assert_se(IS_ALIGNED64(NULL));
|
||||
+
|
||||
+ uint64_t u64;
|
||||
+ uint32_t u32;
|
||||
+ uint16_t u16;
|
||||
+
|
||||
+ assert_se(IS_ALIGNED16(&u16));
|
||||
+ assert_se(IS_ALIGNED16(&u32));
|
||||
+ assert_se(IS_ALIGNED16(&u64));
|
||||
+ assert_se(IS_ALIGNED32(&u32));
|
||||
+ assert_se(IS_ALIGNED32(&u64));
|
||||
+ assert_se(IS_ALIGNED64(&u64));
|
||||
+
|
||||
+ _align_(32) uint8_t ua256;
|
||||
+ _align_(8) uint8_t ua64;
|
||||
+ _align_(4) uint8_t ua32;
|
||||
+ _align_(2) uint8_t ua16;
|
||||
+
|
||||
+ assert_se(IS_ALIGNED16(&ua256));
|
||||
+ assert_se(IS_ALIGNED32(&ua256));
|
||||
+ assert_se(IS_ALIGNED64(&ua256));
|
||||
+
|
||||
+ assert_se(IS_ALIGNED16(&ua64));
|
||||
+ assert_se(IS_ALIGNED32(&ua64));
|
||||
+ assert_se(IS_ALIGNED64(&ua64));
|
||||
+
|
||||
+ assert_se(IS_ALIGNED16(&ua32));
|
||||
+ assert_se(IS_ALIGNED32(&ua32));
|
||||
+
|
||||
+ assert_se(IS_ALIGNED16(&ua16));
|
||||
+
|
||||
+#ifdef __x86_64__
|
||||
+ /* Conditionalized on x86-64, since there we know for sure that all three types are aligned to
|
||||
+ * their size. Too lazy to figure it out for other archs */
|
||||
+ void *p = UINT_TO_PTR(1); /* definitely not aligned */
|
||||
+ assert_se(!IS_ALIGNED16(p));
|
||||
+ assert_se(!IS_ALIGNED32(p));
|
||||
+ assert_se(!IS_ALIGNED64(p));
|
||||
+
|
||||
+ assert_se(IS_ALIGNED16(ALIGN2_PTR(p)));
|
||||
+ assert_se(IS_ALIGNED32(ALIGN4_PTR(p)));
|
||||
+ assert_se(IS_ALIGNED64(ALIGN8_PTR(p)));
|
||||
+
|
||||
+ p = UINT_TO_PTR(-1); /* also definitely not aligned */
|
||||
+ assert_se(!IS_ALIGNED16(p));
|
||||
+ assert_se(!IS_ALIGNED32(p));
|
||||
+ assert_se(!IS_ALIGNED64(p));
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
214
0680-meson-use-0-1-for-SD_BOOT.patch
Normal file
214
0680-meson-use-0-1-for-SD_BOOT.patch
Normal file
@ -0,0 +1,214 @@
|
||||
From 1b03cc4e54f74c075e177b57e04cd6f9338540fd Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Tue, 10 Jan 2023 14:25:57 +0100
|
||||
Subject: [PATCH] meson: use 0|1 for SD_BOOT
|
||||
|
||||
We converted to not using #ifdef for most of our defines because the syntax is
|
||||
nicer and we are protected against typos and can set -Werror=undef. Let's do
|
||||
the same for SD_BOOT. The define is nicely hidden in build.h for normal builds,
|
||||
and for EFI builds we were already setting SD_BOOT on the commandline.
|
||||
|
||||
(cherry picked from commit 493cd5034c3eb091e7163ea1e744a4e07b410710)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
meson.build | 3 +++
|
||||
src/boot/efi/efi-string.c | 8 ++++----
|
||||
src/boot/efi/efi-string.h | 2 +-
|
||||
src/boot/efi/meson.build | 2 +-
|
||||
src/fundamental/macro-fundamental.h | 6 +++---
|
||||
src/fundamental/memory-util-fundamental.h | 2 +-
|
||||
src/fundamental/sha256.c | 2 +-
|
||||
src/fundamental/string-util-fundamental.c | 4 ++--
|
||||
src/fundamental/string-util-fundamental.h | 6 +++---
|
||||
9 files changed, 19 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 54155eee1f..843d823e3e 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -55,6 +55,9 @@ fuzzer_build = want_ossfuzz or want_libfuzzer
|
||||
# limits).
|
||||
conf.set10('FUZZ_USE_SIZE_LIMIT', fuzzer_build)
|
||||
|
||||
+# We'll set this to '1' for EFI builds in a different place.
|
||||
+conf.set10('SD_BOOT', false)
|
||||
+
|
||||
# Create a title-less summary section early, so it ends up first in the output.
|
||||
# More items are added later after they have been detected.
|
||||
summary({'build mode' : get_option('mode')})
|
||||
diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c
|
||||
index 2ba15673c9..79c296eda3 100644
|
||||
--- a/src/boot/efi/efi-string.c
|
||||
+++ b/src/boot/efi/efi-string.c
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "efi-string.h"
|
||||
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
# include "util.h"
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
@@ -378,7 +378,7 @@ bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack) {
|
||||
DEFINE_PARSE_NUMBER(char, parse_number8);
|
||||
DEFINE_PARSE_NUMBER(char16_t, parse_number16);
|
||||
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
/* To provide the actual implementation for these we need to remove the redirection to the builtins. */
|
||||
# undef memcmp
|
||||
# undef memcpy
|
||||
@@ -414,7 +414,7 @@ _used_ _weak_ void *memcpy(void * restrict dest, const void * restrict src, size
|
||||
if (!dest || !src || n == 0)
|
||||
return dest;
|
||||
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
/* The firmware-provided memcpy is likely optimized, so use that. The function is guaranteed to be
|
||||
* available by the UEFI spec. We still make it depend on the boot services pointer being set just in
|
||||
* case the compiler emits a call before it is available. */
|
||||
@@ -441,7 +441,7 @@ _used_ _weak_ void *memset(void *p, int c, size_t n) {
|
||||
if (!p || n == 0)
|
||||
return p;
|
||||
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
/* See comment in efi_memcpy. Note that the signature has c and n swapped! */
|
||||
if (_likely_(BS)) {
|
||||
BS->SetMem(p, n, c);
|
||||
diff --git a/src/boot/efi/efi-string.h b/src/boot/efi/efi-string.h
|
||||
index 25931a7d6e..aaa9b399c8 100644
|
||||
--- a/src/boot/efi/efi-string.h
|
||||
+++ b/src/boot/efi/efi-string.h
|
||||
@@ -109,7 +109,7 @@ bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack);
|
||||
bool parse_number8(const char *s, uint64_t *ret_u, const char **ret_tail);
|
||||
bool parse_number16(const char16_t *s, uint64_t *ret_u, const char16_t **ret_tail);
|
||||
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
/* The compiler normally has knowledge about standard functions such as memcmp, but this is not the case when
|
||||
* compiling with -ffreestanding. By referring to builtins, the compiler can check arguments and do
|
||||
* optimizations again. Note that we still need to provide implementations as the compiler is free to not
|
||||
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
|
||||
index ab2d7595f3..bba3b62d3c 100644
|
||||
--- a/src/boot/efi/meson.build
|
||||
+++ b/src/boot/efi/meson.build
|
||||
@@ -176,7 +176,7 @@ efi_config_h = configure_file(
|
||||
|
||||
efi_cflags = [
|
||||
'-DGNU_EFI_USE_MS_ABI',
|
||||
- '-DSD_BOOT',
|
||||
+ '-DSD_BOOT=1',
|
||||
'-ffreestanding',
|
||||
'-fshort-wchar',
|
||||
'-fvisibility=hidden',
|
||||
diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h
|
||||
index dd0de328cb..1c4c445e4e 100644
|
||||
--- a/src/fundamental/macro-fundamental.h
|
||||
+++ b/src/fundamental/macro-fundamental.h
|
||||
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
-#ifndef SD_BOOT
|
||||
+#if !SD_BOOT
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
#define XCONCATENATE(x, y) x ## y
|
||||
#define CONCATENATE(x, y) XCONCATENATE(x, y)
|
||||
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
_noreturn_ void efi_assert(const char *expr, const char *file, unsigned line, const char *function);
|
||||
|
||||
#ifdef NDEBUG
|
||||
@@ -340,7 +340,7 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
|
||||
#define ALIGN2_PTR(p) ((void*) ALIGN2((uintptr_t) p))
|
||||
#define ALIGN4_PTR(p) ((void*) ALIGN4((uintptr_t) p))
|
||||
#define ALIGN8_PTR(p) ((void*) ALIGN8((uintptr_t) p))
|
||||
-#ifndef SD_BOOT
|
||||
+#if !SD_BOOT
|
||||
/* libefi also provides ALIGN, and we do not use them in sd-boot explicitly. */
|
||||
#define ALIGN(l) ALIGN_TO(l, sizeof(void*))
|
||||
#define ALIGN_PTR(p) ((void*) ALIGN((uintptr_t) (p)))
|
||||
diff --git a/src/fundamental/memory-util-fundamental.h b/src/fundamental/memory-util-fundamental.h
|
||||
index 9015300ae8..8f50d8b8e1 100644
|
||||
--- a/src/fundamental/memory-util-fundamental.h
|
||||
+++ b/src/fundamental/memory-util-fundamental.h
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
# include "efi-string.h"
|
||||
#else
|
||||
# include <string.h>
|
||||
diff --git a/src/fundamental/sha256.c b/src/fundamental/sha256.c
|
||||
index 9b717645b3..39029de93c 100644
|
||||
--- a/src/fundamental/sha256.c
|
||||
+++ b/src/fundamental/sha256.c
|
||||
@@ -22,7 +22,7 @@
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdbool.h>
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
# include "efi-string.h"
|
||||
#else
|
||||
# include <string.h>
|
||||
diff --git a/src/fundamental/string-util-fundamental.c b/src/fundamental/string-util-fundamental.c
|
||||
index 11701ebe52..484131d72a 100644
|
||||
--- a/src/fundamental/string-util-fundamental.c
|
||||
+++ b/src/fundamental/string-util-fundamental.c
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
-#ifndef SD_BOOT
|
||||
+#if !SD_BOOT
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,7 @@ sd_char *startswith(const sd_char *s, const sd_char *prefix) {
|
||||
return (sd_char*) s + l;
|
||||
}
|
||||
|
||||
-#ifndef SD_BOOT
|
||||
+#if !SD_BOOT
|
||||
sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) {
|
||||
size_t l;
|
||||
|
||||
diff --git a/src/fundamental/string-util-fundamental.h b/src/fundamental/string-util-fundamental.h
|
||||
index ecf32e519f..523c612a17 100644
|
||||
--- a/src/fundamental/string-util-fundamental.h
|
||||
+++ b/src/fundamental/string-util-fundamental.h
|
||||
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
# include <efi.h>
|
||||
# include <efilib.h>
|
||||
# include "efi-string.h"
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "macro-fundamental.h"
|
||||
|
||||
-#ifdef SD_BOOT
|
||||
+#if SD_BOOT
|
||||
# define strlen strlen16
|
||||
# define strcmp strcmp16
|
||||
# define strncmp strncmp16
|
||||
@@ -59,7 +59,7 @@ static inline size_t strlen_ptr(const sd_char *s) {
|
||||
}
|
||||
|
||||
sd_char *startswith(const sd_char *s, const sd_char *prefix) _pure_;
|
||||
-#ifndef SD_BOOT
|
||||
+#if !SD_BOOT
|
||||
sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) _pure_;
|
||||
#endif
|
||||
sd_char *endswith(const sd_char *s, const sd_char *postfix) _pure_;
|
843
0681-boot-Add-printf-functions.patch
Normal file
843
0681-boot-Add-printf-functions.patch
Normal file
@ -0,0 +1,843 @@
|
||||
From 6f7f7bb71af6047458a41c0f7135a8d31df840c4 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Fri, 10 Jun 2022 18:55:24 +0200
|
||||
Subject: [PATCH] boot: Add printf functions
|
||||
|
||||
(cherry picked from commit 7c4536a9af986332eaac8db292b22d59b4977f04)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/efi-string.c | 491 +++++++++++++++++++++++++++++++++
|
||||
src/boot/efi/efi-string.h | 26 ++
|
||||
src/boot/efi/fuzz-efi-printf.c | 76 +++++
|
||||
src/boot/efi/meson.build | 1 +
|
||||
src/boot/efi/missing_efi.h | 12 +
|
||||
src/boot/efi/test-efi-string.c | 142 ++++++++++
|
||||
6 files changed, 748 insertions(+)
|
||||
create mode 100644 src/boot/efi/fuzz-efi-printf.c
|
||||
|
||||
diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c
|
||||
index 79c296eda3..860dfc00b2 100644
|
||||
--- a/src/boot/efi/efi-string.c
|
||||
+++ b/src/boot/efi/efi-string.c
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
+#include <wchar.h>
|
||||
|
||||
#include "efi-string.h"
|
||||
|
||||
#if SD_BOOT
|
||||
+# include "missing_efi.h"
|
||||
# include "util.h"
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
@@ -378,6 +380,495 @@ bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack) {
|
||||
DEFINE_PARSE_NUMBER(char, parse_number8);
|
||||
DEFINE_PARSE_NUMBER(char16_t, parse_number16);
|
||||
|
||||
+static const char * const warn_table[] = {
|
||||
+ [EFI_SUCCESS] = "Success",
|
||||
+#if SD_BOOT
|
||||
+ [EFI_WARN_UNKNOWN_GLYPH] = "Unknown glyph",
|
||||
+ [EFI_WARN_DELETE_FAILURE] = "Delete failure",
|
||||
+ [EFI_WARN_WRITE_FAILURE] = "Write failure",
|
||||
+ [EFI_WARN_BUFFER_TOO_SMALL] = "Buffer too small",
|
||||
+ [EFI_WARN_STALE_DATA] = "Stale data",
|
||||
+ [EFI_WARN_FILE_SYSTEM] = "File system",
|
||||
+ [EFI_WARN_RESET_REQUIRED] = "Reset required",
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+/* Errors have MSB set, remove it to keep the table compact. */
|
||||
+#define NOERR(err) ((err) & ~EFI_ERROR_MASK)
|
||||
+
|
||||
+static const char * const err_table[] = {
|
||||
+ [NOERR(EFI_ERROR_MASK)] = "Error",
|
||||
+ [NOERR(EFI_LOAD_ERROR)] = "Load error",
|
||||
+#if SD_BOOT
|
||||
+ [NOERR(EFI_INVALID_PARAMETER)] = "Invalid parameter",
|
||||
+ [NOERR(EFI_UNSUPPORTED)] = "Unsupported",
|
||||
+ [NOERR(EFI_BAD_BUFFER_SIZE)] = "Bad buffer size",
|
||||
+ [NOERR(EFI_BUFFER_TOO_SMALL)] = "Buffer too small",
|
||||
+ [NOERR(EFI_NOT_READY)] = "Not ready",
|
||||
+ [NOERR(EFI_DEVICE_ERROR)] = "Device error",
|
||||
+ [NOERR(EFI_WRITE_PROTECTED)] = "Write protected",
|
||||
+ [NOERR(EFI_OUT_OF_RESOURCES)] = "Out of resources",
|
||||
+ [NOERR(EFI_VOLUME_CORRUPTED)] = "Volume corrupt",
|
||||
+ [NOERR(EFI_VOLUME_FULL)] = "Volume full",
|
||||
+ [NOERR(EFI_NO_MEDIA)] = "No media",
|
||||
+ [NOERR(EFI_MEDIA_CHANGED)] = "Media changed",
|
||||
+ [NOERR(EFI_NOT_FOUND)] = "Not found",
|
||||
+ [NOERR(EFI_ACCESS_DENIED)] = "Access denied",
|
||||
+ [NOERR(EFI_NO_RESPONSE)] = "No response",
|
||||
+ [NOERR(EFI_NO_MAPPING)] = "No mapping",
|
||||
+ [NOERR(EFI_TIMEOUT)] = "Time out",
|
||||
+ [NOERR(EFI_NOT_STARTED)] = "Not started",
|
||||
+ [NOERR(EFI_ALREADY_STARTED)] = "Already started",
|
||||
+ [NOERR(EFI_ABORTED)] = "Aborted",
|
||||
+ [NOERR(EFI_ICMP_ERROR)] = "ICMP error",
|
||||
+ [NOERR(EFI_TFTP_ERROR)] = "TFTP error",
|
||||
+ [NOERR(EFI_PROTOCOL_ERROR)] = "Protocol error",
|
||||
+ [NOERR(EFI_INCOMPATIBLE_VERSION)] = "Incompatible version",
|
||||
+ [NOERR(EFI_SECURITY_VIOLATION)] = "Security violation",
|
||||
+ [NOERR(EFI_CRC_ERROR)] = "CRC error",
|
||||
+ [NOERR(EFI_END_OF_MEDIA)] = "End of media",
|
||||
+ [29] = "Reserved (29)",
|
||||
+ [30] = "Reserved (30)",
|
||||
+ [NOERR(EFI_END_OF_FILE)] = "End of file",
|
||||
+ [NOERR(EFI_INVALID_LANGUAGE)] = "Invalid language",
|
||||
+ [NOERR(EFI_COMPROMISED_DATA)] = "Compromised data",
|
||||
+ [NOERR(EFI_IP_ADDRESS_CONFLICT)] = "IP address conflict",
|
||||
+ [NOERR(EFI_HTTP_ERROR)] = "HTTP error",
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static const char *status_to_string(EFI_STATUS status) {
|
||||
+ if (status <= ELEMENTSOF(warn_table) - 1)
|
||||
+ return warn_table[status];
|
||||
+ if (status >= EFI_ERROR_MASK && status <= ((ELEMENTSOF(err_table) - 1) | EFI_ERROR_MASK))
|
||||
+ return err_table[NOERR(status)];
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+typedef struct {
|
||||
+ size_t padded_len; /* Field width in printf. */
|
||||
+ size_t len; /* Precision in printf. */
|
||||
+ bool pad_zero;
|
||||
+ bool align_left;
|
||||
+ bool alternative_form;
|
||||
+ bool long_arg;
|
||||
+ bool longlong_arg;
|
||||
+ bool have_field_width;
|
||||
+
|
||||
+ const char *str;
|
||||
+ const wchar_t *wstr;
|
||||
+
|
||||
+ /* For numbers. */
|
||||
+ bool is_signed;
|
||||
+ bool lowercase;
|
||||
+ int8_t base;
|
||||
+ char sign_pad; /* For + and (space) flags. */
|
||||
+} SpecifierContext;
|
||||
+
|
||||
+typedef struct {
|
||||
+ char16_t stack_buf[128]; /* We use stack_buf first to avoid allocations in most cases. */
|
||||
+ char16_t *dyn_buf; /* Allocated buf or NULL if stack_buf is used. */
|
||||
+ char16_t *buf; /* Points to the current active buf. */
|
||||
+ size_t n_buf; /* Len of buf (in char16_t's, not bytes!). */
|
||||
+ size_t n; /* Used len of buf (in char16_t's). This is always <n_buf. */
|
||||
+
|
||||
+ EFI_STATUS status;
|
||||
+ const char *format;
|
||||
+ va_list ap;
|
||||
+} FormatContext;
|
||||
+
|
||||
+static void grow_buf(FormatContext *ctx, size_t need) {
|
||||
+ assert(ctx);
|
||||
+
|
||||
+ assert_se(!__builtin_add_overflow(ctx->n, need, &need));
|
||||
+
|
||||
+ if (need < ctx->n_buf)
|
||||
+ return;
|
||||
+
|
||||
+ /* Greedily allocate if we can. */
|
||||
+ if (__builtin_mul_overflow(need, 2, &ctx->n_buf))
|
||||
+ ctx->n_buf = need;
|
||||
+
|
||||
+ /* We cannot use realloc here as ctx->buf may be ctx->stack_buf, which we cannot free. */
|
||||
+ char16_t *new_buf = xnew(char16_t, ctx->n_buf);
|
||||
+ memcpy(new_buf, ctx->buf, ctx->n * sizeof(*ctx->buf));
|
||||
+
|
||||
+ free(ctx->dyn_buf);
|
||||
+ ctx->buf = ctx->dyn_buf = new_buf;
|
||||
+}
|
||||
+
|
||||
+static void push_padding(FormatContext *ctx, char pad, size_t len) {
|
||||
+ assert(ctx);
|
||||
+ while (len > 0) {
|
||||
+ len--;
|
||||
+ ctx->buf[ctx->n++] = pad;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool push_str(FormatContext *ctx, SpecifierContext *sp) {
|
||||
+ assert(ctx);
|
||||
+ assert(sp);
|
||||
+
|
||||
+ sp->padded_len = LESS_BY(sp->padded_len, sp->len);
|
||||
+
|
||||
+ grow_buf(ctx, sp->padded_len + sp->len);
|
||||
+
|
||||
+ if (!sp->align_left)
|
||||
+ push_padding(ctx, ' ', sp->padded_len);
|
||||
+
|
||||
+ /* In userspace unit tests we cannot just memcpy() the wide string. */
|
||||
+ if (sp->wstr && sizeof(wchar_t) == sizeof(char16_t)) {
|
||||
+ memcpy(ctx->buf + ctx->n, sp->wstr, sp->len * sizeof(*sp->wstr));
|
||||
+ ctx->n += sp->len;
|
||||
+ } else
|
||||
+ for (size_t i = 0; i < sp->len; i++)
|
||||
+ ctx->buf[ctx->n++] = sp->str ? sp->str[i] : sp->wstr[i];
|
||||
+
|
||||
+ if (sp->align_left)
|
||||
+ push_padding(ctx, ' ', sp->padded_len);
|
||||
+
|
||||
+ assert(ctx->n < ctx->n_buf);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool push_num(FormatContext *ctx, SpecifierContext *sp, uint64_t u) {
|
||||
+ const char *digits = sp->lowercase ? "0123456789abcdef" : "0123456789ABCDEF";
|
||||
+ char16_t tmp[32];
|
||||
+ size_t n = 0;
|
||||
+
|
||||
+ assert(ctx);
|
||||
+ assert(sp);
|
||||
+ assert(IN_SET(sp->base, 10, 16));
|
||||
+
|
||||
+ /* "%.0u" prints nothing if value is 0. */
|
||||
+ if (u == 0 && sp->len == 0)
|
||||
+ return true;
|
||||
+
|
||||
+ if (sp->is_signed && (int64_t) u < 0) {
|
||||
+ /* We cannot just do "u = -(int64_t)u" here because -INT64_MIN overflows. */
|
||||
+
|
||||
+ uint64_t rem = -((int64_t) u % sp->base);
|
||||
+ u = (int64_t) u / -sp->base;
|
||||
+ tmp[n++] = digits[rem];
|
||||
+ sp->sign_pad = '-';
|
||||
+ }
|
||||
+
|
||||
+ while (u > 0 || n == 0) {
|
||||
+ uint64_t rem = u % sp->base;
|
||||
+ u /= sp->base;
|
||||
+ tmp[n++] = digits[rem];
|
||||
+ }
|
||||
+
|
||||
+ /* Note that numbers never get truncated! */
|
||||
+ size_t prefix = (sp->sign_pad != 0 ? 1 : 0) + (sp->alternative_form ? 2 : 0);
|
||||
+ size_t number_len = prefix + MAX(n, sp->len);
|
||||
+ grow_buf(ctx, MAX(sp->padded_len, number_len));
|
||||
+
|
||||
+ size_t padding = 0;
|
||||
+ if (sp->pad_zero)
|
||||
+ /* Leading zeroes go after the sign or 0x prefix. */
|
||||
+ number_len = MAX(number_len, sp->padded_len);
|
||||
+ else
|
||||
+ padding = LESS_BY(sp->padded_len, number_len);
|
||||
+
|
||||
+ if (!sp->align_left)
|
||||
+ push_padding(ctx, ' ', padding);
|
||||
+
|
||||
+ if (sp->sign_pad != 0)
|
||||
+ ctx->buf[ctx->n++] = sp->sign_pad;
|
||||
+ if (sp->alternative_form) {
|
||||
+ ctx->buf[ctx->n++] = '0';
|
||||
+ ctx->buf[ctx->n++] = sp->lowercase ? 'x' : 'X';
|
||||
+ }
|
||||
+
|
||||
+ push_padding(ctx, '0', LESS_BY(number_len, n + prefix));
|
||||
+
|
||||
+ while (n > 0)
|
||||
+ ctx->buf[ctx->n++] = tmp[--n];
|
||||
+
|
||||
+ if (sp->align_left)
|
||||
+ push_padding(ctx, ' ', padding);
|
||||
+
|
||||
+ assert(ctx->n < ctx->n_buf);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/* This helps unit testing. */
|
||||
+#if SD_BOOT
|
||||
+# define NULLSTR "(null)"
|
||||
+# define wcsnlen strnlen16
|
||||
+#else
|
||||
+# define NULLSTR "(nil)"
|
||||
+#endif
|
||||
+
|
||||
+static bool handle_format_specifier(FormatContext *ctx, SpecifierContext *sp) {
|
||||
+ /* Parses one item from the format specifier in ctx and put the info into sp. If we are done with
|
||||
+ * this specifier returns true, otherwise this function should be called again. */
|
||||
+
|
||||
+ /* This implementation assumes 32bit ints. Also note that all types smaller than int are promoted to
|
||||
+ * int in vararg functions, which is why we fetch only ints for any such types. The compiler would
|
||||
+ * otherwise warn about fetching smaller types. */
|
||||
+ assert_cc(sizeof(int) == 4);
|
||||
+ assert_cc(sizeof(wchar_t) <= sizeof(int));
|
||||
+ assert_cc(sizeof(intmax_t) <= sizeof(long long));
|
||||
+
|
||||
+ assert(ctx);
|
||||
+ assert(sp);
|
||||
+
|
||||
+ switch (*ctx->format) {
|
||||
+ case '#':
|
||||
+ sp->alternative_form = true;
|
||||
+ return false;
|
||||
+ case '.':
|
||||
+ sp->have_field_width = true;
|
||||
+ return false;
|
||||
+ case '-':
|
||||
+ sp->align_left = true;
|
||||
+ return false;
|
||||
+ case '+':
|
||||
+ case ' ':
|
||||
+ sp->sign_pad = *ctx->format;
|
||||
+ return false;
|
||||
+
|
||||
+ case '0':
|
||||
+ if (!sp->have_field_width) {
|
||||
+ sp->pad_zero = true;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* If field width has already been provided then 0 is part of precision (%.0s). */
|
||||
+ _fallthrough_;
|
||||
+
|
||||
+ case '*':
|
||||
+ case '1' ... '9': {
|
||||
+ int64_t i;
|
||||
+
|
||||
+ if (*ctx->format == '*')
|
||||
+ i = va_arg(ctx->ap, int);
|
||||
+ else {
|
||||
+ uint64_t u;
|
||||
+ if (!parse_number8(ctx->format, &u, &ctx->format) || u > INT_MAX)
|
||||
+ assert_not_reached();
|
||||
+ ctx->format--; /* Point it back to the last digit. */
|
||||
+ i = u;
|
||||
+ }
|
||||
+
|
||||
+ if (sp->have_field_width) {
|
||||
+ /* Negative precision is ignored. */
|
||||
+ if (i >= 0)
|
||||
+ sp->len = (size_t) i;
|
||||
+ } else {
|
||||
+ /* Negative field width is treated as positive field width with '-' flag. */
|
||||
+ if (i < 0) {
|
||||
+ i *= -1;
|
||||
+ sp->align_left = true;
|
||||
+ }
|
||||
+ sp->padded_len = i;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ case 'h':
|
||||
+ if (*(ctx->format + 1) == 'h')
|
||||
+ ctx->format++;
|
||||
+ /* char/short gets promoted to int, nothing to do here. */
|
||||
+ return false;
|
||||
+
|
||||
+ case 'l':
|
||||
+ if (*(ctx->format + 1) == 'l') {
|
||||
+ ctx->format++;
|
||||
+ sp->longlong_arg = true;
|
||||
+ } else
|
||||
+ sp->long_arg = true;
|
||||
+ return false;
|
||||
+
|
||||
+ case 'z':
|
||||
+ sp->long_arg = sizeof(size_t) == sizeof(long);
|
||||
+ sp->longlong_arg = !sp->long_arg && sizeof(size_t) == sizeof(long long);
|
||||
+ return false;
|
||||
+
|
||||
+ case 'j':
|
||||
+ sp->long_arg = sizeof(intmax_t) == sizeof(long);
|
||||
+ sp->longlong_arg = !sp->long_arg && sizeof(intmax_t) == sizeof(long long);
|
||||
+ return false;
|
||||
+
|
||||
+ case 't':
|
||||
+ sp->long_arg = sizeof(ptrdiff_t) == sizeof(long);
|
||||
+ sp->longlong_arg = !sp->long_arg && sizeof(ptrdiff_t) == sizeof(long long);
|
||||
+ return false;
|
||||
+
|
||||
+ case '%':
|
||||
+ sp->str = "%";
|
||||
+ sp->len = 1;
|
||||
+ return push_str(ctx, sp);
|
||||
+
|
||||
+ case 'c':
|
||||
+ sp->wstr = &(wchar_t){ va_arg(ctx->ap, int) };
|
||||
+ sp->len = 1;
|
||||
+ return push_str(ctx, sp);
|
||||
+
|
||||
+ case 's':
|
||||
+ if (sp->long_arg) {
|
||||
+ sp->wstr = va_arg(ctx->ap, const wchar_t *) ?: L"(null)";
|
||||
+ sp->len = wcsnlen(sp->wstr, sp->len);
|
||||
+ } else {
|
||||
+ sp->str = va_arg(ctx->ap, const char *) ?: "(null)";
|
||||
+ sp->len = strnlen8(sp->str, sp->len);
|
||||
+ }
|
||||
+ return push_str(ctx, sp);
|
||||
+
|
||||
+ case 'd':
|
||||
+ case 'i':
|
||||
+ case 'u':
|
||||
+ case 'x':
|
||||
+ case 'X':
|
||||
+ sp->lowercase = *ctx->format == 'x';
|
||||
+ sp->is_signed = IN_SET(*ctx->format, 'd', 'i');
|
||||
+ sp->base = IN_SET(*ctx->format, 'x', 'X') ? 16 : 10;
|
||||
+ if (sp->len == SIZE_MAX)
|
||||
+ sp->len = 1;
|
||||
+
|
||||
+ uint64_t v;
|
||||
+ if (sp->longlong_arg)
|
||||
+ v = sp->is_signed ? (uint64_t) va_arg(ctx->ap, long long) :
|
||||
+ va_arg(ctx->ap, unsigned long long);
|
||||
+ else if (sp->long_arg)
|
||||
+ v = sp->is_signed ? (uint64_t) va_arg(ctx->ap, long) : va_arg(ctx->ap, unsigned long);
|
||||
+ else
|
||||
+ v = sp->is_signed ? (uint64_t) va_arg(ctx->ap, int) : va_arg(ctx->ap, unsigned);
|
||||
+
|
||||
+ return push_num(ctx, sp, v);
|
||||
+
|
||||
+ case 'p': {
|
||||
+ const void *ptr = va_arg(ctx->ap, const void *);
|
||||
+ if (!ptr) {
|
||||
+ sp->str = NULLSTR;
|
||||
+ sp->len = STRLEN(NULLSTR);
|
||||
+ return push_str(ctx, sp);
|
||||
+ }
|
||||
+
|
||||
+ sp->base = 16;
|
||||
+ sp->lowercase = true;
|
||||
+ sp->alternative_form = true;
|
||||
+ sp->len = 0; /* Precision is ignored for %p. */
|
||||
+ return push_num(ctx, sp, (uintptr_t) ptr);
|
||||
+ }
|
||||
+
|
||||
+ case 'm': {
|
||||
+ sp->str = status_to_string(ctx->status);
|
||||
+ if (sp->str) {
|
||||
+ sp->len = strlen8(sp->str);
|
||||
+ return push_str(ctx, sp);
|
||||
+ }
|
||||
+
|
||||
+ sp->base = 16;
|
||||
+ sp->lowercase = true;
|
||||
+ sp->alternative_form = true;
|
||||
+ sp->len = 0;
|
||||
+ return push_num(ctx, sp, ctx->status);
|
||||
+ }
|
||||
+
|
||||
+ default:
|
||||
+ assert_not_reached();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* printf_internal is largely compatible to userspace vasprintf. Any features omitted should trigger asserts.
|
||||
+ *
|
||||
+ * Supported:
|
||||
+ * - Flags: #, 0, +, -, space
|
||||
+ * - Lengths: h, hh, l, ll, z, j, t
|
||||
+ * - Specifiers: %, c, s, u, i, d, x, X, p, m
|
||||
+ * - Precision and width (inline or as int arg using *)
|
||||
+ *
|
||||
+ * Notable differences:
|
||||
+ * - Passing NULL to %s is permitted and will print "(null)"
|
||||
+ * - %p will also use "(null)"
|
||||
+ * - The provided EFI_STATUS is used for %m instead of errno
|
||||
+ * - "\n" is translated to "\r\n" */
|
||||
+_printf_(2, 0) static char16_t *printf_internal(EFI_STATUS status, const char *format, va_list ap, bool ret) {
|
||||
+ assert(format);
|
||||
+
|
||||
+ FormatContext ctx = {
|
||||
+ .buf = ctx.stack_buf,
|
||||
+ .n_buf = ELEMENTSOF(ctx.stack_buf),
|
||||
+ .format = format,
|
||||
+ .status = status,
|
||||
+ };
|
||||
+
|
||||
+ /* We cannot put this into the struct without making a copy. */
|
||||
+ va_copy(ctx.ap, ap);
|
||||
+
|
||||
+ while (*ctx.format != '\0') {
|
||||
+ SpecifierContext sp = { .len = SIZE_MAX };
|
||||
+
|
||||
+ switch (*ctx.format) {
|
||||
+ case '%':
|
||||
+ ctx.format++;
|
||||
+ while (!handle_format_specifier(&ctx, &sp))
|
||||
+ ctx.format++;
|
||||
+ ctx.format++;
|
||||
+ break;
|
||||
+ case '\n':
|
||||
+ ctx.format++;
|
||||
+ sp.str = "\r\n";
|
||||
+ sp.len = 2;
|
||||
+ push_str(&ctx, &sp);
|
||||
+ break;
|
||||
+ default:
|
||||
+ sp.str = ctx.format++;
|
||||
+ while (!IN_SET(*ctx.format, '%', '\n', '\0'))
|
||||
+ ctx.format++;
|
||||
+ sp.len = ctx.format - sp.str;
|
||||
+ push_str(&ctx, &sp);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ va_end(ctx.ap);
|
||||
+
|
||||
+ assert(ctx.n < ctx.n_buf);
|
||||
+ ctx.buf[ctx.n++] = '\0';
|
||||
+
|
||||
+ if (ret) {
|
||||
+ if (ctx.dyn_buf)
|
||||
+ return TAKE_PTR(ctx.dyn_buf);
|
||||
+
|
||||
+ char16_t *ret_buf = xnew(char16_t, ctx.n);
|
||||
+ memcpy(ret_buf, ctx.buf, ctx.n * sizeof(*ctx.buf));
|
||||
+ return ret_buf;
|
||||
+ }
|
||||
+
|
||||
+#if SD_BOOT
|
||||
+ ST->ConOut->OutputString(ST->ConOut, ctx.buf);
|
||||
+#endif
|
||||
+
|
||||
+ return mfree(ctx.dyn_buf);
|
||||
+}
|
||||
+
|
||||
+void printf_status(EFI_STATUS status, const char *format, ...) {
|
||||
+ va_list ap;
|
||||
+ va_start(ap, format);
|
||||
+ printf_internal(status, format, ap, false);
|
||||
+ va_end(ap);
|
||||
+}
|
||||
+
|
||||
+void vprintf_status(EFI_STATUS status, const char *format, va_list ap) {
|
||||
+ printf_internal(status, format, ap, false);
|
||||
+}
|
||||
+
|
||||
+char16_t *xasprintf_status(EFI_STATUS status, const char *format, ...) {
|
||||
+ va_list ap;
|
||||
+ va_start(ap, format);
|
||||
+ char16_t *ret = printf_internal(status, format, ap, true);
|
||||
+ va_end(ap);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+char16_t *xvasprintf_status(EFI_STATUS status, const char *format, va_list ap) {
|
||||
+ return printf_internal(status, format, ap, true);
|
||||
+}
|
||||
+
|
||||
#if SD_BOOT
|
||||
/* To provide the actual implementation for these we need to remove the redirection to the builtins. */
|
||||
# undef memcmp
|
||||
diff --git a/src/boot/efi/efi-string.h b/src/boot/efi/efi-string.h
|
||||
index aaa9b399c8..2a28db3593 100644
|
||||
--- a/src/boot/efi/efi-string.h
|
||||
+++ b/src/boot/efi/efi-string.h
|
||||
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
+#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <uchar.h>
|
||||
@@ -109,7 +110,32 @@ bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack);
|
||||
bool parse_number8(const char *s, uint64_t *ret_u, const char **ret_tail);
|
||||
bool parse_number16(const char16_t *s, uint64_t *ret_u, const char16_t **ret_tail);
|
||||
|
||||
+typedef size_t EFI_STATUS;
|
||||
+
|
||||
+#if !SD_BOOT
|
||||
+/* Provide these for unit testing. */
|
||||
+enum {
|
||||
+ EFI_ERROR_MASK = ((EFI_STATUS) 1 << (sizeof(EFI_STATUS) * CHAR_BIT - 1)),
|
||||
+ EFI_SUCCESS = 0,
|
||||
+ EFI_LOAD_ERROR = 1 | EFI_ERROR_MASK,
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+#ifdef __clang__
|
||||
+# define _gnu_printf_(a, b) _printf_(a, b)
|
||||
+#else
|
||||
+# define _gnu_printf_(a, b) __attribute__((format(gnu_printf, a, b)))
|
||||
+#endif
|
||||
+
|
||||
+_gnu_printf_(2, 3) void printf_status(EFI_STATUS status, const char *format, ...);
|
||||
+_gnu_printf_(2, 0) void vprintf_status(EFI_STATUS status, const char *format, va_list ap);
|
||||
+_gnu_printf_(2, 3) _warn_unused_result_ char16_t *xasprintf_status(EFI_STATUS status, const char *format, ...);
|
||||
+_gnu_printf_(2, 0) _warn_unused_result_ char16_t *xvasprintf_status(EFI_STATUS status, const char *format, va_list ap);
|
||||
+
|
||||
#if SD_BOOT
|
||||
+# define printf(...) printf_status(EFI_SUCCESS, __VA_ARGS__)
|
||||
+# define xasprintf(...) xasprintf_status(EFI_SUCCESS, __VA_ARGS__)
|
||||
+
|
||||
/* The compiler normally has knowledge about standard functions such as memcmp, but this is not the case when
|
||||
* compiling with -ffreestanding. By referring to builtins, the compiler can check arguments and do
|
||||
* optimizations again. Note that we still need to provide implementations as the compiler is free to not
|
||||
diff --git a/src/boot/efi/fuzz-efi-printf.c b/src/boot/efi/fuzz-efi-printf.c
|
||||
new file mode 100644
|
||||
index 0000000000..218a427cef
|
||||
--- /dev/null
|
||||
+++ b/src/boot/efi/fuzz-efi-printf.c
|
||||
@@ -0,0 +1,76 @@
|
||||
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
+
|
||||
+#include "alloc-util.h"
|
||||
+#include "efi-string.h"
|
||||
+#include "fuzz.h"
|
||||
+#include "utf8.h"
|
||||
+
|
||||
+typedef struct {
|
||||
+ EFI_STATUS status;
|
||||
+ int16_t field_width;
|
||||
+ int16_t precision;
|
||||
+ const void *ptr;
|
||||
+ char c;
|
||||
+ unsigned char uchar;
|
||||
+ signed char schar;
|
||||
+ unsigned short ushort;
|
||||
+ signed short sshort;
|
||||
+ unsigned int uint;
|
||||
+ signed int sint;
|
||||
+ unsigned long ulong;
|
||||
+ signed long slong;
|
||||
+ unsigned long long ulonglong;
|
||||
+ signed long long slonglong;
|
||||
+ size_t size;
|
||||
+ ssize_t ssize;
|
||||
+ intmax_t intmax;
|
||||
+ uintmax_t uintmax;
|
||||
+ ptrdiff_t ptrdiff;
|
||||
+ char str[];
|
||||
+} Input;
|
||||
+
|
||||
+#define PRINTF_ONE(...) \
|
||||
+ ({ \
|
||||
+ _cleanup_free_ char16_t *_ret = xasprintf_status(__VA_ARGS__); \
|
||||
+ DO_NOT_OPTIMIZE(_ret); \
|
||||
+ })
|
||||
+
|
||||
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
+ if (outside_size_range(size, sizeof(Input), 1024 * 1024))
|
||||
+ return 0;
|
||||
+
|
||||
+ const Input *i = (const Input *) data;
|
||||
+ size_t len = size - offsetof(Input, str);
|
||||
+
|
||||
+ PRINTF_ONE(i->status, "%*.*s", i->field_width, (int) len, i->str);
|
||||
+ PRINTF_ONE(i->status, "%*.*ls", i->field_width, (int) (len / sizeof(wchar_t)), (const wchar_t *) i->str);
|
||||
+
|
||||
+ PRINTF_ONE(i->status, "%% %*.*m", i->field_width, i->precision);
|
||||
+ PRINTF_ONE(i->status, "%*p", i->field_width, i->ptr);
|
||||
+ PRINTF_ONE(i->status, "%*c %12340c %56789c", i->field_width, i->c, i->c, i->c);
|
||||
+
|
||||
+ PRINTF_ONE(i->status, "%*.*hhu", i->field_width, i->precision, i->uchar);
|
||||
+ PRINTF_ONE(i->status, "%*.*hhi", i->field_width, i->precision, i->schar);
|
||||
+ PRINTF_ONE(i->status, "%*.*hu", i->field_width, i->precision, i->ushort);
|
||||
+ PRINTF_ONE(i->status, "%*.*hi", i->field_width, i->precision, i->sshort);
|
||||
+ PRINTF_ONE(i->status, "%*.*u", i->field_width, i->precision, i->uint);
|
||||
+ PRINTF_ONE(i->status, "%*.*i", i->field_width, i->precision, i->sint);
|
||||
+ PRINTF_ONE(i->status, "%*.*lu", i->field_width, i->precision, i->ulong);
|
||||
+ PRINTF_ONE(i->status, "%*.*li", i->field_width, i->precision, i->slong);
|
||||
+ PRINTF_ONE(i->status, "%*.*llu", i->field_width, i->precision, i->ulonglong);
|
||||
+ PRINTF_ONE(i->status, "%*.*lli", i->field_width, i->precision, i->slonglong);
|
||||
+
|
||||
+ PRINTF_ONE(i->status, "%+*.*hhi", i->field_width, i->precision, i->schar);
|
||||
+ PRINTF_ONE(i->status, "%-*.*hi", i->field_width, i->precision, i->sshort);
|
||||
+ PRINTF_ONE(i->status, "% *.*i", i->field_width, i->precision, i->sint);
|
||||
+ PRINTF_ONE(i->status, "%0*li", i->field_width, i->slong);
|
||||
+ PRINTF_ONE(i->status, "%#*.*llx", i->field_width, i->precision, i->ulonglong);
|
||||
+
|
||||
+ PRINTF_ONE(i->status, "%-*.*zx", i->field_width, i->precision, i->size);
|
||||
+ PRINTF_ONE(i->status, "% *.*zi", i->field_width, i->precision, i->ssize);
|
||||
+ PRINTF_ONE(i->status, "%0*ji", i->field_width, i->intmax);
|
||||
+ PRINTF_ONE(i->status, "%#0*jX", i->field_width, i->uintmax);
|
||||
+ PRINTF_ONE(i->status, "%*.*ti", i->field_width, i->precision, i->ptrdiff);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
|
||||
index bba3b62d3c..ed332262e8 100644
|
||||
--- a/src/boot/efi/meson.build
|
||||
+++ b/src/boot/efi/meson.build
|
||||
@@ -423,6 +423,7 @@ if efi_arch[1] in ['ia32', 'x86_64', 'arm', 'aarch64']
|
||||
fuzzers += [
|
||||
[files('fuzz-bcd.c', 'bcd.c', 'efi-string.c')],
|
||||
[files('fuzz-efi-string.c', 'efi-string.c')],
|
||||
+ [files('fuzz-efi-printf.c', 'efi-string.c')],
|
||||
]
|
||||
endif
|
||||
|
||||
diff --git a/src/boot/efi/missing_efi.h b/src/boot/efi/missing_efi.h
|
||||
index b446e0399f..a71c8fa7e2 100644
|
||||
--- a/src/boot/efi/missing_efi.h
|
||||
+++ b/src/boot/efi/missing_efi.h
|
||||
@@ -417,3 +417,15 @@ struct EFI_BOOT_MANAGER_POLICY_PROTOCOL {
|
||||
EFI_GUID *Class);
|
||||
};
|
||||
#endif
|
||||
+
|
||||
+#ifndef EFI_WARN_UNKNOWN_GLYPH
|
||||
+# define EFI_WARN_UNKNOWN_GLYPH 1
|
||||
+#endif
|
||||
+
|
||||
+#ifndef EFI_WARN_RESET_REQUIRED
|
||||
+# define EFI_WARN_STALE_DATA 5
|
||||
+# define EFI_WARN_FILE_SYSTEM 6
|
||||
+# define EFI_WARN_RESET_REQUIRED 7
|
||||
+# define EFI_IP_ADDRESS_CONFLICT EFIERR(34)
|
||||
+# define EFI_HTTP_ERROR EFIERR(35)
|
||||
+#endif
|
||||
diff --git a/src/boot/efi/test-efi-string.c b/src/boot/efi/test-efi-string.c
|
||||
index 7b43e1d629..c26973d8bd 100644
|
||||
--- a/src/boot/efi/test-efi-string.c
|
||||
+++ b/src/boot/efi/test-efi-string.c
|
||||
@@ -468,6 +468,148 @@ TEST(parse_number16) {
|
||||
assert_se(streq16(tail, u"rest"));
|
||||
}
|
||||
|
||||
+_printf_(1, 2) static void test_printf_one(const char *format, ...) {
|
||||
+ va_list ap, ap_efi;
|
||||
+ va_start(ap, format);
|
||||
+ va_copy(ap_efi, ap);
|
||||
+
|
||||
+ _cleanup_free_ char *buf = NULL;
|
||||
+ int r = vasprintf(&buf, format, ap);
|
||||
+ assert_se(r >= 0);
|
||||
+ log_info("/* %s(%s) -> \"%.100s\" */", __func__, format, buf);
|
||||
+
|
||||
+ _cleanup_free_ char16_t *buf_efi = xvasprintf_status(0, format, ap_efi);
|
||||
+
|
||||
+ bool eq = true;
|
||||
+ for (size_t i = 0; i <= (size_t) r; i++) {
|
||||
+ if (buf[i] != buf_efi[i])
|
||||
+ eq = false;
|
||||
+ buf[i] = buf_efi[i];
|
||||
+ }
|
||||
+
|
||||
+ log_info("%.100s", buf);
|
||||
+ assert_se(eq);
|
||||
+
|
||||
+ va_end(ap);
|
||||
+ va_end(ap_efi);
|
||||
+}
|
||||
+
|
||||
+TEST(xvasprintf_status) {
|
||||
+#pragma GCC diagnostic push
|
||||
+#pragma GCC diagnostic ignored "-Wformat-zero-length"
|
||||
+ test_printf_one("");
|
||||
+#pragma GCC diagnostic pop
|
||||
+ test_printf_one("string");
|
||||
+ test_printf_one("%%-%%%%");
|
||||
+
|
||||
+ test_printf_one("%p %p %32p %*p %*p", NULL, (void *) 0xF, &errno, 0, &saved_argc, 20, &saved_argv);
|
||||
+ test_printf_one("%-10p %-32p %-*p %-*p", NULL, &errno, 0, &saved_argc, 20, &saved_argv);
|
||||
+
|
||||
+ test_printf_one("%c %3c %*c %*c %-8c", '1', '!', 0, 'a', 9, '_', '>');
|
||||
+
|
||||
+ test_printf_one("%s %s %s", "012345", "6789", "ab");
|
||||
+ test_printf_one("%.4s %.4s %.4s %.0s", "cdefgh", "ijkl", "mn", "@");
|
||||
+ test_printf_one("%8s %8s %8s", "opqrst", "uvwx", "yz");
|
||||
+ test_printf_one("%8.4s %8.4s %8.4s %8.0s", "ABCDEF", "GHIJ", "KL", "$");
|
||||
+ test_printf_one("%4.8s %4.8s %4.8s", "ABCDEFGHIJ", "ABCDEFGH", "ABCD");
|
||||
+
|
||||
+ test_printf_one("%.*s %.*s %.*s %.*s", 4, "012345", 4, "6789", 4, "ab", 0, "&");
|
||||
+ test_printf_one("%*s %*s %*s", 8, "cdefgh", 8, "ijkl", 8, "mn");
|
||||
+ test_printf_one("%*.*s %*.*s %*.*s %*.*s", 8, 4, "opqrst", 8, 4, "uvwx", 8, 4, "yz", 8, 0, "#");
|
||||
+ test_printf_one("%*.*s %*.*s %*.*s", 3, 8, "OPQRST", 3, 8, "UVWX", 3, 8, "YZ");
|
||||
+
|
||||
+ test_printf_one("%ls %ls %ls", L"012345", L"6789", L"ab");
|
||||
+ test_printf_one("%.4ls %.4ls %.4ls %.0ls", L"cdefgh", L"ijkl", L"mn", L"@");
|
||||
+ test_printf_one("%8ls %8ls %8ls", L"opqrst", L"uvwx", L"yz");
|
||||
+ test_printf_one("%8.4ls %8.4ls %8.4ls %8.0ls", L"ABCDEF", L"GHIJ", L"KL", L"$");
|
||||
+ test_printf_one("%4.8ls %4.8ls %4.8ls", L"ABCDEFGHIJ", L"ABCDEFGH", L"ABCD");
|
||||
+
|
||||
+ test_printf_one("%.*ls %.*ls %.*ls %.*ls", 4, L"012345", 4, L"6789", 4, L"ab", 0, L"&");
|
||||
+ test_printf_one("%*ls %*ls %*ls", 8, L"cdefgh", 8, L"ijkl", 8, L"mn");
|
||||
+ test_printf_one("%*.*ls %*.*ls %*.*ls %*.*ls", 8, 4, L"opqrst", 8, 4, L"uvwx", 8, 4, L"yz", 8, 0, L"#");
|
||||
+ test_printf_one("%*.*ls %*.*ls %*.*ls", 3, 8, L"OPQRST", 3, 8, L"UVWX", 3, 8, L"YZ");
|
||||
+
|
||||
+ test_printf_one("%-14s %-10.0s %-10.3s", "left", "", "chopped");
|
||||
+ test_printf_one("%-14ls %-10.0ls %-10.3ls", L"left", L"", L"chopped");
|
||||
+
|
||||
+ test_printf_one("%.6s", (char[]){ 'n', 'o', ' ', 'n', 'u', 'l' });
|
||||
+ test_printf_one("%.6ls", (wchar_t[]){ 'n', 'o', ' ', 'n', 'u', 'l' });
|
||||
+
|
||||
+ test_printf_one("%u %u %u", 0U, 42U, 1234567890U);
|
||||
+ test_printf_one("%i %i %i", 0, -42, -1234567890);
|
||||
+ test_printf_one("%x %x %x", 0x0U, 0x42U, 0x123ABCU);
|
||||
+ test_printf_one("%X %X %X", 0x1U, 0x43U, 0x234BCDU);
|
||||
+ test_printf_one("%#x %#x %#x", 0x2U, 0x44U, 0x345CDEU);
|
||||
+ test_printf_one("%#X %#X %#X", 0x3U, 0x45U, 0x456FEDU);
|
||||
+
|
||||
+ test_printf_one("%u %lu %llu %zu", UINT_MAX, ULONG_MAX, ULLONG_MAX, SIZE_MAX);
|
||||
+ test_printf_one("%i %i %zi", INT_MIN, INT_MAX, SSIZE_MAX);
|
||||
+ test_printf_one("%li %li %lli %lli", LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX);
|
||||
+ test_printf_one("%x %#lx %llx %#zx", UINT_MAX, ULONG_MAX, ULLONG_MAX, SIZE_MAX);
|
||||
+ test_printf_one("%X %#lX %llX %#zX", UINT_MAX, ULONG_MAX, ULLONG_MAX, SIZE_MAX);
|
||||
+ test_printf_one("%ju %ji %ji", UINTMAX_MAX, INTMAX_MIN, INTMAX_MAX);
|
||||
+ test_printf_one("%ti %ti", PTRDIFF_MIN, PTRDIFF_MAX);
|
||||
+
|
||||
+ test_printf_one("%" PRIu32 " %" PRIi32 " %" PRIi32, UINT32_MAX, INT32_MIN, INT32_MAX);
|
||||
+ test_printf_one("%" PRIx32 " %" PRIX32, UINT32_MAX, UINT32_MAX);
|
||||
+ test_printf_one("%#" PRIx32 " %#" PRIX32, UINT32_MAX, UINT32_MAX);
|
||||
+
|
||||
+ test_printf_one("%" PRIu64 " %" PRIi64 " %" PRIi64, UINT64_MAX, INT64_MIN, INT64_MAX);
|
||||
+ test_printf_one("%" PRIx64 " %" PRIX64, UINT64_MAX, UINT64_MAX);
|
||||
+ test_printf_one("%#" PRIx64 " %#" PRIX64, UINT64_MAX, UINT64_MAX);
|
||||
+
|
||||
+ test_printf_one("%.11u %.11i %.11x %.11X %#.11x %#.11X", 1U, -2, 3U, 0xA1U, 0xB2U, 0xC3U);
|
||||
+ test_printf_one("%13u %13i %13x %13X %#13x %#13X", 4U, -5, 6U, 0xD4U, 0xE5U, 0xF6U);
|
||||
+ test_printf_one("%9.5u %9.5i %9.5x %9.5X %#9.5x %#9.5X", 7U, -8, 9U, 0xA9U, 0xB8U, 0xC7U);
|
||||
+ test_printf_one("%09u %09i %09x %09X %#09x %#09X", 4U, -5, 6U, 0xD6U, 0xE5U, 0xF4U);
|
||||
+
|
||||
+ test_printf_one("%*u %.*u %*i %.*i", 15, 42U, 15, 43U, 15, -42, 15, -43);
|
||||
+ test_printf_one("%*.*u %*.*i", 14, 10, 13U, 14, 10, -14);
|
||||
+ test_printf_one("%*x %*X %.*x %.*X", 15, 0x1AU, 15, 0x2BU, 15, 0x3CU, 15, 0x4DU);
|
||||
+ test_printf_one("%#*x %#*X %#.*x %#.*X", 15, 0xA1U, 15, 0xB2U, 15, 0xC3U, 15, 0xD4U);
|
||||
+ test_printf_one("%*.*x %*.*X", 14, 10, 0x1AU, 14, 10, 0x2BU);
|
||||
+ test_printf_one("%#*.*x %#*.*X", 14, 10, 0x3CU, 14, 10, 0x4DU);
|
||||
+
|
||||
+ test_printf_one("%+.5i %+.5i % .7i % .7i", -15, 51, -15, 51);
|
||||
+ test_printf_one("%+5.i %+5.i % 7.i % 7.i", -15, 51, -15, 51);
|
||||
+
|
||||
+ test_printf_one("%-10u %-10i %-10x %#-10X %- 10i", 1u, -2, 0xA2D2u, 0XB3F4u, -512);
|
||||
+ test_printf_one("%-10.6u %-10.6i %-10.6x %#-10.6X %- 10.6i", 1u, -2, 0xA2D2u, 0XB3F4u, -512);
|
||||
+ test_printf_one("%-6.10u %-6.10i %-6.10x %#-6.10X %- 6.10i", 3u, -4, 0x2A2Du, 0X3B4Fu, -215);
|
||||
+ test_printf_one("%*.u %.*i %.*i", -4, 9u, -4, 8, -4, -6);
|
||||
+
|
||||
+ test_printf_one("%.0u %.0i %.0x %.0X", 0u, 0, 0u, 0u);
|
||||
+ test_printf_one("%.*u %.*i %.*x %.*X", 0, 0u, 0, 0, 0, 0u, 0, 0u);
|
||||
+ test_printf_one("%*u %*i %*x %*X", -1, 0u, -1, 0, -1, 0u, -1, 0u);
|
||||
+
|
||||
+ test_printf_one("%*s%*s%*s", 256, "", 256, "", 4096, ""); /* Test buf growing. */
|
||||
+ test_printf_one("%0*i%0*i%0*i", 256, 0, 256, 0, 4096, 0); /* Test buf growing. */
|
||||
+ test_printf_one("%0*i", INT16_MAX, 0); /* Poor programmer's memzero. */
|
||||
+
|
||||
+ /* Non printf-compatible behavior tests below. */
|
||||
+ char16_t *s;
|
||||
+
|
||||
+ assert_se(s = xasprintf_status(0, "\n \r \r\n"));
|
||||
+ assert_se(streq16(s, u"\r\n \r \r\r\n"));
|
||||
+ s = mfree(s);
|
||||
+
|
||||
+ assert_se(s = xasprintf_status(EFI_SUCCESS, "%m"));
|
||||
+ assert_se(streq16(s, u"Success"));
|
||||
+ s = mfree(s);
|
||||
+
|
||||
+ assert_se(s = xasprintf_status(EFI_SUCCESS, "%15m"));
|
||||
+ assert_se(streq16(s, u" Success"));
|
||||
+ s = mfree(s);
|
||||
+
|
||||
+ assert_se(s = xasprintf_status(EFI_LOAD_ERROR, "%m"));
|
||||
+ assert_se(streq16(s, u"Load error"));
|
||||
+ s = mfree(s);
|
||||
+
|
||||
+ assert_se(s = xasprintf_status(0x42, "%m"));
|
||||
+ assert_se(streq16(s, u"0x42"));
|
||||
+ s = mfree(s);
|
||||
+}
|
||||
+
|
||||
TEST(efi_memcmp) {
|
||||
assert_se(efi_memcmp(NULL, NULL, 0) == 0);
|
||||
assert_se(efi_memcmp(NULL, NULL, 1) == 0);
|
965
0682-boot-Use-printf-for-error-logging.patch
Normal file
965
0682-boot-Use-printf-for-error-logging.patch
Normal file
@ -0,0 +1,965 @@
|
||||
From e5dea043b9c20f648bffffd581a0e624f5622a16 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Fri, 10 Jun 2022 19:06:57 +0200
|
||||
Subject: [PATCH] boot: Use printf for error logging
|
||||
|
||||
This also drops the _stall suffix in anticipation of the next commit.
|
||||
|
||||
(cherry picked from commit c2c6203556f842820ca09e0653c123305f2ba6d2)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/assert.c | 12 ---------
|
||||
src/boot/efi/boot.c | 54 +++++++++++++++++++-------------------
|
||||
src/boot/efi/console.c | 6 ++---
|
||||
src/boot/efi/cpio.c | 23 ++++++++--------
|
||||
src/boot/efi/devicetree.c | 3 +--
|
||||
src/boot/efi/drivers.c | 16 +++++------
|
||||
src/boot/efi/linux.c | 10 +++----
|
||||
src/boot/efi/linux_x86.c | 15 +++++------
|
||||
src/boot/efi/log.c | 34 ++++++++++++++++++++++++
|
||||
src/boot/efi/log.h | 9 +++++++
|
||||
src/boot/efi/measure.c | 2 +-
|
||||
src/boot/efi/meson.build | 3 ++-
|
||||
src/boot/efi/pe.c | 2 +-
|
||||
src/boot/efi/random-seed.c | 44 +++++++++++++++----------------
|
||||
src/boot/efi/secure-boot.c | 11 ++++----
|
||||
src/boot/efi/stub.c | 6 ++---
|
||||
src/boot/efi/util.c | 30 +--------------------
|
||||
src/boot/efi/util.h | 12 +--------
|
||||
18 files changed, 141 insertions(+), 151 deletions(-)
|
||||
delete mode 100644 src/boot/efi/assert.c
|
||||
create mode 100644 src/boot/efi/log.c
|
||||
create mode 100644 src/boot/efi/log.h
|
||||
|
||||
diff --git a/src/boot/efi/assert.c b/src/boot/efi/assert.c
|
||||
deleted file mode 100644
|
||||
index bb16d2bf93..0000000000
|
||||
--- a/src/boot/efi/assert.c
|
||||
+++ /dev/null
|
||||
@@ -1,12 +0,0 @@
|
||||
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
-
|
||||
-#include <efi.h>
|
||||
-#include <efilib.h>
|
||||
-
|
||||
-#include "util.h"
|
||||
-
|
||||
-void efi_assert(const char *expr, const char *file, unsigned line, const char *function) {
|
||||
- log_error_stall(L"systemd-boot assertion '%a' failed at %a:%u, function %a(). Halting.", expr, file, line, function);
|
||||
- for (;;)
|
||||
- BS->Stall(60 * 1000 * 1000);
|
||||
-}
|
||||
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
|
||||
index a39c356158..1e7b7a0fa7 100644
|
||||
--- a/src/boot/efi/boot.c
|
||||
+++ b/src/boot/efi/boot.c
|
||||
@@ -587,14 +587,14 @@ static EFI_STATUS reboot_into_firmware(void) {
|
||||
EFI_STATUS err;
|
||||
|
||||
if (!FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
|
||||
- return log_error_status_stall(EFI_UNSUPPORTED, L"Reboot to firmware interface not supported.");
|
||||
+ return log_error_status(EFI_UNSUPPORTED, "Reboot to firmware interface not supported.");
|
||||
|
||||
(void) efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", &osind);
|
||||
osind |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
|
||||
|
||||
err = efivar_set_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", osind, EFI_VARIABLE_NON_VOLATILE);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error setting OsIndications: %r", err);
|
||||
+ return log_error_status(err, "Error setting OsIndications: %m");
|
||||
|
||||
RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
|
||||
assert_not_reached();
|
||||
@@ -634,7 +634,7 @@ static bool menu_run(
|
||||
config->console_mode_efivar : config->console_mode);
|
||||
if (err != EFI_SUCCESS) {
|
||||
clear_screen(COLOR_NORMAL);
|
||||
- log_error_stall(L"Error switching console mode: %r", err);
|
||||
+ log_error_status(err, "Error switching console mode: %m");
|
||||
}
|
||||
|
||||
size_t line_width = 0, entry_padding = 3;
|
||||
@@ -1177,7 +1177,7 @@ static void config_defaults_load_from_file(Config *config, char *content) {
|
||||
else {
|
||||
uint64_t u;
|
||||
if (!parse_number8(value, &u, NULL) || u > TIMEOUT_TYPE_MAX) {
|
||||
- log_error_stall(L"Error parsing 'timeout' config option: %a", value);
|
||||
+ log_error("Error parsing 'timeout' config option: %s", value);
|
||||
continue;
|
||||
}
|
||||
config->timeout_sec_config = u;
|
||||
@@ -1188,7 +1188,7 @@ static void config_defaults_load_from_file(Config *config, char *content) {
|
||||
|
||||
if (streq8(key, "default")) {
|
||||
if (value[0] == '@' && !strcaseeq8(value, "@saved")) {
|
||||
- log_error_stall(L"Unsupported special entry identifier: %a", value);
|
||||
+ log_error("Unsupported special entry identifier: %s", value);
|
||||
continue;
|
||||
}
|
||||
free(config->entry_default_config);
|
||||
@@ -1199,35 +1199,35 @@ static void config_defaults_load_from_file(Config *config, char *content) {
|
||||
if (streq8(key, "editor")) {
|
||||
err = parse_boolean(value, &config->editor);
|
||||
if (err != EFI_SUCCESS)
|
||||
- log_error_stall(L"Error parsing 'editor' config option: %a", value);
|
||||
+ log_error("Error parsing 'editor' config option: %s", value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (streq8(key, "auto-entries")) {
|
||||
err = parse_boolean(value, &config->auto_entries);
|
||||
if (err != EFI_SUCCESS)
|
||||
- log_error_stall(L"Error parsing 'auto-entries' config option: %a", value);
|
||||
+ log_error("Error parsing 'auto-entries' config option: %s", value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (streq8(key, "auto-firmware")) {
|
||||
err = parse_boolean(value, &config->auto_firmware);
|
||||
if (err != EFI_SUCCESS)
|
||||
- log_error_stall(L"Error parsing 'auto-firmware' config option: %a", value);
|
||||
+ log_error("Error parsing 'auto-firmware' config option: %s", value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (streq8(key, "beep")) {
|
||||
err = parse_boolean(value, &config->beep);
|
||||
if (err != EFI_SUCCESS)
|
||||
- log_error_stall(L"Error parsing 'beep' config option: %a", value);
|
||||
+ log_error("Error parsing 'beep' config option: %s", value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (streq8(key, "reboot-for-bitlocker")) {
|
||||
err = parse_boolean(value, &config->reboot_for_bitlocker);
|
||||
if (err != EFI_SUCCESS)
|
||||
- log_error_stall(L"Error parsing 'reboot-for-bitlocker' config option: %a", value);
|
||||
+ log_error("Error parsing 'reboot-for-bitlocker' config option: %s", value);
|
||||
}
|
||||
|
||||
if (streq8(key, "secure-boot-enroll")) {
|
||||
@@ -1238,7 +1238,7 @@ static void config_defaults_load_from_file(Config *config, char *content) {
|
||||
else if (streq8(value, "off"))
|
||||
config->secure_boot_enroll = ENROLL_OFF;
|
||||
else
|
||||
- log_error_stall(L"Error parsing 'secure-boot-enroll' config option: %a", value);
|
||||
+ log_error("Error parsing 'secure-boot-enroll' config option: %s", value);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1252,7 +1252,7 @@ static void config_defaults_load_from_file(Config *config, char *content) {
|
||||
else {
|
||||
uint64_t u;
|
||||
if (!parse_number8(value, &u, NULL) || u > CONSOLE_MODE_RANGE_MAX) {
|
||||
- log_error_stall(L"Error parsing 'console-mode' config option: %a", value);
|
||||
+ log_error("Error parsing 'console-mode' config option: %s", value);
|
||||
continue;
|
||||
}
|
||||
config->console_mode = u;
|
||||
@@ -1356,7 +1356,7 @@ static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) {
|
||||
strcpy16(file_info->FileName, entry->next_name);
|
||||
err = handle->SetInfo(handle, &GenericFileInfo, file_info_size, file_info);
|
||||
if (err != EFI_SUCCESS) {
|
||||
- log_error_stall(L"Failed to rename '%s' to '%s', ignoring: %r", old_path, entry->next_name, err);
|
||||
+ log_error_status(err, "Failed to rename '%ls' to '%ls', ignoring: %m", old_path, entry->next_name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1564,7 +1564,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
if (err == EFI_SUCCESS)
|
||||
config->timeout_sec = config->timeout_sec_efivar;
|
||||
else if (err != EFI_NOT_FOUND)
|
||||
- log_error_stall(u"Error reading LoaderConfigTimeout EFI variable: %r", err);
|
||||
+ log_error_status(err, "Error reading LoaderConfigTimeout EFI variable: %m");
|
||||
|
||||
err = efivar_get_timeout(u"LoaderConfigTimeoutOneShot", &config->timeout_sec);
|
||||
if (err == EFI_SUCCESS) {
|
||||
@@ -1573,7 +1573,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
|
||||
config->force_menu = true; /* force the menu when this is set */
|
||||
} else if (err != EFI_NOT_FOUND)
|
||||
- log_error_stall(u"Error reading LoaderConfigTimeoutOneShot EFI variable: %r", err);
|
||||
+ log_error_status(err, "Error reading LoaderConfigTimeoutOneShot EFI variable: %m");
|
||||
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigConsoleMode", &value);
|
||||
if (err == EFI_SUCCESS)
|
||||
@@ -2327,38 +2327,38 @@ static EFI_STATUS image_start(
|
||||
_cleanup_(file_closep) EFI_FILE *image_root = NULL;
|
||||
err = open_volume(entry->device, &image_root);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error opening root path: %r", err);
|
||||
+ return log_error_status(err, "Error opening root path: %m");
|
||||
|
||||
err = make_file_device_path(entry->device, entry->loader, &path);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error making file device path: %r", err);
|
||||
+ return log_error_status(err, "Error making file device path: %m");
|
||||
|
||||
size_t initrd_size = 0;
|
||||
_cleanup_free_ void *initrd = NULL;
|
||||
_cleanup_free_ char16_t *options_initrd = NULL;
|
||||
err = initrd_prepare(image_root, entry, &options_initrd, &initrd, &initrd_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error preparing initrd: %r", err);
|
||||
+ return log_error_status(err, "Error preparing initrd: %m");
|
||||
|
||||
err = shim_load_image(parent_image, path, &image);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error loading %s: %r", entry->loader, err);
|
||||
+ return log_error_status(err, "Error loading %ls: %m", entry->loader);
|
||||
|
||||
if (entry->devicetree) {
|
||||
err = devicetree_install(&dtstate, image_root, entry->devicetree);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error loading %s: %r", entry->devicetree, err);
|
||||
+ return log_error_status(err, "Error loading %ls: %m", entry->devicetree);
|
||||
}
|
||||
|
||||
_cleanup_(cleanup_initrd) EFI_HANDLE initrd_handle = NULL;
|
||||
err = initrd_register(initrd, initrd_size, &initrd_handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error registering initrd: %r", err);
|
||||
+ return log_error_status(err, "Error registering initrd: %m");
|
||||
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
|
||||
err = BS->HandleProtocol(image, &LoadedImageProtocol, (void **) &loaded_image);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error getting LoadedImageProtocol handle: %r", err);
|
||||
+ return log_error_status(err, "Error getting LoadedImageProtocol handle: %m");
|
||||
|
||||
char16_t *options = options_initrd ?: entry->options;
|
||||
if (options) {
|
||||
@@ -2382,7 +2382,7 @@ static EFI_STATUS image_start(
|
||||
err = pe_kernel_info(loaded_image->ImageBase, &compat_address);
|
||||
if (err != EFI_SUCCESS) {
|
||||
if (err != EFI_UNSUPPORTED)
|
||||
- return log_error_status_stall(err, L"Error finding kernel compat entry address: %r", err);
|
||||
+ return log_error_status(err, "Error finding kernel compat entry address: %m");
|
||||
} else if (compat_address > 0) {
|
||||
EFI_IMAGE_ENTRY_POINT kernel_entry =
|
||||
(EFI_IMAGE_ENTRY_POINT) ((uint8_t *) loaded_image->ImageBase + compat_address);
|
||||
@@ -2395,7 +2395,7 @@ static EFI_STATUS image_start(
|
||||
err = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
- return log_error_status_stall(err, L"Failed to execute %s (%s): %r", entry->title_show, entry->loader, err);
|
||||
+ return log_error_status(err, "Failed to execute %ls (%ls): %m", entry->title_show, entry->loader);
|
||||
}
|
||||
|
||||
static void config_free(Config *config) {
|
||||
@@ -2634,7 +2634,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
|
||||
+ return log_error_status(err, "Error getting a LoadedImageProtocol handle: %m");
|
||||
|
||||
(void) device_path_to_str(loaded_image->FilePath, &loaded_image_path);
|
||||
|
||||
@@ -2642,14 +2642,14 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
|
||||
err = discover_root_dir(loaded_image, &root_dir);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Unable to open root directory: %r", err);
|
||||
+ return log_error_status(err, "Unable to open root directory: %m");
|
||||
|
||||
(void) load_drivers(image, loaded_image, root_dir);
|
||||
|
||||
config_load_all_entries(&config, loaded_image, loaded_image_path, root_dir);
|
||||
|
||||
if (config.entry_count == 0) {
|
||||
- log_error_stall(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed.");
|
||||
+ log_error("No loader found. Configuration files in \\loader\\entries\\*.conf are needed.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c
|
||||
index c3d9ff0e82..b876ff2bd7 100644
|
||||
--- a/src/boot/efi/console.c
|
||||
+++ b/src/boot/efi/console.c
|
||||
@@ -83,7 +83,7 @@ EFI_STATUS console_key_read(uint64_t *key, uint64_t timeout_usec) {
|
||||
|
||||
err = BS->CreateEvent(EVT_TIMER, 0, NULL, NULL, &timer);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error creating timer event: %r", err);
|
||||
+ return log_error_status(err, "Error creating timer event: %m");
|
||||
|
||||
EFI_EVENT events[] = {
|
||||
timer,
|
||||
@@ -104,14 +104,14 @@ EFI_STATUS console_key_read(uint64_t *key, uint64_t timeout_usec) {
|
||||
TimerRelative,
|
||||
MIN(timeout_usec, watchdog_ping_usec) * 10);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error arming timer event: %r", err);
|
||||
+ return log_error_status(err, "Error arming timer event: %m");
|
||||
|
||||
(void) BS->SetWatchdogTimer(watchdog_timeout_sec, 0x10000, 0, NULL);
|
||||
err = BS->WaitForEvent(n_events, events, &index);
|
||||
(void) BS->SetWatchdogTimer(watchdog_timeout_sec, 0x10000, 0, NULL);
|
||||
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error waiting for events: %r", err);
|
||||
+ return log_error_status(err, "Error waiting for events: %m");
|
||||
|
||||
/* We have keyboard input, process it after this loop. */
|
||||
if (timer != events[index])
|
||||
diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c
|
||||
index bb424a44d5..62773ded9a 100644
|
||||
--- a/src/boot/efi/cpio.c
|
||||
+++ b/src/boot/efi/cpio.c
|
||||
@@ -326,7 +326,7 @@ static EFI_STATUS measure_cpio(
|
||||
tpm_description,
|
||||
&m);
|
||||
if (err != EFI_SUCCESS) {
|
||||
- log_error_stall(L"Unable to add initrd TPM measurement for PCR %u (%s), ignoring: %r", tpm_pcr[i], tpm_description, err);
|
||||
+ log_error_status(err, "Unable to add initrd TPM measurement for PCR %u (%ls), ignoring: %m", tpm_pcr[i], tpm_description);
|
||||
measured = false;
|
||||
continue;
|
||||
}
|
||||
@@ -401,8 +401,7 @@ EFI_STATUS pack_cpio(
|
||||
* its file handles. */
|
||||
goto nothing;
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(
|
||||
- err, L"Unable to open root directory: %r", err);
|
||||
+ return log_error_status(err, "Unable to open root directory: %m");
|
||||
|
||||
if (!dropin_dir)
|
||||
dropin_dir = rel_dropin_dir = get_dropin_dir(loaded_image->FilePath);
|
||||
@@ -412,14 +411,14 @@ EFI_STATUS pack_cpio(
|
||||
/* No extra subdir, that's totally OK */
|
||||
goto nothing;
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to open extra directory of loaded image: %r", err);
|
||||
+ return log_error_status(err, "Failed to open extra directory of loaded image: %m");
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char16_t *d = NULL;
|
||||
|
||||
err = readdir_harder(extra_dir, &dirent, &dirent_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to read extra directory of loaded image: %r", err);
|
||||
+ return log_error_status(err, "Failed to read extra directory of loaded image: %m");
|
||||
if (!dirent) /* End of directory */
|
||||
break;
|
||||
|
||||
@@ -462,7 +461,7 @@ EFI_STATUS pack_cpio(
|
||||
* archive. Otherwise the cpio archive cannot be unpacked, since the leading dirs won't exist. */
|
||||
err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to pack cpio prefix: %r", err);
|
||||
+ return log_error_status(err, "Failed to pack cpio prefix: %m");
|
||||
|
||||
for (size_t i = 0; i < n_items; i++) {
|
||||
_cleanup_free_ char *content = NULL;
|
||||
@@ -470,7 +469,7 @@ EFI_STATUS pack_cpio(
|
||||
|
||||
err = file_read(extra_dir, items[i], 0, 0, &content, &contentsize);
|
||||
if (err != EFI_SUCCESS) {
|
||||
- log_error_status_stall(err, L"Failed to read %s, ignoring: %r", items[i], err);
|
||||
+ log_error_status(err, "Failed to read %ls, ignoring: %m", items[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -482,12 +481,12 @@ EFI_STATUS pack_cpio(
|
||||
&inode,
|
||||
&buffer, &buffer_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to pack cpio file %s: %r", dirent->FileName, err);
|
||||
+ return log_error_status(err, "Failed to pack cpio file %ls: %m", dirent->FileName);
|
||||
}
|
||||
|
||||
err = pack_cpio_trailer(&buffer, &buffer_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to pack cpio trailer: %r");
|
||||
+ return log_error_status(err, "Failed to pack cpio trailer: %m");
|
||||
|
||||
err = measure_cpio(buffer, buffer_size, tpm_pcr, n_tpm_pcr, tpm_description, ret_measured);
|
||||
if (err != EFI_SUCCESS)
|
||||
@@ -539,7 +538,7 @@ EFI_STATUS pack_cpio_literal(
|
||||
|
||||
err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to pack cpio prefix: %r", err);
|
||||
+ return log_error_status(err, "Failed to pack cpio prefix: %m");
|
||||
|
||||
err = pack_cpio_one(
|
||||
target_filename,
|
||||
@@ -549,11 +548,11 @@ EFI_STATUS pack_cpio_literal(
|
||||
&inode,
|
||||
&buffer, &buffer_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to pack cpio file %s: %r", target_filename, err);
|
||||
+ return log_error_status(err, "Failed to pack cpio file %ls: %m", target_filename);
|
||||
|
||||
err = pack_cpio_trailer(&buffer, &buffer_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to pack cpio trailer: %r");
|
||||
+ return log_error_status(err, "Failed to pack cpio trailer: %m");
|
||||
|
||||
err = measure_cpio(buffer, buffer_size, tpm_pcr, n_tpm_pcr, tpm_description, ret_measured);
|
||||
if (err != EFI_SUCCESS)
|
||||
diff --git a/src/boot/efi/devicetree.c b/src/boot/efi/devicetree.c
|
||||
index f3c2e47e58..52f64a6e2f 100644
|
||||
--- a/src/boot/efi/devicetree.c
|
||||
+++ b/src/boot/efi/devicetree.c
|
||||
@@ -36,8 +36,7 @@ static EFI_STATUS devicetree_fixup(struct devicetree_state *state, size_t len) {
|
||||
|
||||
err = BS->LocateProtocol(&EfiDtFixupProtocol, NULL, (void **) &fixup);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(EFI_SUCCESS,
|
||||
- L"Could not locate device tree fixup protocol, skipping.");
|
||||
+ return log_error_status(EFI_SUCCESS, "Could not locate device tree fixup protocol, skipping.");
|
||||
|
||||
size = devicetree_allocated(state);
|
||||
err = fixup->Fixup(fixup, PHYSICAL_ADDRESS_TO_POINTER(state->addr), &size,
|
||||
diff --git a/src/boot/efi/drivers.c b/src/boot/efi/drivers.c
|
||||
index 41a7d8fe15..c76f8e0903 100644
|
||||
--- a/src/boot/efi/drivers.c
|
||||
+++ b/src/boot/efi/drivers.c
|
||||
@@ -23,26 +23,26 @@ static EFI_STATUS load_one_driver(
|
||||
spath = xpool_print(L"\\EFI\\systemd\\drivers\\%s", fname);
|
||||
err = make_file_device_path(loaded_image->DeviceHandle, spath, &path);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error making file device path: %r", err);
|
||||
+ return log_error_status(err, "Error making file device path: %m");
|
||||
|
||||
err = BS->LoadImage(false, parent_image, path, NULL, 0, &image);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to load image %s: %r", fname, err);
|
||||
+ return log_error_status(err, "Failed to load image %ls: %m", fname);
|
||||
|
||||
err = BS->HandleProtocol(image, &LoadedImageProtocol, (void **)&loaded_image);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to find protocol in driver image %s: %r", fname, err);
|
||||
+ return log_error_status(err, "Failed to find protocol in driver image %ls: %m", fname);
|
||||
|
||||
if (loaded_image->ImageCodeType != EfiBootServicesCode &&
|
||||
loaded_image->ImageCodeType != EfiRuntimeServicesCode)
|
||||
- return log_error_status_stall(EFI_INVALID_PARAMETER, L"Image %s is not a driver, refusing.", fname);
|
||||
+ return log_error("Image %ls is not a driver, refusing.", fname);
|
||||
|
||||
err = BS->StartImage(image, NULL, NULL);
|
||||
if (err != EFI_SUCCESS) {
|
||||
/* EFI_ABORTED signals an initializing driver. It uses this error code on success
|
||||
* so that it is unloaded after. */
|
||||
if (err != EFI_ABORTED)
|
||||
- log_error_stall(L"Failed to start image %s: %r", fname, err);
|
||||
+ log_error_status(err, "Failed to start image %ls: %m", fname);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ EFI_STATUS reconnect_all_drivers(void) {
|
||||
|
||||
err = BS->LocateHandleBuffer(AllHandles, NULL, NULL, &n_handles, &handles);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to get list of handles: %r", err);
|
||||
+ return log_error_status(err, "Failed to get list of handles: %m");
|
||||
|
||||
for (size_t i = 0; i < n_handles; i++)
|
||||
/* Some firmware gives us some bogus handles (or they might become bad due to
|
||||
@@ -87,12 +87,12 @@ EFI_STATUS load_drivers(
|
||||
if (err == EFI_NOT_FOUND)
|
||||
return EFI_SUCCESS;
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to open \\EFI\\systemd\\drivers: %r", err);
|
||||
+ return log_error_status(err, "Failed to open \\EFI\\systemd\\drivers: %m");
|
||||
|
||||
for (;;) {
|
||||
err = readdir_harder(drivers_dir, &dirent, &dirent_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to read extra directory of loaded image: %r", err);
|
||||
+ return log_error_status(err, "Failed to read extra directory of loaded image: %m");
|
||||
if (!dirent) /* End of directory */
|
||||
break;
|
||||
|
||||
diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c
|
||||
index 48801f9dd8..2ae68ec295 100644
|
||||
--- a/src/boot/efi/linux.c
|
||||
+++ b/src/boot/efi/linux.c
|
||||
@@ -120,17 +120,17 @@ EFI_STATUS linux_exec(
|
||||
initrd_length);
|
||||
#endif
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, u"Bad kernel image: %r", err);
|
||||
+ return log_error_status(err, "Bad kernel image: %m");
|
||||
|
||||
_cleanup_(unload_imagep) EFI_HANDLE kernel_image = NULL;
|
||||
err = load_image(parent, linux_buffer, linux_length, &kernel_image);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, u"Error loading kernel image: %r", err);
|
||||
+ return log_error_status(err, "Error loading kernel image: %m");
|
||||
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
|
||||
err = BS->HandleProtocol(kernel_image, &LoadedImageProtocol, (void **) &loaded_image);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, u"Error getting kernel loaded image protocol: %r", err);
|
||||
+ return log_error_status(err, "Error getting kernel loaded image protocol: %m");
|
||||
|
||||
if (cmdline) {
|
||||
loaded_image->LoadOptions = (void *) cmdline;
|
||||
@@ -140,7 +140,7 @@ EFI_STATUS linux_exec(
|
||||
_cleanup_(cleanup_initrd) EFI_HANDLE initrd_handle = NULL;
|
||||
err = initrd_register(initrd_buffer, initrd_length, &initrd_handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, u"Error registering initrd: %r", err);
|
||||
+ return log_error_status(err, "Error registering initrd: %m");
|
||||
|
||||
err = BS->StartImage(kernel_image, NULL, NULL);
|
||||
|
||||
@@ -151,5 +151,5 @@ EFI_STATUS linux_exec(
|
||||
err = compat_entry(kernel_image, ST);
|
||||
}
|
||||
|
||||
- return log_error_status_stall(err, u"Error starting kernel image: %r", err);
|
||||
+ return log_error_status(err, "Error starting kernel image: %m");
|
||||
}
|
||||
diff --git a/src/boot/efi/linux_x86.c b/src/boot/efi/linux_x86.c
|
||||
index 6a5e431107..cbd92201b6 100644
|
||||
--- a/src/boot/efi/linux_x86.c
|
||||
+++ b/src/boot/efi/linux_x86.c
|
||||
@@ -141,28 +141,27 @@ EFI_STATUS linux_exec_efi_handover(
|
||||
|
||||
const BootParams *image_params = (const BootParams *) linux_buffer;
|
||||
if (image_params->hdr.header != SETUP_MAGIC || image_params->hdr.boot_flag != BOOT_FLAG_MAGIC)
|
||||
- return log_error_status_stall(EFI_UNSUPPORTED, u"Unsupported kernel image.");
|
||||
+ return log_error_status(EFI_UNSUPPORTED, "Unsupported kernel image.");
|
||||
if (image_params->hdr.version < SETUP_VERSION_2_11)
|
||||
- return log_error_status_stall(EFI_UNSUPPORTED, u"Kernel too old.");
|
||||
+ return log_error_status(EFI_UNSUPPORTED, "Kernel too old.");
|
||||
if (!image_params->hdr.relocatable_kernel)
|
||||
- return log_error_status_stall(EFI_UNSUPPORTED, u"Kernel is not relocatable.");
|
||||
+ return log_error_status(EFI_UNSUPPORTED, "Kernel is not relocatable.");
|
||||
|
||||
/* The xloadflags were added in version 2.12+ of the boot protocol but the handover support predates
|
||||
* that, so we cannot safety-check this for 2.11. */
|
||||
if (image_params->hdr.version >= SETUP_VERSION_2_12 &&
|
||||
!FLAGS_SET(image_params->hdr.xloadflags, XLF_EFI_HANDOVER))
|
||||
- return log_error_status_stall(EFI_UNSUPPORTED, u"Kernel does not support EFI handover protocol.");
|
||||
+ return log_error_status(EFI_UNSUPPORTED, "Kernel does not support EFI handover protocol.");
|
||||
|
||||
bool can_4g = image_params->hdr.version >= SETUP_VERSION_2_12 &&
|
||||
FLAGS_SET(image_params->hdr.xloadflags, XLF_CAN_BE_LOADED_ABOVE_4G);
|
||||
|
||||
if (!can_4g && POINTER_TO_PHYSICAL_ADDRESS(linux_buffer) + linux_length > UINT32_MAX)
|
||||
- return log_error_status_stall(
|
||||
+ return log_error_status(
|
||||
EFI_UNSUPPORTED,
|
||||
- u"Unified kernel image was loaded above 4G, but kernel lacks support.");
|
||||
+ "Unified kernel image was loaded above 4G, but kernel lacks support.");
|
||||
if (!can_4g && POINTER_TO_PHYSICAL_ADDRESS(initrd_buffer) + initrd_length > UINT32_MAX)
|
||||
- return log_error_status_stall(
|
||||
- EFI_UNSUPPORTED, u"Initrd is above 4G, but kernel lacks support.");
|
||||
+ return log_error_status(EFI_UNSUPPORTED, "Initrd is above 4G, but kernel lacks support.");
|
||||
|
||||
_cleanup_pages_ Pages boot_params_page = xmalloc_pages(
|
||||
can_4g ? AllocateAnyPages : AllocateMaxAddress,
|
||||
diff --git a/src/boot/efi/log.c b/src/boot/efi/log.c
|
||||
new file mode 100644
|
||||
index 0000000000..38e7c5a8a8
|
||||
--- /dev/null
|
||||
+++ b/src/boot/efi/log.c
|
||||
@@ -0,0 +1,34 @@
|
||||
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
+
|
||||
+#include <efi.h>
|
||||
+#include <efilib.h>
|
||||
+
|
||||
+#include "log.h"
|
||||
+
|
||||
+void efi_assert(const char *expr, const char *file, unsigned line, const char *function) {
|
||||
+ log_error("systemd-boot assertion '%s' failed at %s:%u@%s. Halting.", expr, file, line, function);
|
||||
+ for (;;)
|
||||
+ BS->Stall(60 * 1000 * 1000);
|
||||
+}
|
||||
+
|
||||
+EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...) {
|
||||
+ assert(format);
|
||||
+
|
||||
+ int32_t attr = ST->ConOut->Mode->Attribute;
|
||||
+
|
||||
+ if (ST->ConOut->Mode->CursorColumn > 0)
|
||||
+ ST->ConOut->OutputString(ST->ConOut, (char16_t *) u"\r\n");
|
||||
+ ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
|
||||
+
|
||||
+ va_list ap;
|
||||
+ va_start(ap, format);
|
||||
+ vprintf_status(status, format, ap);
|
||||
+ va_end(ap);
|
||||
+
|
||||
+ ST->ConOut->OutputString(ST->ConOut, (char16_t *) u"\r\n");
|
||||
+ ST->ConOut->SetAttribute(ST->ConOut, attr);
|
||||
+
|
||||
+ /* Give the user a chance to see the message. */
|
||||
+ BS->Stall(3 * 1000 * 1000);
|
||||
+ return status;
|
||||
+}
|
||||
diff --git a/src/boot/efi/log.h b/src/boot/efi/log.h
|
||||
new file mode 100644
|
||||
index 0000000000..c6e8d626ce
|
||||
--- /dev/null
|
||||
+++ b/src/boot/efi/log.h
|
||||
@@ -0,0 +1,9 @@
|
||||
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
+#pragma once
|
||||
+
|
||||
+#include "efi-string.h"
|
||||
+
|
||||
+_gnu_printf_(2, 3) EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...);
|
||||
+#define log_error_status(status, ...) log_internal(status, __VA_ARGS__)
|
||||
+#define log_error(...) log_internal(EFI_INVALID_PARAMETER, __VA_ARGS__)
|
||||
+#define log_oom() log_internal(EFI_OUT_OF_RESOURCES, "Out of memory.")
|
||||
diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c
|
||||
index 27a0f06475..52c5cd7ae8 100644
|
||||
--- a/src/boot/efi/measure.c
|
||||
+++ b/src/boot/efi/measure.c
|
||||
@@ -207,7 +207,7 @@ EFI_STATUS tpm_log_load_options(const char16_t *load_options, bool *ret_measured
|
||||
|
||||
err = tpm_log_event(pcr, POINTER_TO_PHYSICAL_ADDRESS(load_options), strsize16(load_options), load_options, &m);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Unable to add load options (i.e. kernel command) line measurement to PCR %u: %r", pcr, err);
|
||||
+ return log_error_status(err, "Unable to add load options (i.e. kernel command) line measurement to PCR %u: %m", pcr);
|
||||
|
||||
measured = measured < 0 ? m : (measured && m);
|
||||
}
|
||||
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
|
||||
index ed332262e8..09c40a280b 100644
|
||||
--- a/src/boot/efi/meson.build
|
||||
+++ b/src/boot/efi/meson.build
|
||||
@@ -359,6 +359,7 @@ efi_headers = files(
|
||||
'graphics.h',
|
||||
'initrd.h',
|
||||
'linux.h',
|
||||
+ 'log.h',
|
||||
'measure.h',
|
||||
'missing_efi.h',
|
||||
'part-discovery.h',
|
||||
@@ -372,7 +373,6 @@ efi_headers = files(
|
||||
)
|
||||
|
||||
common_sources = files(
|
||||
- 'assert.c',
|
||||
'console.c',
|
||||
'devicetree.c',
|
||||
'drivers.c',
|
||||
@@ -380,6 +380,7 @@ common_sources = files(
|
||||
'efi-string.c',
|
||||
'graphics.c',
|
||||
'initrd.c',
|
||||
+ 'log.c',
|
||||
'measure.c',
|
||||
'part-discovery.c',
|
||||
'pe.c',
|
||||
diff --git a/src/boot/efi/pe.c b/src/boot/efi/pe.c
|
||||
index 65308639f6..c946ce2b0a 100644
|
||||
--- a/src/boot/efi/pe.c
|
||||
+++ b/src/boot/efi/pe.c
|
||||
@@ -158,7 +158,7 @@ static void locate_sections(
|
||||
|
||||
if (in_memory) {
|
||||
if (prev_section_addr > sect->VirtualAddress)
|
||||
- log_error_stall(u"Overlapping PE sections detected. Boot may fail due to image memory corruption!");
|
||||
+ log_error("Overlapping PE sections detected. Boot may fail due to image memory corruption!");
|
||||
prev_section_addr = sect->VirtualAddress + sect->VirtualSize;
|
||||
}
|
||||
|
||||
diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c
|
||||
index a52934a901..e971f48097 100644
|
||||
--- a/src/boot/efi/random-seed.c
|
||||
+++ b/src/boot/efi/random-seed.c
|
||||
@@ -48,7 +48,7 @@ static EFI_STATUS acquire_rng(void *ret, size_t size) {
|
||||
|
||||
err = rng->GetRNG(rng, NULL, size, ret);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to acquire RNG data: %r", err);
|
||||
+ return log_error_status(err, "Failed to acquire RNG data: %m");
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -63,12 +63,12 @@ static EFI_STATUS acquire_system_token(void **ret, size_t *ret_size) {
|
||||
err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size);
|
||||
if (err != EFI_SUCCESS) {
|
||||
if (err != EFI_NOT_FOUND)
|
||||
- log_error_stall(L"Failed to read LoaderSystemToken EFI variable: %r", err);
|
||||
+ log_error_status(err, "Failed to read LoaderSystemToken EFI variable: %m");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (size <= 0)
|
||||
- return log_error_status_stall(EFI_NOT_FOUND, L"System token too short, ignoring.");
|
||||
+ return log_error_status(EFI_NOT_FOUND, "System token too short, ignoring.");
|
||||
|
||||
*ret = TAKE_PTR(data);
|
||||
*ret_size = size;
|
||||
@@ -201,29 +201,29 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
0);
|
||||
if (err != EFI_SUCCESS) {
|
||||
if (err != EFI_NOT_FOUND && err != EFI_WRITE_PROTECTED)
|
||||
- log_error_stall(L"Failed to open random seed file: %r", err);
|
||||
+ log_error_status(err, "Failed to open random seed file: %m");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = get_file_info_harder(handle, &info, NULL);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to get file info for random seed: %r", err);
|
||||
+ return log_error_status(err, "Failed to get file info for random seed: %m");
|
||||
|
||||
size = info->FileSize;
|
||||
if (size < RANDOM_MAX_SIZE_MIN)
|
||||
- return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too short.");
|
||||
+ return log_error("Random seed file is too short.");
|
||||
|
||||
if (size > RANDOM_MAX_SIZE_MAX)
|
||||
- return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too large.");
|
||||
+ return log_error("Random seed file is too large.");
|
||||
|
||||
seed = xmalloc(size);
|
||||
rsize = size;
|
||||
err = handle->Read(handle, &rsize, seed);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to read random seed file: %r", err);
|
||||
+ return log_error_status(err, "Failed to read random seed file: %m");
|
||||
if (rsize != size) {
|
||||
explicit_bzero_safe(seed, rsize);
|
||||
- return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short read on random seed file.");
|
||||
+ return log_error_status(EFI_PROTOCOL_ERROR, "Short read on random seed file.");
|
||||
}
|
||||
|
||||
sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
@@ -232,14 +232,14 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
|
||||
err = handle->SetPosition(handle, 0);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err);
|
||||
+ return log_error_status(err, "Failed to seek to beginning of random seed file: %m");
|
||||
|
||||
/* Let's also include the UEFI monotonic counter (which is supposedly increasing on every single
|
||||
* boot) in the hash, so that even if the changes to the ESP for some reason should not be
|
||||
* persistent, the random seed we generate will still be different on every single boot. */
|
||||
err = BS->GetNextMonotonicCount(&uefi_monotonic_counter);
|
||||
if (err != EFI_SUCCESS && !seeded_by_efi)
|
||||
- return log_error_status_stall(err, L"Failed to acquire UEFI monotonic counter: %r", err);
|
||||
+ return log_error_status(err, "Failed to acquire UEFI monotonic counter: %m");
|
||||
size = sizeof(uefi_monotonic_counter);
|
||||
sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
sha256_process_bytes(&uefi_monotonic_counter, size, &hash);
|
||||
@@ -264,26 +264,26 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
if (size < info->FileSize) {
|
||||
err = handle->SetPosition(handle, size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to seek to offset of random seed file: %r", err);
|
||||
+ return log_error_status(err, "Failed to seek to offset of random seed file: %m");
|
||||
wsize = info->FileSize - size;
|
||||
err = handle->Write(handle, &wsize, seed /* All zeros now */);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to write random seed file: %r", err);
|
||||
+ return log_error_status(err, "Failed to write random seed file: %m");
|
||||
if (wsize != info->FileSize - size)
|
||||
- return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short write on random seed file.");
|
||||
+ return log_error_status(EFI_PROTOCOL_ERROR, "Short write on random seed file.");
|
||||
err = handle->Flush(handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to flush random seed file: %r", err);
|
||||
+ return log_error_status(err, "Failed to flush random seed file: %m");
|
||||
err = handle->SetPosition(handle, 0);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err);
|
||||
+ return log_error_status(err, "Failed to seek to beginning of random seed file: %m");
|
||||
|
||||
/* We could truncate the file here with something like:
|
||||
*
|
||||
* info->FileSize = size;
|
||||
* err = handle->SetInfo(handle, &GenericFileInfo, info->Size, info);
|
||||
* if (err != EFI_SUCCESS)
|
||||
- * return log_error_status_stall(err, L"Failed to truncate random seed file: %r", err);
|
||||
+ * return log_error_status(err, "Failed to truncate random seed file: %u");
|
||||
*
|
||||
* But this is considered slightly risky, because EFI filesystem drivers are a little bit
|
||||
* flimsy. So instead we rely on userspace eventually truncating this when it writes a new
|
||||
@@ -293,18 +293,18 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
wsize = size;
|
||||
err = handle->Write(handle, &wsize, random_bytes);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to write random seed file: %r", err);
|
||||
+ return log_error_status(err, "Failed to write random seed file: %m");
|
||||
if (wsize != size)
|
||||
- return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short write on random seed file.");
|
||||
+ return log_error_status(EFI_PROTOCOL_ERROR, "Short write on random seed file.");
|
||||
err = handle->Flush(handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to flush random seed file: %r", err);
|
||||
+ return log_error_status(err, "Failed to flush random seed file: %m");
|
||||
|
||||
err = BS->AllocatePool(EfiACPIReclaimMemory,
|
||||
offsetof(struct linux_efi_random_seed, seed) + DESIRED_SEED_SIZE,
|
||||
(void **) &new_seed_table);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to allocate EFI table for random seed: %r", err);
|
||||
+ return log_error_status(err, "Failed to allocate EFI table for random seed: %m");
|
||||
new_seed_table->size = DESIRED_SEED_SIZE;
|
||||
|
||||
/* hash = hash_key || 1 */
|
||||
@@ -316,7 +316,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) {
|
||||
|
||||
err = BS->InstallConfigurationTable(&(EFI_GUID)LINUX_EFI_RANDOM_SEED_TABLE_GUID, new_seed_table);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed to install EFI table for random seed: %r", err);
|
||||
+ return log_error_status(err, "Failed to install EFI table for random seed: %m");
|
||||
TAKE_PTR(new_seed_table);
|
||||
|
||||
if (previous_seed_table) {
|
||||
diff --git a/src/boot/efi/secure-boot.c b/src/boot/efi/secure-boot.c
|
||||
index 3f3a222b5e..6b6d48277e 100644
|
||||
--- a/src/boot/efi/secure-boot.c
|
||||
+++ b/src/boot/efi/secure-boot.c
|
||||
@@ -66,10 +66,9 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) {
|
||||
continue;
|
||||
}
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(
|
||||
+ return log_error_status(
|
||||
err,
|
||||
- L"Error waiting for user input to enroll Secure Boot keys: %r",
|
||||
- err);
|
||||
+ "Error waiting for user input to enroll Secure Boot keys: %m");
|
||||
|
||||
/* user aborted, returning EFI_SUCCESS here allows the user to go back to the menu */
|
||||
return EFI_SUCCESS;
|
||||
@@ -80,7 +79,7 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) {
|
||||
|
||||
err = open_directory(root_dir, path, &dir);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Failed opening keys directory %s: %r", path, err);
|
||||
+ return log_error_status(err, "Failed opening keys directory %ls: %m", path);
|
||||
|
||||
struct {
|
||||
const char16_t *name;
|
||||
@@ -98,7 +97,7 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) {
|
||||
for (size_t i = 0; i < ELEMENTSOF(sb_vars); i++) {
|
||||
err = file_read(dir, sb_vars[i].filename, 0, 0, &sb_vars[i].buffer, &sb_vars[i].size);
|
||||
if (err != EFI_SUCCESS) {
|
||||
- log_error_stall(L"Failed reading file %s\\%s: %r", path, sb_vars[i].filename, err);
|
||||
+ log_error_status(err, "Failed reading file %ls\\%ls: %m", path, sb_vars[i].filename);
|
||||
goto out_deallocate;
|
||||
}
|
||||
}
|
||||
@@ -112,7 +111,7 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) {
|
||||
|
||||
err = efivar_set_raw(&sb_vars[i].vendor, sb_vars[i].name, sb_vars[i].buffer, sb_vars[i].size, sb_vars_opts);
|
||||
if (err != EFI_SUCCESS) {
|
||||
- log_error_stall(L"Failed to write %s secure boot variable: %r", sb_vars[i].name, err);
|
||||
+ log_error_status(err, "Failed to write %ls secure boot variable: %m", sb_vars[i].name);
|
||||
goto out_deallocate;
|
||||
}
|
||||
}
|
||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
||||
index 433fef548c..f9c023e11c 100644
|
||||
--- a/src/boot/efi/stub.c
|
||||
+++ b/src/boot/efi/stub.c
|
||||
@@ -207,7 +207,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (err != EFI_SUCCESS)
|
||||
- return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
|
||||
+ return log_error_status(err, "Error getting a LoadedImageProtocol handle: %m");
|
||||
|
||||
if (efivar_get_uint64_le(LOADER_GUID, L"LoaderFeatures", &loader_features) != EFI_SUCCESS ||
|
||||
!FLAGS_SET(loader_features, EFI_LOADER_FEATURE_RANDOM_SEED)) {
|
||||
@@ -222,7 +222,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
if (err != EFI_SUCCESS || szs[UNIFIED_SECTION_LINUX] == 0) {
|
||||
if (err == EFI_SUCCESS)
|
||||
err = EFI_NOT_FOUND;
|
||||
- return log_error_status_stall(err, L"Unable to locate embedded .linux section: %r", err);
|
||||
+ return log_error_status(err, "Unable to locate embedded .linux section: %m");
|
||||
}
|
||||
|
||||
/* Measure all "payload" of this PE image into a separate PCR (i.e. where nothing else is written
|
||||
@@ -417,7 +417,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
err = devicetree_install_from_memory(
|
||||
&dt_state, PHYSICAL_ADDRESS_TO_POINTER(dt_base), dt_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
- log_error_stall(L"Error loading embedded devicetree: %r", err);
|
||||
+ log_error_status(err, "Error loading embedded devicetree: %m");
|
||||
}
|
||||
|
||||
err = linux_exec(image, cmdline,
|
||||
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
|
||||
index 7596bc3edc..320bddec1b 100644
|
||||
--- a/src/boot/efi/util.c
|
||||
+++ b/src/boot/efi/util.c
|
||||
@@ -325,34 +325,6 @@ EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, size_t off, size_t siz
|
||||
return err;
|
||||
}
|
||||
|
||||
-void log_error_stall(const char16_t *fmt, ...) {
|
||||
- va_list args;
|
||||
-
|
||||
- assert(fmt);
|
||||
-
|
||||
- int32_t attr = ST->ConOut->Mode->Attribute;
|
||||
- ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTRED|EFI_BACKGROUND_BLACK);
|
||||
-
|
||||
- if (ST->ConOut->Mode->CursorColumn > 0)
|
||||
- Print(L"\n");
|
||||
-
|
||||
- va_start(args, fmt);
|
||||
- VPrint(fmt, args);
|
||||
- va_end(args);
|
||||
-
|
||||
- Print(L"\n");
|
||||
-
|
||||
- ST->ConOut->SetAttribute(ST->ConOut, attr);
|
||||
-
|
||||
- /* Give the user a chance to see the message. */
|
||||
- BS->Stall(3 * 1000 * 1000);
|
||||
-}
|
||||
-
|
||||
-EFI_STATUS log_oom(void) {
|
||||
- log_error_stall(L"Out of memory.");
|
||||
- return EFI_OUT_OF_RESOURCES;
|
||||
-}
|
||||
-
|
||||
void print_at(size_t x, size_t y, size_t attr, const char16_t *str) {
|
||||
assert(str);
|
||||
ST->ConOut->SetCursorPosition(ST->ConOut, x, y);
|
||||
@@ -572,7 +544,7 @@ void hexdump(const char16_t *prefix, const void *data, size_t size) {
|
||||
|
||||
buf[size*2] = 0;
|
||||
|
||||
- log_error_stall(L"%s[%" PRIuN "]: %s", prefix, size, buf);
|
||||
+ log_error("%ls[%zu]: %ls", prefix, size, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
|
||||
index b97dc9768c..771f11c8bd 100644
|
||||
--- a/src/boot/efi/util.h
|
||||
+++ b/src/boot/efi/util.h
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <efilib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
+#include "log.h"
|
||||
#include "string-util-fundamental.h"
|
||||
|
||||
#define UINTN_MAX (~(UINTN)0)
|
||||
@@ -139,17 +140,6 @@ static inline void unload_imagep(EFI_HANDLE *image) {
|
||||
&(const EFI_GUID) { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } }
|
||||
#define EFI_GLOBAL_GUID &(const EFI_GUID) EFI_GLOBAL_VARIABLE
|
||||
|
||||
-void log_error_stall(const char16_t *fmt, ...);
|
||||
-EFI_STATUS log_oom(void);
|
||||
-
|
||||
-/* This works just like log_error_errno() from userspace, but requires you
|
||||
- * to provide err a second time if you want to use %r in the message! */
|
||||
-#define log_error_status_stall(err, fmt, ...) \
|
||||
- ({ \
|
||||
- log_error_stall(fmt, ##__VA_ARGS__); \
|
||||
- err; \
|
||||
- })
|
||||
-
|
||||
void print_at(size_t x, size_t y, size_t attr, const char16_t *str);
|
||||
void clear_screen(size_t attr);
|
||||
|
220
0683-boot-Introduce-log_wait.patch
Normal file
220
0683-boot-Introduce-log_wait.patch
Normal file
@ -0,0 +1,220 @@
|
||||
From e2493416cd85725a1198a391f9b1f93e1e9db88e Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Sun, 5 Jun 2022 13:19:21 +0200
|
||||
Subject: [PATCH] boot: Introduce log_wait
|
||||
|
||||
Instead of stalling for every log message as it appears we now wait for
|
||||
several messages at strategic locations.
|
||||
|
||||
(cherry picked from commit 6ac54809deefddccc7861b5a2cfa4d766cf1aa3b)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/boot.c | 18 +++++++++++++-----
|
||||
src/boot/efi/console.c | 1 +
|
||||
src/boot/efi/graphics.c | 7 ++++---
|
||||
src/boot/efi/linux.c | 1 +
|
||||
src/boot/efi/linux_x86.c | 1 +
|
||||
src/boot/efi/log.c | 13 +++++++++++--
|
||||
src/boot/efi/log.h | 1 +
|
||||
src/boot/efi/stub.c | 19 +++++++++++++------
|
||||
src/boot/efi/util.c | 1 +
|
||||
9 files changed, 46 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
|
||||
index 1e7b7a0fa7..1e94aa57b1 100644
|
||||
--- a/src/boot/efi/boot.c
|
||||
+++ b/src/boot/efi/boot.c
|
||||
@@ -2612,7 +2612,7 @@ static EFI_STATUS discover_root_dir(EFI_LOADED_IMAGE_PROTOCOL *loaded_image, EFI
|
||||
return open_volume(loaded_image->DeviceHandle, ret_dir);
|
||||
}
|
||||
|
||||
-EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
+static EFI_STATUS real_main(EFI_HANDLE image) {
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
|
||||
_cleanup_(file_closep) EFI_FILE *root_dir = NULL;
|
||||
_cleanup_(config_free) Config config = {};
|
||||
@@ -2621,11 +2621,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
uint64_t init_usec;
|
||||
bool menu = false;
|
||||
|
||||
- InitializeLib(image, sys_table);
|
||||
init_usec = time_usec();
|
||||
- debug_hook(L"systemd-boot");
|
||||
- /* Uncomment the next line if you need to wait for debugger. */
|
||||
- // debug_break();
|
||||
|
||||
err = BS->OpenProtocol(image,
|
||||
&LoadedImageProtocol,
|
||||
@@ -2714,3 +2710,15 @@ out:
|
||||
BS->CloseProtocol(image, &LoadedImageProtocol, image, NULL);
|
||||
return err;
|
||||
}
|
||||
+
|
||||
+EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
+ InitializeLib(image, sys_table);
|
||||
+
|
||||
+ debug_hook(L"systemd-boot");
|
||||
+ /* Uncomment the next line if you need to wait for debugger. */
|
||||
+ // debug_break();
|
||||
+
|
||||
+ EFI_STATUS err = real_main(image);
|
||||
+ log_wait();
|
||||
+ return err;
|
||||
+}
|
||||
diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c
|
||||
index b876ff2bd7..001b82854b 100644
|
||||
--- a/src/boot/efi/console.c
|
||||
+++ b/src/boot/efi/console.c
|
||||
@@ -188,6 +188,7 @@ static EFI_STATUS change_mode(int64_t mode) {
|
||||
mode = CLAMP(mode, CONSOLE_MODE_RANGE_MIN, CONSOLE_MODE_RANGE_MAX);
|
||||
old_mode = MAX(CONSOLE_MODE_RANGE_MIN, ST->ConOut->Mode->Mode);
|
||||
|
||||
+ log_wait();
|
||||
err = ST->ConOut->SetMode(ST->ConOut, mode);
|
||||
if (err == EFI_SUCCESS)
|
||||
return EFI_SUCCESS;
|
||||
diff --git a/src/boot/efi/graphics.c b/src/boot/efi/graphics.c
|
||||
index dc646bce1f..350d1bc434 100644
|
||||
--- a/src/boot/efi/graphics.c
|
||||
+++ b/src/boot/efi/graphics.c
|
||||
@@ -25,16 +25,17 @@ EFI_STATUS graphics_mode(bool on) {
|
||||
return err == EFI_NOT_FOUND ? EFI_SUCCESS : err;
|
||||
|
||||
/* check current mode */
|
||||
- err =ConsoleControl->GetMode(ConsoleControl, ¤t, &uga_exists, &stdin_locked);
|
||||
+ err = ConsoleControl->GetMode(ConsoleControl, ¤t, &uga_exists, &stdin_locked);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
/* do not touch the mode */
|
||||
- new = on ? EfiConsoleControlScreenGraphics : EfiConsoleControlScreenText;
|
||||
+ new = on ? EfiConsoleControlScreenGraphics : EfiConsoleControlScreenText;
|
||||
if (new == current)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
- err =ConsoleControl->SetMode(ConsoleControl, new);
|
||||
+ log_wait();
|
||||
+ err = ConsoleControl->SetMode(ConsoleControl, new);
|
||||
|
||||
/* some firmware enables the cursor when switching modes */
|
||||
ST->ConOut->EnableCursor(ST->ConOut, false);
|
||||
diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c
|
||||
index 2ae68ec295..727e507101 100644
|
||||
--- a/src/boot/efi/linux.c
|
||||
+++ b/src/boot/efi/linux.c
|
||||
@@ -142,6 +142,7 @@ EFI_STATUS linux_exec(
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error registering initrd: %m");
|
||||
|
||||
+ log_wait();
|
||||
err = BS->StartImage(kernel_image, NULL, NULL);
|
||||
|
||||
/* Try calling the kernel compat entry point if one exists. */
|
||||
diff --git a/src/boot/efi/linux_x86.c b/src/boot/efi/linux_x86.c
|
||||
index cbd92201b6..eaae988d97 100644
|
||||
--- a/src/boot/efi/linux_x86.c
|
||||
+++ b/src/boot/efi/linux_x86.c
|
||||
@@ -209,6 +209,7 @@ EFI_STATUS linux_exec_efi_handover(
|
||||
boot_params->hdr.ramdisk_size = initrd_length;
|
||||
boot_params->ext_ramdisk_size = ((uint64_t) initrd_length) >> 32;
|
||||
|
||||
+ log_wait();
|
||||
linux_efi_handover(parent, (uintptr_t) linux_buffer, boot_params);
|
||||
return EFI_LOAD_ERROR;
|
||||
}
|
||||
diff --git a/src/boot/efi/log.c b/src/boot/efi/log.c
|
||||
index 38e7c5a8a8..b1a613e4e5 100644
|
||||
--- a/src/boot/efi/log.c
|
||||
+++ b/src/boot/efi/log.c
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "log.h"
|
||||
|
||||
+static unsigned log_count = 0;
|
||||
+
|
||||
void efi_assert(const char *expr, const char *file, unsigned line, const char *function) {
|
||||
log_error("systemd-boot assertion '%s' failed at %s:%u@%s. Halting.", expr, file, line, function);
|
||||
for (;;)
|
||||
@@ -28,7 +30,14 @@ EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...) {
|
||||
ST->ConOut->OutputString(ST->ConOut, (char16_t *) u"\r\n");
|
||||
ST->ConOut->SetAttribute(ST->ConOut, attr);
|
||||
|
||||
- /* Give the user a chance to see the message. */
|
||||
- BS->Stall(3 * 1000 * 1000);
|
||||
+ log_count++;
|
||||
return status;
|
||||
}
|
||||
+
|
||||
+void log_wait(void) {
|
||||
+ if (log_count == 0)
|
||||
+ return;
|
||||
+
|
||||
+ BS->Stall(MIN(4u, log_count) * 2500 * 1000);
|
||||
+ log_count = 0;
|
||||
+}
|
||||
diff --git a/src/boot/efi/log.h b/src/boot/efi/log.h
|
||||
index c6e8d626ce..f24034fd78 100644
|
||||
--- a/src/boot/efi/log.h
|
||||
+++ b/src/boot/efi/log.h
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "efi-string.h"
|
||||
|
||||
+void log_wait(void);
|
||||
_gnu_printf_(2, 3) EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...);
|
||||
#define log_error_status(status, ...) log_internal(status, __VA_ARGS__)
|
||||
#define log_error(...) log_internal(EFI_INVALID_PARAMETER, __VA_ARGS__)
|
||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
||||
index f9c023e11c..f71f041a2f 100644
|
||||
--- a/src/boot/efi/stub.c
|
||||
+++ b/src/boot/efi/stub.c
|
||||
@@ -180,7 +180,7 @@ static bool use_load_options(
|
||||
return true;
|
||||
}
|
||||
|
||||
-EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
+static EFI_STATUS real_main(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;
|
||||
size_t linux_size, initrd_size, dt_size;
|
||||
@@ -194,11 +194,6 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
uint64_t loader_features = 0;
|
||||
EFI_STATUS err;
|
||||
|
||||
- InitializeLib(image, sys_table);
|
||||
- debug_hook(L"systemd-stub");
|
||||
- /* Uncomment the next line if you need to wait for debugger. */
|
||||
- // debug_break();
|
||||
-
|
||||
err = BS->OpenProtocol(
|
||||
image,
|
||||
&LoadedImageProtocol,
|
||||
@@ -426,3 +421,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
graphics_mode(false);
|
||||
return err;
|
||||
}
|
||||
+
|
||||
+EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
+ InitializeLib(image, sys_table);
|
||||
+
|
||||
+ debug_hook(L"systemd-stub");
|
||||
+ /* Uncomment the next line if you need to wait for debugger. */
|
||||
+ // debug_break();
|
||||
+
|
||||
+ EFI_STATUS err = real_main(image);
|
||||
+ log_wait();
|
||||
+ return err;
|
||||
+}
|
||||
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
|
||||
index 320bddec1b..aa7b1fa1a2 100644
|
||||
--- a/src/boot/efi/util.c
|
||||
+++ b/src/boot/efi/util.c
|
||||
@@ -333,6 +333,7 @@ void print_at(size_t x, size_t y, size_t attr, const char16_t *str) {
|
||||
}
|
||||
|
||||
void clear_screen(size_t attr) {
|
||||
+ log_wait();
|
||||
ST->ConOut->SetAttribute(ST->ConOut, attr);
|
||||
ST->ConOut->ClearScreen(ST->ConOut);
|
||||
}
|
21
0684-boot-Add-log_trace-debugging-helper.patch
Normal file
21
0684-boot-Add-log_trace-debugging-helper.patch
Normal file
@ -0,0 +1,21 @@
|
||||
From ee1dfadec7be7c64a2bc2b34a1e4195b9048c46f Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Thu, 18 Aug 2022 13:41:49 +0200
|
||||
Subject: [PATCH] boot: Add log_trace debugging helper
|
||||
|
||||
(cherry picked from commit 5966c54df4668abc17ae12c40fb0c30d31e80998)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/log.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/boot/efi/log.h b/src/boot/efi/log.h
|
||||
index f24034fd78..9bdcfad923 100644
|
||||
--- a/src/boot/efi/log.h
|
||||
+++ b/src/boot/efi/log.h
|
||||
@@ -8,3 +8,4 @@ _gnu_printf_(2, 3) EFI_STATUS log_internal(EFI_STATUS status, const char *format
|
||||
#define log_error_status(status, ...) log_internal(status, __VA_ARGS__)
|
||||
#define log_error(...) log_internal(EFI_INVALID_PARAMETER, __VA_ARGS__)
|
||||
#define log_oom() log_internal(EFI_OUT_OF_RESOURCES, "Out of memory.")
|
||||
+#define log_trace() log_internal(EFI_SUCCESS, "%s:%i@%s", __FILE__, __LINE__, __func__)
|
78
0685-tree-wide-Use-__func__-in-asserts.patch
Normal file
78
0685-tree-wide-Use-__func__-in-asserts.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From b3fb286a49f0a4254f49ff88d1ed520e878c5cca Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Thu, 18 Aug 2022 13:43:19 +0200
|
||||
Subject: [PATCH] tree-wide: Use __func__ in asserts
|
||||
|
||||
clang puts the whole function signature in __PRETTY_FUNCTION__, which is
|
||||
a bit excessive for something that can already be figured out by using
|
||||
the line number.
|
||||
|
||||
(cherry picked from commit 5a9b91576630f82ca72a932b5195654dbb04d67e)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/basic/macro.h | 6 +++---
|
||||
src/fundamental/macro-fundamental.h | 6 +++---
|
||||
src/journal/test-journal-interleaving.c | 2 +-
|
||||
3 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/basic/macro.h b/src/basic/macro.h
|
||||
index 9cb7ae5077..2d378454a2 100644
|
||||
--- a/src/basic/macro.h
|
||||
+++ b/src/basic/macro.h
|
||||
@@ -194,12 +194,12 @@ static inline int __coverity_check_and_return__(int condition) {
|
||||
#define assert_message_se(expr, message) \
|
||||
do { \
|
||||
if (_unlikely_(!(expr))) \
|
||||
- log_assert_failed(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \
|
||||
+ log_assert_failed(message, PROJECT_FILE, __LINE__, __func__); \
|
||||
} while (false)
|
||||
|
||||
#define assert_log(expr, message) ((_likely_(expr)) \
|
||||
? (true) \
|
||||
- : (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__), false))
|
||||
+ : (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __func__), false))
|
||||
|
||||
#endif /* __COVERITY__ */
|
||||
|
||||
@@ -214,7 +214,7 @@ static inline int __coverity_check_and_return__(int condition) {
|
||||
#endif
|
||||
|
||||
#define assert_not_reached() \
|
||||
- log_assert_failed_unreachable(PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__)
|
||||
+ log_assert_failed_unreachable(PROJECT_FILE, __LINE__, __func__)
|
||||
|
||||
#define assert_return(expr, r) \
|
||||
do { \
|
||||
diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h
|
||||
index 1c4c445e4e..e226d8d411 100644
|
||||
--- a/src/fundamental/macro-fundamental.h
|
||||
+++ b/src/fundamental/macro-fundamental.h
|
||||
@@ -73,11 +73,11 @@
|
||||
#define assert(expr)
|
||||
#define assert_not_reached() __builtin_unreachable()
|
||||
#else
|
||||
- #define assert(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); })
|
||||
- #define assert_not_reached() efi_assert("Code should not be reached", __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||
+ #define assert(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __func__); })
|
||||
+ #define assert_not_reached() efi_assert("Code should not be reached", __FILE__, __LINE__, __func__)
|
||||
#endif
|
||||
#define static_assert _Static_assert
|
||||
- #define assert_se(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); })
|
||||
+ #define assert_se(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __func__); })
|
||||
#endif
|
||||
|
||||
/* This passes the argument through after (if asserts are enabled) checking that it is not null. */
|
||||
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
|
||||
index b3ae4b8143..fb38cc7e82 100644
|
||||
--- a/src/journal/test-journal-interleaving.c
|
||||
+++ b/src/journal/test-journal-interleaving.c
|
||||
@@ -30,7 +30,7 @@ _noreturn_ static void log_assert_errno(const char *text, int error, const char
|
||||
do { \
|
||||
int _r_ = (expr); \
|
||||
if (_unlikely_(_r_ < 0)) \
|
||||
- log_assert_errno(#expr, -_r_, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \
|
||||
+ log_assert_errno(#expr, -_r_, PROJECT_FILE, __LINE__, __func__); \
|
||||
} while (false)
|
||||
|
||||
static ManagedJournalFile *test_open(const char *name) {
|
326
0686-boot-Drop-use-of-xpool_print-SPrint.patch
Normal file
326
0686-boot-Drop-use-of-xpool_print-SPrint.patch
Normal file
@ -0,0 +1,326 @@
|
||||
From a15ea7473b6e54c3019daf2a894d681c0928a132 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Sun, 5 Jun 2022 15:08:07 +0200
|
||||
Subject: [PATCH] boot: Drop use of xpool_print/SPrint
|
||||
|
||||
(cherry picked from commit 2f3c3b0bee5534f2338439f04b0aa517479f8b76)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/boot.c | 73 +++++++++++++++++++++---------------------
|
||||
src/boot/efi/cpio.c | 2 +-
|
||||
src/boot/efi/drivers.c | 2 +-
|
||||
src/boot/efi/stub.c | 6 ++--
|
||||
src/boot/efi/util.h | 1 -
|
||||
src/boot/efi/vmm.c | 3 +-
|
||||
6 files changed, 43 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
|
||||
index 1e94aa57b1..64a9eda24e 100644
|
||||
--- a/src/boot/efi/boot.c
|
||||
+++ b/src/boot/efi/boot.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <efi.h>
|
||||
#include <efigpt.h>
|
||||
#include <efilib.h>
|
||||
+#include <inttypes.h>
|
||||
|
||||
#include "bcd.h"
|
||||
#include "bootspec-fundamental.h"
|
||||
@@ -417,7 +418,7 @@ static char16_t *update_timeout_efivar(uint32_t *t, bool inc) {
|
||||
case TIMEOUT_MENU_HIDDEN:
|
||||
return xstrdup16(u"Menu disabled. Hold down key at bootup to show menu.");
|
||||
default:
|
||||
- return xpool_print(L"Menu timeout set to %u s.", *t);
|
||||
+ return xasprintf("Menu timeout set to %u s.", *t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -749,7 +750,7 @@ static bool menu_run(
|
||||
|
||||
if (timeout_remain > 0) {
|
||||
free(status);
|
||||
- status = xpool_print(L"Boot in %u s.", timeout_remain);
|
||||
+ status = xasprintf("Boot in %u s.", timeout_remain);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
@@ -928,9 +929,9 @@ static bool menu_run(
|
||||
break;
|
||||
|
||||
case KEYPRESS(0, 0, 'v'):
|
||||
- status = xpool_print(
|
||||
- L"systemd-boot " GIT_VERSION L" (" EFI_MACHINE_TYPE_NAME L"), "
|
||||
- L"UEFI Specification %u.%02u, Vendor %s %u.%02u",
|
||||
+ status = xasprintf(
|
||||
+ "systemd-boot " GIT_VERSION " (" EFI_MACHINE_TYPE_NAME "), "
|
||||
+ "UEFI Specification %u.%02u, Vendor %ls %u.%02u",
|
||||
ST->Hdr.Revision >> 16,
|
||||
ST->Hdr.Revision & 0xffff,
|
||||
ST->FirmwareVendor,
|
||||
@@ -952,10 +953,12 @@ static bool menu_run(
|
||||
case KEYPRESS(0, 0, 'r'):
|
||||
err = console_set_mode(CONSOLE_MODE_NEXT);
|
||||
if (err != EFI_SUCCESS)
|
||||
- status = xpool_print(L"Error changing console mode: %r", err);
|
||||
+ status = xasprintf_status(err, "Error changing console mode: %m");
|
||||
else {
|
||||
config->console_mode_efivar = ST->ConOut->Mode->Mode;
|
||||
- status = xpool_print(L"Console mode changed to %ld.", config->console_mode_efivar);
|
||||
+ status = xasprintf(
|
||||
+ "Console mode changed to %" PRIi64 ".",
|
||||
+ config->console_mode_efivar);
|
||||
}
|
||||
new_mode = true;
|
||||
break;
|
||||
@@ -965,10 +968,13 @@ static bool menu_run(
|
||||
err = console_set_mode(config->console_mode == CONSOLE_MODE_KEEP ?
|
||||
console_mode_initial : config->console_mode);
|
||||
if (err != EFI_SUCCESS)
|
||||
- status = xpool_print(L"Error resetting console mode: %r", err);
|
||||
+ status = xasprintf_status(err, "Error resetting console mode: %m");
|
||||
else
|
||||
- status = xpool_print(L"Console mode reset to %s default.",
|
||||
- config->console_mode == CONSOLE_MODE_KEEP ? L"firmware" : L"configuration file");
|
||||
+ status = xasprintf(
|
||||
+ "Console mode reset to %s default.",
|
||||
+ config->console_mode == CONSOLE_MODE_KEEP ?
|
||||
+ "firmware" :
|
||||
+ "configuration file");
|
||||
new_mode = true;
|
||||
break;
|
||||
|
||||
@@ -981,9 +987,9 @@ static bool menu_run(
|
||||
if (FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) {
|
||||
firmware_setup = true;
|
||||
/* Let's make sure the user really wants to do this. */
|
||||
- status = xpool_print(L"Press Enter to reboot into firmware interface.");
|
||||
+ status = xstrdup16(u"Press Enter to reboot into firmware interface.");
|
||||
} else
|
||||
- status = xpool_print(L"Reboot into firmware interface not supported.");
|
||||
+ status = xstrdup16(u"Reboot into firmware interface not supported.");
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1317,9 +1323,9 @@ static void config_entry_parse_tries(
|
||||
entry->tries_done = tries_done;
|
||||
entry->path = xstrdup16(path);
|
||||
entry->current_name = xstrdup16(file);
|
||||
- entry->next_name = xpool_print(
|
||||
- L"%.*s%u-%u%s",
|
||||
- prefix_len,
|
||||
+ entry->next_name = xasprintf(
|
||||
+ "%.*ls%" PRIu64 "-%" PRIu64 "%ls",
|
||||
+ (int) prefix_len,
|
||||
file,
|
||||
LESS_BY(tries_left, 1u),
|
||||
MIN(tries_done + 1, (uint64_t) INT_MAX),
|
||||
@@ -1342,7 +1348,7 @@ static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) {
|
||||
if (!entry->path || !entry->current_name || !entry->next_name)
|
||||
return;
|
||||
|
||||
- old_path = xpool_print(L"%s\\%s", entry->path, entry->current_name);
|
||||
+ old_path = xasprintf("%ls\\%ls", entry->path, entry->current_name);
|
||||
|
||||
err = root_dir->Open(root_dir, &handle, old_path, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0ULL);
|
||||
if (err != EFI_SUCCESS)
|
||||
@@ -1365,7 +1371,7 @@ static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) {
|
||||
|
||||
/* Let's tell the OS that we renamed this file, so that it knows what to rename to the counter-less name on
|
||||
* success */
|
||||
- new_path = xpool_print(L"%s\\%s", entry->path, entry->next_name);
|
||||
+ new_path = xasprintf("%ls\\%ls", entry->path, entry->next_name);
|
||||
efivar_set(LOADER_GUID, L"LoaderBootCountPath", new_path, 0);
|
||||
|
||||
/* If the file we just renamed is the loader path, then let's update that. */
|
||||
@@ -1479,7 +1485,7 @@ static void config_entry_add_type1(
|
||||
|
||||
new = xstr8_to_16(value);
|
||||
if (entry->options) {
|
||||
- char16_t *s = xpool_print(L"%s %s", entry->options, new);
|
||||
+ char16_t *s = xasprintf("%ls %ls", entry->options, new);
|
||||
free(entry->options);
|
||||
entry->options = s;
|
||||
} else
|
||||
@@ -1796,7 +1802,7 @@ static void config_title_generate(Config *config) {
|
||||
continue;
|
||||
|
||||
_cleanup_free_ char16_t *t = config->entries[i]->title_show;
|
||||
- config->entries[i]->title_show = xpool_print(L"%s (%s)", t, config->entries[i]->version);
|
||||
+ config->entries[i]->title_show = xasprintf("%ls (%ls)", t, config->entries[i]->version);
|
||||
}
|
||||
|
||||
if (entries_unique(config->entries, unique, config->entry_count))
|
||||
@@ -1813,11 +1819,7 @@ static void config_title_generate(Config *config) {
|
||||
continue;
|
||||
|
||||
_cleanup_free_ char16_t *t = config->entries[i]->title_show;
|
||||
- config->entries[i]->title_show = xpool_print(
|
||||
- L"%s (%.*s)",
|
||||
- t,
|
||||
- strnlen16(config->entries[i]->machine_id, 8),
|
||||
- config->entries[i]->machine_id);
|
||||
+ config->entries[i]->title_show = xasprintf("%ls (%.8ls)", t, config->entries[i]->machine_id);
|
||||
}
|
||||
|
||||
if (entries_unique(config->entries, unique, config->entry_count))
|
||||
@@ -1829,7 +1831,7 @@ static void config_title_generate(Config *config) {
|
||||
continue;
|
||||
|
||||
_cleanup_free_ char16_t *t = config->entries[i]->title_show;
|
||||
- config->entries[i]->title_show = xpool_print(L"%s (%s)", t, config->entries[i]->id);
|
||||
+ config->entries[i]->title_show = xasprintf("%ls (%ls)", t, config->entries[i]->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1994,10 +1996,9 @@ static EFI_STATUS boot_windows_bitlocker(void) {
|
||||
|
||||
for (size_t i = 0; i < boot_order_size / sizeof(uint16_t); i++) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
- char16_t name[sizeof(L"Boot0000")];
|
||||
size_t buf_size;
|
||||
|
||||
- SPrint(name, sizeof(name), L"Boot%04x", (uint32_t) boot_order[i]);
|
||||
+ _cleanup_free_ char16_t *name = xasprintf("Boot%04x", boot_order[i]);
|
||||
err = efivar_get_raw(EFI_GLOBAL_GUID, name, &buf, &buf_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
continue;
|
||||
@@ -2187,7 +2188,7 @@ static void config_entry_add_unified(
|
||||
.title = xstrdup16(good_name),
|
||||
.version = xstrdup16(good_version),
|
||||
.device = device,
|
||||
- .loader = xpool_print(L"\\EFI\\Linux\\%s", f->FileName),
|
||||
+ .loader = xasprintf("\\EFI\\Linux\\%ls", f->FileName),
|
||||
.sort_key = xstrdup16(good_sort_key),
|
||||
.key = 'l',
|
||||
.tries_done = -1,
|
||||
@@ -2266,9 +2267,9 @@ static EFI_STATUS initrd_prepare(
|
||||
STRV_FOREACH(i, entry->initrd) {
|
||||
_cleanup_free_ char16_t *o = options;
|
||||
if (o)
|
||||
- options = xpool_print(L"%s initrd=%s", o, *i);
|
||||
+ options = xasprintf("%ls initrd=%ls", o, *i);
|
||||
else
|
||||
- options = xpool_print(L"initrd=%s", *i);
|
||||
+ options = xasprintf("initrd=%ls", *i);
|
||||
|
||||
_cleanup_(file_closep) EFI_FILE *handle = NULL;
|
||||
err = root->Open(root, &handle, *i, EFI_FILE_MODE_READ, 0);
|
||||
@@ -2300,7 +2301,7 @@ static EFI_STATUS initrd_prepare(
|
||||
|
||||
if (entry->options) {
|
||||
_cleanup_free_ char16_t *o = options;
|
||||
- options = xpool_print(L"%s %s", o, entry->options);
|
||||
+ options = xasprintf("%ls %ls", o, entry->options);
|
||||
}
|
||||
|
||||
*ret_options = TAKE_PTR(options);
|
||||
@@ -2482,9 +2483,9 @@ static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir)
|
||||
|
||||
entry = xnew(ConfigEntry, 1);
|
||||
*entry = (ConfigEntry) {
|
||||
- .id = xpool_print(L"secure-boot-keys-%s", dirent->FileName),
|
||||
- .title = xpool_print(L"Enroll Secure Boot keys: %s", dirent->FileName),
|
||||
- .path = xpool_print(L"\\loader\\keys\\%s", dirent->FileName),
|
||||
+ .id = xasprintf("secure-boot-keys-%ls", dirent->FileName),
|
||||
+ .title = xasprintf("Enroll Secure Boot keys: %ls", dirent->FileName),
|
||||
+ .path = xasprintf("\\loader\\keys\\%ls", dirent->FileName),
|
||||
.type = LOADER_SECURE_BOOT_KEYS,
|
||||
.tries_done = -1,
|
||||
.tries_left = -1,
|
||||
@@ -2527,10 +2528,10 @@ static void export_variables(
|
||||
efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec);
|
||||
efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0);
|
||||
|
||||
- infostr = xpool_print(L"%s %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
|
||||
+ infostr = xasprintf("%ls %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
|
||||
efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", infostr, 0);
|
||||
|
||||
- typestr = xpool_print(L"UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
|
||||
+ typestr = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
|
||||
efivar_set(LOADER_GUID, L"LoaderFirmwareType", typestr, 0);
|
||||
|
||||
(void) efivar_set_uint64_le(LOADER_GUID, L"LoaderFeatures", loader_features, 0);
|
||||
diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c
|
||||
index 62773ded9a..0d95d40183 100644
|
||||
--- a/src/boot/efi/cpio.c
|
||||
+++ b/src/boot/efi/cpio.c
|
||||
@@ -360,7 +360,7 @@ static char16_t *get_dropin_dir(const EFI_DEVICE_PATH *file_path) {
|
||||
return NULL;
|
||||
|
||||
convert_efi_path(file_path_str);
|
||||
- return xpool_print(u"%s.extra.d", file_path_str);
|
||||
+ return xasprintf("%ls.extra.d", file_path_str);
|
||||
}
|
||||
|
||||
EFI_STATUS pack_cpio(
|
||||
diff --git a/src/boot/efi/drivers.c b/src/boot/efi/drivers.c
|
||||
index c76f8e0903..4abb3fbd82 100644
|
||||
--- a/src/boot/efi/drivers.c
|
||||
+++ b/src/boot/efi/drivers.c
|
||||
@@ -20,7 +20,7 @@ static EFI_STATUS load_one_driver(
|
||||
assert(loaded_image);
|
||||
assert(fname);
|
||||
|
||||
- spath = xpool_print(L"\\EFI\\systemd\\drivers\\%s", fname);
|
||||
+ spath = xasprintf("\\EFI\\systemd\\drivers\\%ls", fname);
|
||||
err = make_file_device_path(loaded_image->DeviceHandle, spath, &path);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error making file device path: %m");
|
||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
||||
index f71f041a2f..552660eb07 100644
|
||||
--- a/src/boot/efi/stub.c
|
||||
+++ b/src/boot/efi/stub.c
|
||||
@@ -114,14 +114,14 @@ static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
|
||||
/* if LoaderFirmwareInfo is not set, let's set it */
|
||||
if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) {
|
||||
_cleanup_free_ char16_t *s = NULL;
|
||||
- s = xpool_print(L"%s %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
|
||||
+ s = xasprintf("%ls %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
|
||||
efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", s, 0);
|
||||
}
|
||||
|
||||
/* ditto for LoaderFirmwareType */
|
||||
if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) {
|
||||
_cleanup_free_ char16_t *s = NULL;
|
||||
- s = xpool_print(L"UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
|
||||
+ s = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
|
||||
efivar_set(LOADER_GUID, L"LoaderFirmwareType", s, 0);
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ static bool use_load_options(
|
||||
*ret = xstrdup16(shell->Argv[1]);
|
||||
for (size_t i = 2; i < shell->Argc; i++) {
|
||||
_cleanup_free_ char16_t *old = *ret;
|
||||
- *ret = xpool_print(u"%s %s", old, shell->Argv[i]);
|
||||
+ *ret = xasprintf("%ls %ls", old, shell->Argv[i]);
|
||||
}
|
||||
|
||||
mangle_stub_cmdline(*ret);
|
||||
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
|
||||
index 771f11c8bd..e0c3b408f2 100644
|
||||
--- a/src/boot/efi/util.h
|
||||
+++ b/src/boot/efi/util.h
|
||||
@@ -68,7 +68,6 @@ static inline void *xrealloc(void *p, size_t old_size, size_t new_size) {
|
||||
return r;
|
||||
}
|
||||
|
||||
-#define xpool_print(fmt, ...) ((char16_t *) ASSERT_SE_PTR(PoolPrint((fmt), ##__VA_ARGS__)))
|
||||
#define xnew(type, n) ((type *) xmalloc_multiply(sizeof(type), (n)))
|
||||
|
||||
typedef struct {
|
||||
diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c
|
||||
index 3dfa92b58d..b24d556700 100644
|
||||
--- a/src/boot/efi/vmm.c
|
||||
+++ b/src/boot/efi/vmm.c
|
||||
@@ -97,9 +97,8 @@ EFI_STATUS vmm_open(EFI_HANDLE *ret_vmm_dev, EFI_FILE **ret_vmm_dir) {
|
||||
|
||||
for (size_t order = 0;; order++) {
|
||||
_cleanup_free_ EFI_DEVICE_PATH *dp = NULL;
|
||||
- char16_t order_str[STRLEN("VMMBootOrder") + 4 + 1];
|
||||
|
||||
- SPrint(order_str, sizeof(order_str), u"VMMBootOrder%04x", order);
|
||||
+ _cleanup_free_ char16_t *order_str = xasprintf("VMMBootOrder%04zx", order);
|
||||
dp_err = efivar_get_raw(&(EFI_GUID)VMM_BOOT_ORDER_GUID, order_str, (char**)&dp, NULL);
|
||||
|
||||
for (size_t i = 0; i < n_handles; i++) {
|
323
0687-boot-Drop-use-of-Print.patch
Normal file
323
0687-boot-Drop-use-of-Print.patch
Normal file
@ -0,0 +1,323 @@
|
||||
From 013b84264db5b2062840f0ff04df776fa144c586 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Tue, 23 Aug 2022 10:51:36 +0200
|
||||
Subject: [PATCH] boot: Drop use of Print
|
||||
|
||||
The custom print helpers have been replaced with explicit checks at the
|
||||
call site to keep this in line with the way it is done in userspace. Any
|
||||
calls where the check has been ommited should not need them as the value
|
||||
is expected to alawys be around.
|
||||
|
||||
(cherry picked from commit 9220b2c46bfbdf759b5a777a8bb3109a4d873039)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/boot.c | 176 ++++++++++++++++++++-----------------
|
||||
src/boot/efi/secure-boot.c | 6 +-
|
||||
src/boot/efi/stub.c | 2 +-
|
||||
src/boot/efi/util.h | 2 +-
|
||||
4 files changed, 102 insertions(+), 84 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
|
||||
index 64a9eda24e..cb237675ec 100644
|
||||
--- a/src/boot/efi/boot.c
|
||||
+++ b/src/boot/efi/boot.c
|
||||
@@ -433,22 +433,9 @@ static bool unicode_supported(void) {
|
||||
return cache;
|
||||
}
|
||||
|
||||
-static void ps_string(const char16_t *fmt, const void *value) {
|
||||
- assert(fmt);
|
||||
- if (value)
|
||||
- Print(fmt, value);
|
||||
-}
|
||||
-
|
||||
-static void ps_bool(const char16_t *fmt, bool value) {
|
||||
- assert(fmt);
|
||||
- Print(fmt, yes_no(value));
|
||||
-}
|
||||
-
|
||||
static bool ps_continue(void) {
|
||||
- if (unicode_supported())
|
||||
- Print(L"\n─── Press any key to continue, ESC or q to quit. ───\n\n");
|
||||
- else
|
||||
- Print(L"\n--- Press any key to continue, ESC or q to quit. ---\n\n");
|
||||
+ const char16_t *sep = unicode_supported() ? u"───" : u"---";
|
||||
+ printf("\n%ls Press any key to continue, ESC or q to quit. %ls\n\n", sep, sep);
|
||||
|
||||
uint64_t key;
|
||||
return console_key_read(&key, UINT64_MAX) == EFI_SUCCESS &&
|
||||
@@ -470,112 +457,143 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
|
||||
secure = secure_boot_mode();
|
||||
(void) efivar_get(LOADER_GUID, L"LoaderDevicePartUUID", &device_part_uuid);
|
||||
|
||||
- /* We employ some unusual indentation here for readability. */
|
||||
-
|
||||
- ps_string(L" systemd-boot version: %a\n", GIT_VERSION);
|
||||
- ps_string(L" loaded image: %s\n", loaded_image_path);
|
||||
- ps_string(L" loader partition UUID: %s\n", device_part_uuid);
|
||||
- ps_string(L" architecture: %a\n", EFI_MACHINE_TYPE_NAME);
|
||||
- Print(L" UEFI specification: %u.%02u\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
|
||||
- ps_string(L" firmware vendor: %s\n", ST->FirmwareVendor);
|
||||
- Print(L" firmware version: %u.%02u\n", ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
|
||||
- Print(L" OS indications: %lu\n", get_os_indications_supported());
|
||||
- Print(L" secure boot: %s (%s)\n", yes_no(IN_SET(secure, SECURE_BOOT_USER, SECURE_BOOT_DEPLOYED)), secure_boot_mode_to_string(secure));
|
||||
- ps_bool(L" shim: %s\n", shim_loaded());
|
||||
- ps_bool(L" TPM: %s\n", tpm_present());
|
||||
- Print(L" console mode: %d/%ld (%" PRIuN L"x%" PRIuN L" @%ux%u)\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - INT64_C(1), x_max, y_max, screen_width, screen_height);
|
||||
+ printf(" systemd-boot version: " GIT_VERSION "\n");
|
||||
+ if (loaded_image_path)
|
||||
+ printf(" loaded image: %ls\n", loaded_image_path);
|
||||
+ if (device_part_uuid)
|
||||
+ printf(" loader partition UUID: %ls\n", device_part_uuid);
|
||||
+ printf(" architecture: " EFI_MACHINE_TYPE_NAME "\n");
|
||||
+ printf(" UEFI specification: %u.%02u\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
|
||||
+ printf(" firmware vendor: %ls\n", ST->FirmwareVendor);
|
||||
+ printf(" firmware version: %u.%02u\n", ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
|
||||
+ printf(" OS indications: %#" PRIx64 "\n", get_os_indications_supported());
|
||||
+ printf(" secure boot: %ls (%ls)\n",
|
||||
+ yes_no(IN_SET(secure, SECURE_BOOT_USER, SECURE_BOOT_DEPLOYED)),
|
||||
+ secure_boot_mode_to_string(secure));
|
||||
+ printf(" shim: %ls\n", yes_no(shim_loaded()));
|
||||
+ printf(" TPM: %ls\n", yes_no(tpm_present()));
|
||||
+ printf(" console mode: %i/%" PRIi64 " (%zux%zu @%ux%u)\n",
|
||||
+ ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - INT64_C(1),
|
||||
+ x_max, y_max, screen_width, screen_height);
|
||||
|
||||
if (!ps_continue())
|
||||
return;
|
||||
|
||||
switch (config->timeout_sec_config) {
|
||||
case TIMEOUT_UNSET:
|
||||
- break;
|
||||
+ break;
|
||||
case TIMEOUT_MENU_FORCE:
|
||||
- Print(L" timeout (config): menu-force\n"); break;
|
||||
+ printf(" timeout (config): menu-force\n");
|
||||
+ break;
|
||||
case TIMEOUT_MENU_HIDDEN:
|
||||
- Print(L" timeout (config): menu-hidden\n"); break;
|
||||
+ printf(" timeout (config): menu-hidden\n");
|
||||
+ break;
|
||||
default:
|
||||
- Print(L" timeout (config): %u s\n", config->timeout_sec_config);
|
||||
+ printf(" timeout (config): %u s\n", config->timeout_sec_config);
|
||||
}
|
||||
|
||||
switch (config->timeout_sec_efivar) {
|
||||
case TIMEOUT_UNSET:
|
||||
- break;
|
||||
+ break;
|
||||
case TIMEOUT_MENU_FORCE:
|
||||
- Print(L" timeout (EFI var): menu-force\n"); break;
|
||||
+ printf(" timeout (EFI var): menu-force\n");
|
||||
+ break;
|
||||
case TIMEOUT_MENU_HIDDEN:
|
||||
- Print(L" timeout (EFI var): menu-hidden\n"); break;
|
||||
+ printf(" timeout (EFI var): menu-hidden\n");
|
||||
+ break;
|
||||
default:
|
||||
- Print(L" timeout (EFI var): %u s\n", config->timeout_sec_efivar);
|
||||
+ printf(" timeout (EFI var): %u s\n", config->timeout_sec_efivar);
|
||||
}
|
||||
|
||||
- ps_string(L" default (config): %s\n", config->entry_default_config);
|
||||
- ps_string(L" default (EFI var): %s\n", config->entry_default_efivar);
|
||||
- ps_string(L" default (one-shot): %s\n", config->entry_oneshot);
|
||||
- ps_string(L" saved entry: %s\n", config->entry_saved);
|
||||
- ps_bool(L" editor: %s\n", config->editor);
|
||||
- ps_bool(L" auto-entries: %s\n", config->auto_entries);
|
||||
- ps_bool(L" auto-firmware: %s\n", config->auto_firmware);
|
||||
- ps_bool(L" beep: %s\n", config->beep);
|
||||
- ps_bool(L" reboot-for-bitlocker: %s\n", config->reboot_for_bitlocker);
|
||||
+ if (config->entry_default_config)
|
||||
+ printf(" default (config): %ls\n", config->entry_default_config);
|
||||
+ if (config->entry_default_efivar)
|
||||
+ printf(" default (EFI var): %ls\n", config->entry_default_efivar);
|
||||
+ if (config->entry_oneshot)
|
||||
+ printf(" default (one-shot): %ls\n", config->entry_oneshot);
|
||||
+ if (config->entry_saved)
|
||||
+ printf(" saved entry: %ls\n", config->entry_saved);
|
||||
+ printf(" editor: %ls\n", yes_no(config->editor));
|
||||
+ printf(" auto-entries: %ls\n", yes_no(config->auto_entries));
|
||||
+ printf(" auto-firmware: %ls\n", yes_no(config->auto_firmware));
|
||||
+ printf(" beep: %ls\n", yes_no(config->beep));
|
||||
+ printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker));
|
||||
|
||||
switch (config->secure_boot_enroll) {
|
||||
case ENROLL_OFF:
|
||||
- Print(L" secure-boot-enroll: off\n"); break;
|
||||
+ printf(" secure-boot-enroll: off\n");
|
||||
+ break;
|
||||
case ENROLL_MANUAL:
|
||||
- Print(L" secure-boot-enroll: manual\n"); break;
|
||||
+ printf(" secure-boot-enroll: manual\n");
|
||||
+ break;
|
||||
case ENROLL_FORCE:
|
||||
- Print(L" secure-boot-enroll: force\n"); break;
|
||||
+ printf(" secure-boot-enroll: force\n");
|
||||
+ break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
switch (config->console_mode) {
|
||||
case CONSOLE_MODE_AUTO:
|
||||
- Print(L" console-mode (config): %s\n", L"auto"); break;
|
||||
+ printf(" console-mode (config): auto\n");
|
||||
+ break;
|
||||
case CONSOLE_MODE_KEEP:
|
||||
- Print(L" console-mode (config): %s\n", L"keep"); break;
|
||||
+ printf(" console-mode (config): keep\n");
|
||||
+ break;
|
||||
case CONSOLE_MODE_FIRMWARE_MAX:
|
||||
- Print(L" console-mode (config): %s\n", L"max"); break;
|
||||
+ printf(" console-mode (config): max\n");
|
||||
+ break;
|
||||
default:
|
||||
- Print(L" console-mode (config): %ld\n", config->console_mode); break;
|
||||
+ printf(" console-mode (config): %" PRIi64 "\n", config->console_mode);
|
||||
+ break;
|
||||
}
|
||||
|
||||
/* EFI var console mode is always a concrete value or unset. */
|
||||
if (config->console_mode_efivar != CONSOLE_MODE_KEEP)
|
||||
- Print(L"console-mode (EFI var): %ld\n", config->console_mode_efivar);
|
||||
+ printf("console-mode (EFI var): %" PRIi64 "\n", config->console_mode_efivar);
|
||||
|
||||
if (!ps_continue())
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < config->entry_count; i++) {
|
||||
ConfigEntry *entry = config->entries[i];
|
||||
-
|
||||
- _cleanup_free_ char16_t *dp = NULL;
|
||||
- if (entry->device)
|
||||
- (void) device_path_to_str(DevicePathFromHandle(entry->device), &dp);
|
||||
-
|
||||
- Print(L" config entry: %" PRIuN L"/%" PRIuN L"\n", i + 1, config->entry_count);
|
||||
- ps_string(L" id: %s\n", entry->id);
|
||||
- ps_string(L" title: %s\n", entry->title);
|
||||
- ps_string(L" title show: %s\n", streq16(entry->title, entry->title_show) ? NULL : entry->title_show);
|
||||
- ps_string(L" sort key: %s\n", entry->sort_key);
|
||||
- ps_string(L" version: %s\n", entry->version);
|
||||
- ps_string(L" machine-id: %s\n", entry->machine_id);
|
||||
- ps_string(L" device: %s\n", dp);
|
||||
- ps_string(L" loader: %s\n", entry->loader);
|
||||
+ EFI_DEVICE_PATH *dp = NULL;
|
||||
+ _cleanup_free_ char16_t *dp_str = NULL;
|
||||
+
|
||||
+ if (entry->device &&
|
||||
+ BS->HandleProtocol(entry->device, &(EFI_GUID) EFI_DEVICE_PATH_PROTOCOL_GUID, (void **) &dp) ==
|
||||
+ EFI_SUCCESS)
|
||||
+ (void) device_path_to_str(dp, &dp_str);
|
||||
+
|
||||
+ printf(" config entry: %zu/%zu\n", i + 1, config->entry_count);
|
||||
+ printf(" id: %ls\n", entry->id);
|
||||
+ if (entry->title)
|
||||
+ printf(" title: %ls\n", entry->title);
|
||||
+ if (entry->title_show && !streq16(entry->title, entry->title_show))
|
||||
+ printf(" title show: %ls\n", entry->title_show);
|
||||
+ if (entry->sort_key)
|
||||
+ printf(" sort key: %ls\n", entry->sort_key);
|
||||
+ if (entry->version)
|
||||
+ printf(" version: %ls\n", entry->version);
|
||||
+ if (entry->machine_id)
|
||||
+ printf(" machine-id: %ls\n", entry->machine_id);
|
||||
+ if (dp_str)
|
||||
+ printf(" device: %ls\n", dp_str);
|
||||
+ if (entry->loader)
|
||||
+ printf(" loader: %ls\n", entry->loader);
|
||||
STRV_FOREACH(initrd, entry->initrd)
|
||||
- Print(L" initrd: %s\n", *initrd);
|
||||
- ps_string(L" devicetree: %s\n", entry->devicetree);
|
||||
- ps_string(L" options: %s\n", entry->options);
|
||||
- ps_bool(L" internal call: %s\n", !!entry->call);
|
||||
-
|
||||
- ps_bool(L"counting boots: %s\n", entry->tries_left >= 0);
|
||||
+ printf(" initrd: %ls\n", *initrd);
|
||||
+ if (entry->devicetree)
|
||||
+ printf(" devicetree: %ls\n", entry->devicetree);
|
||||
+ if (entry->options)
|
||||
+ printf(" options: %ls\n", entry->options);
|
||||
+ printf(" internal call: %ls\n", yes_no(!!entry->call));
|
||||
+
|
||||
+ printf("counting boots: %ls\n", yes_no(entry->tries_left >= 0));
|
||||
if (entry->tries_left >= 0) {
|
||||
- Print(L" tries: %u left, %u done\n", entry->tries_left, entry->tries_done);
|
||||
- Print(L" current path: %s\\%s\n", entry->path, entry->current_name);
|
||||
- Print(L" next path: %s\\%s\n", entry->path, entry->next_name);
|
||||
+ printf(" tries: %i left, %i done\n", entry->tries_left, entry->tries_done);
|
||||
+ printf(" current path: %ls\\%ls\n", entry->path, entry->current_name);
|
||||
+ printf(" next path: %ls\\%ls\n", entry->path, entry->next_name);
|
||||
}
|
||||
|
||||
if (!ps_continue())
|
||||
@@ -629,7 +647,7 @@ static bool menu_run(
|
||||
ST->ConOut->EnableCursor(ST->ConOut, false);
|
||||
|
||||
/* draw a single character to make ClearScreen work on some firmware */
|
||||
- Print(L" ");
|
||||
+ ST->ConOut->OutputString(ST->ConOut, (char16_t *) u" ");
|
||||
|
||||
err = console_set_mode(config->console_mode_efivar != CONSOLE_MODE_KEEP ?
|
||||
config->console_mode_efivar : config->console_mode);
|
||||
@@ -2715,7 +2733,7 @@ out:
|
||||
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
InitializeLib(image, sys_table);
|
||||
|
||||
- debug_hook(L"systemd-boot");
|
||||
+ debug_hook("systemd-boot");
|
||||
/* Uncomment the next line if you need to wait for debugger. */
|
||||
// debug_break();
|
||||
|
||||
diff --git a/src/boot/efi/secure-boot.c b/src/boot/efi/secure-boot.c
|
||||
index 6b6d48277e..2594c8798f 100644
|
||||
--- a/src/boot/efi/secure-boot.c
|
||||
+++ b/src/boot/efi/secure-boot.c
|
||||
@@ -44,16 +44,16 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) {
|
||||
|
||||
clear_screen(COLOR_NORMAL);
|
||||
|
||||
- Print(u"Enrolling secure boot keys from directory: %s\n");
|
||||
+ printf("Enrolling secure boot keys from directory: %ls\n", path);
|
||||
|
||||
/* Enrolling secure boot keys is safe to do in virtualized environments as there is nothing
|
||||
* we can brick there. */
|
||||
if (!in_hypervisor()) {
|
||||
- Print(u"Warning: Enrolling custom Secure Boot keys might soft-brick your machine!\n", path);
|
||||
+ printf("Warning: Enrolling custom Secure Boot keys might soft-brick your machine!\n");
|
||||
|
||||
unsigned timeout_sec = 15;
|
||||
for (;;) {
|
||||
- Print(u"\rEnrolling in %2u s, press any key to abort.", timeout_sec);
|
||||
+ printf("\rEnrolling in %2u s, press any key to abort.", timeout_sec);
|
||||
|
||||
uint64_t key;
|
||||
err = console_key_read(&key, 1000 * 1000);
|
||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
||||
index 552660eb07..69e6a0b07f 100644
|
||||
--- a/src/boot/efi/stub.c
|
||||
+++ b/src/boot/efi/stub.c
|
||||
@@ -425,7 +425,7 @@ static EFI_STATUS real_main(EFI_HANDLE image) {
|
||||
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
InitializeLib(image, sys_table);
|
||||
|
||||
- debug_hook(L"systemd-stub");
|
||||
+ debug_hook("systemd-stub");
|
||||
/* Uncomment the next line if you need to wait for debugger. */
|
||||
// debug_break();
|
||||
|
||||
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
|
||||
index e0c3b408f2..3247694014 100644
|
||||
--- a/src/boot/efi/util.h
|
||||
+++ b/src/boot/efi/util.h
|
||||
@@ -180,7 +180,7 @@ void debug_break(void);
|
||||
extern uint8_t _text, _data;
|
||||
/* Report the relocated position of text and data sections so that a debugger
|
||||
* can attach to us. See debug-sd-boot.sh for how this can be done. */
|
||||
-# define debug_hook(identity) Print(identity L"@0x%lx,0x%lx\n", POINTER_TO_PHYSICAL_ADDRESS(&_text), POINTER_TO_PHYSICAL_ADDRESS(&_data))
|
||||
+# define debug_hook(identity) printf(identity "@%p,%p\n", &_text, &_data)
|
||||
#else
|
||||
# define debug_hook(identity)
|
||||
#endif
|
1107
0688-boot-Rework-GUID-handling.patch
Normal file
1107
0688-boot-Rework-GUID-handling.patch
Normal file
File diff suppressed because it is too large
Load Diff
51
0689-efi-string-Fix-strchr-null-byte-handling.patch
Normal file
51
0689-efi-string-Fix-strchr-null-byte-handling.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 50a254def1c98a34ee5fdb52dcfbb1ed59b1250a Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Mon, 30 Jan 2023 16:22:10 +0100
|
||||
Subject: [PATCH] efi-string: Fix strchr() null byte handling
|
||||
|
||||
strchr() should be able to search for the terminating null byte,
|
||||
our implementation doesn't, let's fix that.
|
||||
|
||||
(cherry picked from commit bbef5a9617e91b4b1bc30266eb9dcbda395a8c61)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/efi-string.c | 2 +-
|
||||
src/boot/efi/test-efi-string.c | 4 ++++
|
||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c
|
||||
index 860dfc00b2..cf0d71e986 100644
|
||||
--- a/src/boot/efi/efi-string.c
|
||||
+++ b/src/boot/efi/efi-string.c
|
||||
@@ -116,7 +116,7 @@ DEFINE_STRCPY(char16_t, strcpy16);
|
||||
s++; \
|
||||
} \
|
||||
\
|
||||
- return NULL; \
|
||||
+ return c ? NULL : (type *) s; \
|
||||
}
|
||||
|
||||
DEFINE_STRCHR(char, strchr8);
|
||||
diff --git a/src/boot/efi/test-efi-string.c b/src/boot/efi/test-efi-string.c
|
||||
index c26973d8bd..c7e42c7b94 100644
|
||||
--- a/src/boot/efi/test-efi-string.c
|
||||
+++ b/src/boot/efi/test-efi-string.c
|
||||
@@ -229,6 +229,8 @@ TEST(strchr8) {
|
||||
assert_se(strchr8(str, 'a') == &str[0]);
|
||||
assert_se(strchr8(str, 'c') == &str[2]);
|
||||
assert_se(strchr8(str, 'B') == &str[4]);
|
||||
+
|
||||
+ assert_se(strchr8(str, 0) == str + strlen8(str));
|
||||
}
|
||||
|
||||
TEST(strchr16) {
|
||||
@@ -240,6 +242,8 @@ TEST(strchr16) {
|
||||
assert_se(strchr16(str, 'a') == &str[0]);
|
||||
assert_se(strchr16(str, 'c') == &str[2]);
|
||||
assert_se(strchr16(str, 'B') == &str[4]);
|
||||
+
|
||||
+ assert_se(strchr16(str, 0) == str + strlen16(str));
|
||||
}
|
||||
|
||||
TEST(xstrndup8) {
|
79
0690-efi-string-Add-startswith8.patch
Normal file
79
0690-efi-string-Add-startswith8.patch
Normal file
@ -0,0 +1,79 @@
|
||||
From 3684d9be497c5cb5164435238b970931c93b41e6 Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Mon, 30 Jan 2023 16:25:23 +0100
|
||||
Subject: [PATCH] efi-string: Add startswith8()
|
||||
|
||||
startswith() from string-util-fundamental.h is defined for sd_char
|
||||
which is char16_t, so let's add an implementation for char as well.
|
||||
|
||||
(cherry picked from commit ad36d31ea578622883c3b5297c971374096a504a)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/efi-string.c | 15 +++++++++++++++
|
||||
src/boot/efi/efi-string.h | 2 ++
|
||||
src/boot/efi/test-efi-string.c | 12 ++++++++++++
|
||||
3 files changed, 29 insertions(+)
|
||||
|
||||
diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c
|
||||
index cf0d71e986..6b84af69e6 100644
|
||||
--- a/src/boot/efi/efi-string.c
|
||||
+++ b/src/boot/efi/efi-string.c
|
||||
@@ -216,6 +216,21 @@ char16_t *xstrn8_to_16(const char *str8, size_t n) {
|
||||
return str16;
|
||||
}
|
||||
|
||||
+char *startswith8(const char *s, const char *prefix) {
|
||||
+ size_t l;
|
||||
+
|
||||
+ assert(prefix);
|
||||
+
|
||||
+ if (!s)
|
||||
+ return NULL;
|
||||
+
|
||||
+ l = strlen8(prefix);
|
||||
+ if (!strneq8(s, prefix, l))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return (char*) s + l;
|
||||
+}
|
||||
+
|
||||
static bool efi_fnmatch_prefix(const char16_t *p, const char16_t *h, const char16_t **ret_p, const char16_t **ret_h) {
|
||||
assert(p);
|
||||
assert(h);
|
||||
diff --git a/src/boot/efi/efi-string.h b/src/boot/efi/efi-string.h
|
||||
index 2a28db3593..477229bf60 100644
|
||||
--- a/src/boot/efi/efi-string.h
|
||||
+++ b/src/boot/efi/efi-string.h
|
||||
@@ -105,6 +105,8 @@ static inline char16_t *xstr8_to_16(const char *str8) {
|
||||
return xstrn8_to_16(str8, strlen8(str8));
|
||||
}
|
||||
|
||||
+char *startswith8(const char *s, const char *prefix);
|
||||
+
|
||||
bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack);
|
||||
|
||||
bool parse_number8(const char *s, uint64_t *ret_u, const char **ret_tail);
|
||||
diff --git a/src/boot/efi/test-efi-string.c b/src/boot/efi/test-efi-string.c
|
||||
index c7e42c7b94..be7f8f9b1c 100644
|
||||
--- a/src/boot/efi/test-efi-string.c
|
||||
+++ b/src/boot/efi/test-efi-string.c
|
||||
@@ -355,6 +355,18 @@ TEST(xstrn8_to_16) {
|
||||
free(s);
|
||||
}
|
||||
|
||||
+TEST(startswith8) {
|
||||
+ assert_se(streq8(startswith8("", ""), ""));
|
||||
+ assert_se(streq8(startswith8("x", ""), "x"));
|
||||
+ assert_se(!startswith8("", "x"));
|
||||
+ assert_se(!startswith8("", "xxxxxxxx"));
|
||||
+ assert_se(streq8(startswith8("xxx", "x"), "xx"));
|
||||
+ assert_se(streq8(startswith8("xxx", "xx"), "x"));
|
||||
+ assert_se(streq8(startswith8("xxx", "xxx"), ""));
|
||||
+ assert_se(!startswith8("xxx", "xxxx"));
|
||||
+ assert_se(!startswith8(NULL, ""));
|
||||
+}
|
||||
+
|
||||
#define TEST_FNMATCH_ONE(pattern, haystack, expect) \
|
||||
({ \
|
||||
assert_se(fnmatch(pattern, haystack, 0) == (expect ? 0 : FNM_NOMATCH)); \
|
93
0691-efi-string-Add-efi_memchr.patch
Normal file
93
0691-efi-string-Add-efi_memchr.patch
Normal file
@ -0,0 +1,93 @@
|
||||
From 9461c9b524c2f3bf19b86dbcda24f57acde67852 Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Tue, 31 Jan 2023 15:39:40 +0100
|
||||
Subject: [PATCH] efi-string: Add efi_memchr()
|
||||
|
||||
(cherry picked from commit e71f0f63da87fb8043f665a142261bc393fe0216)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/efi-string.c | 14 ++++++++++++++
|
||||
src/boot/efi/efi-string.h | 2 ++
|
||||
src/boot/efi/test-efi-string.c | 13 +++++++++++++
|
||||
3 files changed, 29 insertions(+)
|
||||
|
||||
diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c
|
||||
index 6b84af69e6..60b5d0f712 100644
|
||||
--- a/src/boot/efi/efi-string.c
|
||||
+++ b/src/boot/efi/efi-string.c
|
||||
@@ -886,16 +886,30 @@ char16_t *xvasprintf_status(EFI_STATUS status, const char *format, va_list ap) {
|
||||
|
||||
#if SD_BOOT
|
||||
/* To provide the actual implementation for these we need to remove the redirection to the builtins. */
|
||||
+# undef memchr
|
||||
# undef memcmp
|
||||
# undef memcpy
|
||||
# undef memset
|
||||
#else
|
||||
/* And for userspace unit testing we need to give them an efi_ prefix. */
|
||||
+# define memchr efi_memchr
|
||||
# define memcmp efi_memcmp
|
||||
# define memcpy efi_memcpy
|
||||
# define memset efi_memset
|
||||
#endif
|
||||
|
||||
+_used_ void *memchr(const void *p, int c, size_t n) {
|
||||
+ if (!p || n == 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ const uint8_t *q = p;
|
||||
+ for (size_t i = 0; i < n; i++)
|
||||
+ if (q[i] == (unsigned char) c)
|
||||
+ return (void *) (q + i);
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
_used_ int memcmp(const void *p1, const void *p2, size_t n) {
|
||||
const uint8_t *up1 = p1, *up2 = p2;
|
||||
int r;
|
||||
diff --git a/src/boot/efi/efi-string.h b/src/boot/efi/efi-string.h
|
||||
index 477229bf60..3d035d7ead 100644
|
||||
--- a/src/boot/efi/efi-string.h
|
||||
+++ b/src/boot/efi/efi-string.h
|
||||
@@ -142,6 +142,7 @@ _gnu_printf_(2, 0) _warn_unused_result_ char16_t *xvasprintf_status(EFI_STATUS s
|
||||
* compiling with -ffreestanding. By referring to builtins, the compiler can check arguments and do
|
||||
* optimizations again. Note that we still need to provide implementations as the compiler is free to not
|
||||
* inline its own implementation and instead issue a library call. */
|
||||
+# define memchr __builtin_memchr
|
||||
# define memcmp __builtin_memcmp
|
||||
# define memcpy __builtin_memcpy
|
||||
# define memset __builtin_memset
|
||||
@@ -155,6 +156,7 @@ static inline void *mempcpy(void * restrict dest, const void * restrict src, siz
|
||||
|
||||
#else
|
||||
/* For unit testing. */
|
||||
+void *efi_memchr(const void *p, int c, size_t n);
|
||||
int efi_memcmp(const void *p1, const void *p2, size_t n);
|
||||
void *efi_memcpy(void * restrict dest, const void * restrict src, size_t n);
|
||||
void *efi_memset(void *p, int c, size_t n);
|
||||
diff --git a/src/boot/efi/test-efi-string.c b/src/boot/efi/test-efi-string.c
|
||||
index be7f8f9b1c..d214b1536e 100644
|
||||
--- a/src/boot/efi/test-efi-string.c
|
||||
+++ b/src/boot/efi/test-efi-string.c
|
||||
@@ -626,6 +626,19 @@ TEST(xvasprintf_status) {
|
||||
s = mfree(s);
|
||||
}
|
||||
|
||||
+TEST(efi_memchr) {
|
||||
+ assert_se(streq8(efi_memchr("abcde", 'c', 5), "cde"));
|
||||
+ assert_se(streq8(efi_memchr("abcde", 'c', 3), "cde"));
|
||||
+ assert_se(streq8(efi_memchr("abcde", 'c', 2), NULL));
|
||||
+ assert_se(streq8(efi_memchr("abcde", 'c', 7), "cde"));
|
||||
+ assert_se(streq8(efi_memchr("abcde", 'q', 5), NULL));
|
||||
+ assert_se(streq8(efi_memchr("abcde", 'q', 0), NULL));
|
||||
+ /* Test that the character is interpreted as unsigned char. */
|
||||
+ assert_se(streq8(efi_memchr("abcde", 'a', 6), efi_memchr("abcde", 'a' + 0x100, 6)));
|
||||
+ assert_se(streq8(efi_memchr("abcde", 0, 6), ""));
|
||||
+ assert_se(efi_memchr(NULL, 0, 0) == NULL);
|
||||
+}
|
||||
+
|
||||
TEST(efi_memcmp) {
|
||||
assert_se(efi_memcmp(NULL, NULL, 0) == 0);
|
||||
assert_se(efi_memcmp(NULL, NULL, 1) == 0);
|
70
0692-vmm-Add-more-const.patch
Normal file
70
0692-vmm-Add-more-const.patch
Normal file
@ -0,0 +1,70 @@
|
||||
From 139d725cb2b293443e7b0db263401b588373a7cb Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Mon, 30 Jan 2023 21:15:12 +0100
|
||||
Subject: [PATCH] vmm: Add more const
|
||||
|
||||
SMBIOS tables are immutable, so let's access it via const pointers
|
||||
where possible.
|
||||
|
||||
(cherry picked from commit 761f62fe98cab82a3742bdae49f79626ede2ceaf)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/vmm.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c
|
||||
index 6bd440f032..6b684e1bf4 100644
|
||||
--- a/src/boot/efi/vmm.c
|
||||
+++ b/src/boot/efi/vmm.c
|
||||
@@ -201,17 +201,17 @@ typedef struct {
|
||||
uint8_t bios_characteristics_ext[2];
|
||||
} _packed_ SmbiosTableType0;
|
||||
|
||||
-static void *find_smbios_configuration_table(uint64_t *ret_size) {
|
||||
+static const void *find_smbios_configuration_table(uint64_t *ret_size) {
|
||||
assert(ret_size);
|
||||
|
||||
- Smbios3EntryPoint *entry3 = find_configuration_table(MAKE_GUID_PTR(SMBIOS3_TABLE));
|
||||
+ const Smbios3EntryPoint *entry3 = find_configuration_table(MAKE_GUID_PTR(SMBIOS3_TABLE));
|
||||
if (entry3 && memcmp(entry3->anchor_string, "_SM3_", 5) == 0 &&
|
||||
entry3->entry_point_length <= sizeof(*entry3)) {
|
||||
*ret_size = entry3->table_maximum_size;
|
||||
return PHYSICAL_ADDRESS_TO_POINTER(entry3->table_address);
|
||||
}
|
||||
|
||||
- SmbiosEntryPoint *entry = find_configuration_table(MAKE_GUID_PTR(SMBIOS_TABLE));
|
||||
+ const SmbiosEntryPoint *entry = find_configuration_table(MAKE_GUID_PTR(SMBIOS_TABLE));
|
||||
if (entry && memcmp(entry->anchor_string, "_SM_", 4) == 0 &&
|
||||
entry->entry_point_length <= sizeof(*entry)) {
|
||||
*ret_size = entry->table_length;
|
||||
@@ -221,9 +221,9 @@ static void *find_smbios_configuration_table(uint64_t *ret_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static SmbiosHeader *get_smbios_table(uint8_t type) {
|
||||
+static const SmbiosHeader *get_smbios_table(uint8_t type) {
|
||||
uint64_t size = 0;
|
||||
- uint8_t *p = find_smbios_configuration_table(&size);
|
||||
+ const uint8_t *p = find_smbios_configuration_table(&size);
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
@@ -231,7 +231,7 @@ static SmbiosHeader *get_smbios_table(uint8_t type) {
|
||||
if (size < sizeof(SmbiosHeader))
|
||||
return NULL;
|
||||
|
||||
- SmbiosHeader *header = (SmbiosHeader *) p;
|
||||
+ const SmbiosHeader *header = (const SmbiosHeader *) p;
|
||||
|
||||
/* End of table. */
|
||||
if (header->type == 127)
|
||||
@@ -273,7 +273,7 @@ static SmbiosHeader *get_smbios_table(uint8_t type) {
|
||||
|
||||
static bool smbios_in_hypervisor(void) {
|
||||
/* Look up BIOS Information (Type 0). */
|
||||
- SmbiosTableType0 *type0 = (SmbiosTableType0 *) get_smbios_table(0);
|
||||
+ const SmbiosTableType0 *type0 = (const SmbiosTableType0 *) get_smbios_table(0);
|
||||
if (!type0 || type0->header.length < sizeof(SmbiosTableType0))
|
||||
return false;
|
||||
|
107
0693-vmm-Add-smbios_find_oem_string.patch
Normal file
107
0693-vmm-Add-smbios_find_oem_string.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From c7c166f2dd636418bfa25ea9c69ebfc45c618d8f Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Mon, 30 Jan 2023 16:26:14 +0100
|
||||
Subject: [PATCH] vmm: Add smbios_find_oem_string()
|
||||
|
||||
This function can be used to find SMBIOS strings in the SMBIOS Type 11
|
||||
table.
|
||||
|
||||
(cherry picked from commit a885188b3ab71c222cbcc42b083ba671884aa651)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/vmm.c | 44 +++++++++++++++++++++++++++++++++++++++++---
|
||||
src/boot/efi/vmm.h | 2 ++
|
||||
2 files changed, 43 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c
|
||||
index 6b684e1bf4..19b66a3974 100644
|
||||
--- a/src/boot/efi/vmm.c
|
||||
+++ b/src/boot/efi/vmm.c
|
||||
@@ -201,6 +201,12 @@ typedef struct {
|
||||
uint8_t bios_characteristics_ext[2];
|
||||
} _packed_ SmbiosTableType0;
|
||||
|
||||
+typedef struct {
|
||||
+ SmbiosHeader header;
|
||||
+ uint8_t count;
|
||||
+ char contents[];
|
||||
+} _packed_ SmbiosTableType11;
|
||||
+
|
||||
static const void *find_smbios_configuration_table(uint64_t *ret_size) {
|
||||
assert(ret_size);
|
||||
|
||||
@@ -221,7 +227,7 @@ static const void *find_smbios_configuration_table(uint64_t *ret_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static const SmbiosHeader *get_smbios_table(uint8_t type) {
|
||||
+static const SmbiosHeader *get_smbios_table(uint8_t type, uint64_t *ret_size_left) {
|
||||
uint64_t size = 0;
|
||||
const uint8_t *p = find_smbios_configuration_table(&size);
|
||||
if (!p)
|
||||
@@ -240,8 +246,11 @@ static const SmbiosHeader *get_smbios_table(uint8_t type) {
|
||||
if (size < header->length)
|
||||
return NULL;
|
||||
|
||||
- if (header->type == type)
|
||||
+ if (header->type == type) {
|
||||
+ if (ret_size_left)
|
||||
+ *ret_size_left = size;
|
||||
return header; /* Yay! */
|
||||
+ }
|
||||
|
||||
/* Skip over formatted area. */
|
||||
size -= header->length;
|
||||
@@ -273,7 +282,7 @@ static const SmbiosHeader *get_smbios_table(uint8_t type) {
|
||||
|
||||
static bool smbios_in_hypervisor(void) {
|
||||
/* Look up BIOS Information (Type 0). */
|
||||
- const SmbiosTableType0 *type0 = (const SmbiosTableType0 *) get_smbios_table(0);
|
||||
+ const SmbiosTableType0 *type0 = (const SmbiosTableType0 *) get_smbios_table(0, NULL);
|
||||
if (!type0 || type0->header.length < sizeof(SmbiosTableType0))
|
||||
return false;
|
||||
|
||||
@@ -289,3 +298,32 @@ bool in_hypervisor(void) {
|
||||
cache = cpuid_in_hypervisor() || smbios_in_hypervisor();
|
||||
return cache;
|
||||
}
|
||||
+
|
||||
+const char* smbios_find_oem_string(const char *name) {
|
||||
+ uint64_t left;
|
||||
+
|
||||
+ assert(name);
|
||||
+
|
||||
+ const SmbiosTableType11 *type11 = (const SmbiosTableType11 *) get_smbios_table(11, &left);
|
||||
+ if (!type11 || type11->header.length < sizeof(SmbiosTableType11))
|
||||
+ return NULL;
|
||||
+
|
||||
+ assert(left >= type11->header.length);
|
||||
+
|
||||
+ const char *s = type11->contents;
|
||||
+ left -= type11->header.length;
|
||||
+
|
||||
+ for (const char *p = s; p < s + left; ) {
|
||||
+ const char *e = memchr(p, 0, s + left - p);
|
||||
+ if (!e || e == p) /* Double NUL byte means we've reached the end of the OEM strings. */
|
||||
+ break;
|
||||
+
|
||||
+ const char *eq = startswith8(p, name);
|
||||
+ if (eq && *eq == '=')
|
||||
+ return eq + 1;
|
||||
+
|
||||
+ p = e + 1;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
diff --git a/src/boot/efi/vmm.h b/src/boot/efi/vmm.h
|
||||
index e98ec74af1..2002f32bec 100644
|
||||
--- a/src/boot/efi/vmm.h
|
||||
+++ b/src/boot/efi/vmm.h
|
||||
@@ -8,3 +8,5 @@ bool is_direct_boot(EFI_HANDLE device);
|
||||
EFI_STATUS vmm_open(EFI_HANDLE *ret_qemu_dev, EFI_FILE **ret_qemu_dir);
|
||||
|
||||
bool in_hypervisor(void);
|
||||
+
|
||||
+const char* smbios_find_oem_string(const char *name);
|
@ -0,0 +1,71 @@
|
||||
From dc742ee6411f4f7bd5d447cd29dc17a0025843e0 Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Mon, 30 Jan 2023 16:26:50 +0100
|
||||
Subject: [PATCH] stub: Read extra kernel command line items from SMBIOS
|
||||
|
||||
Let's read more kernel command line arguments from SMBIOS OEM string
|
||||
io.systemd.stub.kernel-cmdline-extra. This allows adding debug kernel
|
||||
command line arguments when booting in qemy without having to modify
|
||||
the UKI.
|
||||
|
||||
(cherry picked from commit 717af0de4648ccc223f06683a6baf73d64271e02)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
man/systemd-stub.xml | 17 +++++++++++++++++
|
||||
src/boot/efi/stub.c | 7 +++++++
|
||||
2 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/man/systemd-stub.xml b/man/systemd-stub.xml
|
||||
index 85d30129d6..66c158c44d 100644
|
||||
--- a/man/systemd-stub.xml
|
||||
+++ b/man/systemd-stub.xml
|
||||
@@ -382,6 +382,23 @@
|
||||
default, this is done for the TPM2 PCR signature and public key files.</para>
|
||||
</refsect1>
|
||||
|
||||
+ <refsect1>
|
||||
+ <title>SMBIOS Type 11 Strings</title>
|
||||
+
|
||||
+ <para><command>systemd-stub</command> can be configured using SMBIOS Type 11 strings. Applicable strings
|
||||
+ consist of a name, followed by <literal>=</literal>, followed by the value.
|
||||
+ <command>systemd-stub</command> will search the table for a string with a specific name, and if found,
|
||||
+ use its value. The following strings are read:</para>
|
||||
+
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><varname>io.systemd.stub.kernel-cmdline-extra</varname></term>
|
||||
+ <listitem><para>If set, the value of this string is added to the list of kernel command line
|
||||
+ arguments that are passed to the kernel.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
<refsect1>
|
||||
<title>Assembling Kernel Images</title>
|
||||
|
||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
||||
index dac1bb0606..86eae2e350 100644
|
||||
--- a/src/boot/efi/stub.c
|
||||
+++ b/src/boot/efi/stub.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "splash.h"
|
||||
#include "tpm-pcr.h"
|
||||
#include "util.h"
|
||||
+#include "vmm.h"
|
||||
|
||||
/* magic string to find in the binary image */
|
||||
_used_ _section_(".sdmagic") static const char magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####";
|
||||
@@ -277,6 +278,12 @@ static EFI_STATUS real_main(EFI_HANDLE image) {
|
||||
mangle_stub_cmdline(cmdline);
|
||||
}
|
||||
|
||||
+ const char *extra = smbios_find_oem_string("io.systemd.stub.kernel-cmdline-extra");
|
||||
+ if (extra) {
|
||||
+ _cleanup_free_ char16_t *tmp = TAKE_PTR(cmdline), *extra16 = xstr8_to_16(extra);
|
||||
+ cmdline = xasprintf("%ls %ls", tmp, extra16);
|
||||
+ }
|
||||
+
|
||||
export_variables(loaded_image);
|
||||
|
||||
if (pack_cpio(loaded_image,
|
46
0695-vmm-Modernize-get_smbios_table.patch
Normal file
46
0695-vmm-Modernize-get_smbios_table.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 47fd30b95f506beaef5640ad61b40b180c7ac47b Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Wed, 22 Feb 2023 17:04:58 +0100
|
||||
Subject: [PATCH] vmm: Modernize get_smbios_table()
|
||||
|
||||
(cherry picked from commit c8e5d82c97a1478b15d2f97ffebd9591e81663ba)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/vmm.c | 18 +++++++-----------
|
||||
1 file changed, 7 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c
|
||||
index 19b66a3974..f9a59dca0a 100644
|
||||
--- a/src/boot/efi/vmm.c
|
||||
+++ b/src/boot/efi/vmm.c
|
||||
@@ -258,22 +258,18 @@ static const SmbiosHeader *get_smbios_table(uint8_t type, uint64_t *ret_size_lef
|
||||
|
||||
/* Skip over string table. */
|
||||
for (;;) {
|
||||
- while (size > 0 && *p != '\0') {
|
||||
- p++;
|
||||
- size--;
|
||||
- }
|
||||
- if (size == 0)
|
||||
+ const uint8_t *e = memchr(p, 0, size);
|
||||
+ if (!e)
|
||||
return NULL;
|
||||
- p++;
|
||||
- size--;
|
||||
|
||||
- /* Double NUL terminates string table. */
|
||||
- if (*p == '\0') {
|
||||
- if (size == 0)
|
||||
- return NULL;
|
||||
+ if (e == p) {/* Double NUL byte means we've reached the end of the string table. */
|
||||
p++;
|
||||
+ size--;
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ size -= e + 1 - p;
|
||||
+ p = e + 1;
|
||||
}
|
||||
}
|
||||
|
59
0696-stub-measure-SMBIOS-kernel-cmdline-extra-in-PCR12.patch
Normal file
59
0696-stub-measure-SMBIOS-kernel-cmdline-extra-in-PCR12.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From ee8090db1c2fe4df29fd0b134d80791eced6434d Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Sun, 21 May 2023 15:18:21 +0100
|
||||
Subject: [PATCH] stub: measure SMBIOS kernel-cmdline-extra in PCR12
|
||||
|
||||
PCR1, where SMBIOS strings are measured, is filled with data that is not
|
||||
under the control of the machine owner. Measure cmdline extensions in
|
||||
PCR12 too, where we measure other optional addons that are loaded by
|
||||
sd-stub.
|
||||
|
||||
(cherry picked from commit 2c90b5ec63ab420d074ebe4f5c6881737c9bc155)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
man/systemd-stub.xml | 5 ++++-
|
||||
src/boot/efi/stub.c | 7 +++++++
|
||||
2 files changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/man/systemd-stub.xml b/man/systemd-stub.xml
|
||||
index 66c158c44d..edfc299bc2 100644
|
||||
--- a/man/systemd-stub.xml
|
||||
+++ b/man/systemd-stub.xml
|
||||
@@ -66,6 +66,9 @@
|
||||
<listitem><para>A compiled binary DeviceTree will be looked for in the <literal>.dtb</literal> PE
|
||||
section.</para></listitem>
|
||||
|
||||
+ <listitem><para>Kernel version information, i.e. the output of <command>uname -r</command> for the
|
||||
+ kernel included in the UKI, in the <literal>.uname</literal> PE section.</para></listitem>
|
||||
+
|
||||
<listitem><para>The kernel command line to pass to the invoked kernel will be looked for in the
|
||||
<literal>.cmdline</literal> PE section.</para></listitem>
|
||||
|
||||
@@ -394,7 +397,7 @@
|
||||
<varlistentry>
|
||||
<term><varname>io.systemd.stub.kernel-cmdline-extra</varname></term>
|
||||
<listitem><para>If set, the value of this string is added to the list of kernel command line
|
||||
- arguments that are passed to the kernel.</para></listitem>
|
||||
+ arguments that are measured in PCR12 and passed to the kernel.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
||||
index 86eae2e350..a195612f0e 100644
|
||||
--- a/src/boot/efi/stub.c
|
||||
+++ b/src/boot/efi/stub.c
|
||||
@@ -282,6 +282,13 @@ static EFI_STATUS real_main(EFI_HANDLE image) {
|
||||
if (extra) {
|
||||
_cleanup_free_ char16_t *tmp = TAKE_PTR(cmdline), *extra16 = xstr8_to_16(extra);
|
||||
cmdline = xasprintf("%ls %ls", tmp, extra16);
|
||||
+
|
||||
+ /* SMBIOS strings are measured in PCR1, but we also want to measure them in our specific
|
||||
+ * PCR12, as firmware-owned PCRs are very difficult to use as they'll contain unpredictable
|
||||
+ * measurements that are not under control of the machine owner. */
|
||||
+ m = false;
|
||||
+ (void) tpm_log_load_options(extra16, &m);
|
||||
+ parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m);
|
||||
}
|
||||
|
||||
export_variables(loaded_image);
|
@ -0,0 +1,28 @@
|
||||
From 3a31a48e1bda8d8799695a878a872fd30d5c3e45 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Fri, 12 May 2023 00:49:57 +0100
|
||||
Subject: [PATCH] efi: support passing empty cmdline to mangle_stub_cmdline()
|
||||
|
||||
Just return instead of crashing
|
||||
|
||||
(cherry picked from commit e715d82de6694d82a17921b5ccbcf47398604068)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/util.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
|
||||
index bd821a5afb..b8befb4b0c 100644
|
||||
--- a/src/boot/efi/util.c
|
||||
+++ b/src/boot/efi/util.c
|
||||
@@ -272,6 +272,9 @@ char16_t *xstr8_to_path(const char *str8) {
|
||||
}
|
||||
|
||||
void mangle_stub_cmdline(char16_t *cmdline) {
|
||||
+ if (!cmdline)
|
||||
+ return;
|
||||
+
|
||||
for (; *cmdline != '\0'; cmdline++)
|
||||
/* Convert ASCII control characters to spaces. */
|
||||
if (*cmdline <= 0x1F)
|
@ -0,0 +1,61 @@
|
||||
From d0e7305306407992bebbf6785a03cf2062d8359b Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Fri, 12 May 2023 00:51:19 +0100
|
||||
Subject: [PATCH] efi: set EFIVAR to stop Shim from uninstalling its protocol
|
||||
|
||||
We'll use it from the stub to validate files. Requires Shim 5.18.
|
||||
By default, Shim uninstalls its protocol when calling StartImage(),
|
||||
so when loading systemd-boot via shim and then loading an UKI, the
|
||||
UKI's sd-stub will no longer be able to use the shim verification
|
||||
protocol by default.
|
||||
|
||||
(cherry picked from commit e1f1b5fc62f721a3a4c14d97ad01447b2ac07d6d)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/boot.c | 4 ++++
|
||||
src/boot/efi/shim.c | 9 +++++++++
|
||||
src/boot/efi/shim.h | 1 +
|
||||
3 files changed, 14 insertions(+)
|
||||
|
||||
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
|
||||
index d859ffe0b8..5a9bfc9646 100644
|
||||
--- a/src/boot/efi/boot.c
|
||||
+++ b/src/boot/efi/boot.c
|
||||
@@ -2644,6 +2644,10 @@ static EFI_STATUS real_main(EFI_HANDLE image) {
|
||||
|
||||
init_usec = time_usec();
|
||||
|
||||
+ /* Ask Shim to leave its protocol around, so that the stub can use it to validate PEs.
|
||||
+ * By default, Shim uninstalls its protocol when calling StartImage(). */
|
||||
+ shim_retain_protocol();
|
||||
+
|
||||
err = BS->OpenProtocol(
|
||||
image,
|
||||
MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL),
|
||||
diff --git a/src/boot/efi/shim.c b/src/boot/efi/shim.c
|
||||
index 5da298c10a..d2fd680bbc 100644
|
||||
--- a/src/boot/efi/shim.c
|
||||
+++ b/src/boot/efi/shim.c
|
||||
@@ -100,3 +100,12 @@ EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path
|
||||
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+void shim_retain_protocol(void) {
|
||||
+ uint8_t value = 1;
|
||||
+
|
||||
+ /* Ask Shim to avoid uninstalling its security protocol, so that we can use it from sd-stub to
|
||||
+ * validate PE addons. By default, Shim uninstalls its protocol when calling StartImage().
|
||||
+ * Requires Shim 15.8. */
|
||||
+ (void) efivar_set_raw(MAKE_GUID_PTR(SHIM_LOCK), u"ShimRetainProtocol", &value, sizeof(value), 0);
|
||||
+}
|
||||
diff --git a/src/boot/efi/shim.h b/src/boot/efi/shim.h
|
||||
index 6d213f5efa..23fdc0923f 100644
|
||||
--- a/src/boot/efi/shim.h
|
||||
+++ b/src/boot/efi/shim.h
|
||||
@@ -14,3 +14,4 @@
|
||||
|
||||
bool shim_loaded(void);
|
||||
EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path, EFI_HANDLE *ret_image);
|
||||
+void shim_retain_protocol(void);
|
78
0699-ukify-use-empty-stub-for-addons.patch
Normal file
78
0699-ukify-use-empty-stub-for-addons.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 7307ab86351846cb750f3fcd35db7d9de9aefdf0 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Tue, 23 May 2023 01:45:40 +0100
|
||||
Subject: [PATCH] ukify: use empty stub for addons
|
||||
|
||||
Instead of picking up sd-stub, which is runnable, add an empty
|
||||
addon stub that just returns an error if executed
|
||||
|
||||
(cherry picked from commit f644ea3ed7ec22c28814b194e4e5bbbf2fa98560)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
src/boot/efi/addon.c | 15 +++++++++++++++
|
||||
src/boot/efi/meson.build | 13 ++++++++++---
|
||||
2 files changed, 25 insertions(+), 3 deletions(-)
|
||||
create mode 100644 src/boot/efi/addon.c
|
||||
|
||||
diff --git a/src/boot/efi/addon.c b/src/boot/efi/addon.c
|
||||
new file mode 100644
|
||||
index 0000000000..959e54b5cc
|
||||
--- /dev/null
|
||||
+++ b/src/boot/efi/addon.c
|
||||
@@ -0,0 +1,15 @@
|
||||
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
+
|
||||
+#include "efi.h"
|
||||
+#include "macro-fundamental.h"
|
||||
+
|
||||
+/* Magic string for recognizing our own binaries */
|
||||
+_used_ _section_(".sdmagic") static const char magic[] =
|
||||
+ "#### LoaderInfo: systemd-addon " GIT_VERSION " ####";
|
||||
+
|
||||
+/* This is intended to carry data, not to be executed */
|
||||
+
|
||||
+EFIAPI EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *system_table);
|
||||
+EFIAPI EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *system_table) {
|
||||
+ return EFI_UNSUPPORTED;
|
||||
+}
|
||||
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
|
||||
index 09c40a280b..9e5d535b5b 100644
|
||||
--- a/src/boot/efi/meson.build
|
||||
+++ b/src/boot/efi/meson.build
|
||||
@@ -403,6 +403,8 @@ stub_sources = files(
|
||||
'stub.c',
|
||||
)
|
||||
|
||||
+addon_sources = files('addon.c')
|
||||
+
|
||||
if efi_arch[1] in ['ia32', 'x86_64']
|
||||
stub_sources += files('linux_x86.c')
|
||||
endif
|
||||
@@ -430,7 +432,8 @@ endif
|
||||
|
||||
systemd_boot_objects = []
|
||||
stub_objects = []
|
||||
-foreach file : fundamental_source_paths + common_sources + systemd_boot_sources + stub_sources
|
||||
+addon_objects = []
|
||||
+foreach file : fundamental_source_paths + common_sources + systemd_boot_sources + stub_sources + addon_sources
|
||||
# FIXME: replace ''.format(file) with fs.name(file) when meson_version requirement is >= 0.59.0
|
||||
o_file = custom_target('@0@.o'.format(file).split('/')[-1],
|
||||
input : file,
|
||||
@@ -443,10 +446,14 @@ foreach file : fundamental_source_paths + common_sources + systemd_boot_sources
|
||||
if (fundamental_source_paths + common_sources + stub_sources).contains(file)
|
||||
stub_objects += o_file
|
||||
endif
|
||||
+ if (fundamental_source_paths + common_sources + addon_sources).contains(file)
|
||||
+ addon_objects += o_file
|
||||
+ endif
|
||||
endforeach
|
||||
|
||||
-foreach tuple : [['systemd-boot@0@.@1@', systemd_boot_objects, false, 'systemd-boot'],
|
||||
- ['linux@0@.@1@.stub', stub_objects, true, 'systemd-stub']]
|
||||
+foreach tuple : [['systemd-boot@0@.@1@', systemd_boot_objects, false, 'systemd-boot',],
|
||||
+ ['linux@0@.@1@.stub', stub_objects, true, 'systemd-stub'],
|
||||
+ ['addon@0@.@1@.stub', addon_objects, true, 'addon']]
|
||||
elf = custom_target(
|
||||
tuple[0].format(efi_arch[0], 'elf'),
|
||||
input : tuple[1],
|
389
0700-stub-allow-loading-and-verifying-cmdline-addons.patch
Normal file
389
0700-stub-allow-loading-and-verifying-cmdline-addons.patch
Normal file
@ -0,0 +1,389 @@
|
||||
From 2f2729382327bde136559a0d0ac15740d76108f9 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Fri, 12 May 2023 00:55:58 +0100
|
||||
Subject: [PATCH] stub: allow loading and verifying cmdline addons
|
||||
|
||||
Files placed in /EFI/Linux/UKI.efi.extra.d/ and /loader/addons/ are
|
||||
opened and verified using the LoadImage protocol, and will thus get
|
||||
verified via shim/firmware.
|
||||
If they are valid signed PE files, the .cmdline section will be
|
||||
extracted and appended. If there are multiple addons in each directory,
|
||||
they will be parsed in alphanumerical order.
|
||||
|
||||
Optionally the .uname sections are also matched if present, so
|
||||
that they can be used to filter out addons as well if needed, and only
|
||||
addons that correspond exactly to the UKI being loaded are used.
|
||||
It is recommended to also always add a .sbat section to addons, so
|
||||
that they can be mass-revoked with just a policy update.
|
||||
|
||||
The files must have a .addon.efi suffix.
|
||||
|
||||
Files in the per-UKI directory are parsed, sorted, measured and
|
||||
appended first. Then, files in the generic directory are processed.
|
||||
|
||||
(cherry picked from commit 05c9f9c2517c54b98d55f08f8afa67c79be861e8)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
man/systemd-stub.xml | 32 ++++++
|
||||
src/boot/efi/cpio.c | 2 +-
|
||||
src/boot/efi/cpio.h | 2 +
|
||||
src/boot/efi/meson.build | 2 +-
|
||||
src/boot/efi/stub.c | 216 +++++++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 252 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/man/systemd-stub.xml b/man/systemd-stub.xml
|
||||
index edfc299bc2..21035cc944 100644
|
||||
--- a/man/systemd-stub.xml
|
||||
+++ b/man/systemd-stub.xml
|
||||
@@ -28,8 +28,10 @@
|
||||
<para><filename>/usr/lib/systemd/boot/efi/linuxx64.efi.stub</filename></para>
|
||||
<para><filename>/usr/lib/systemd/boot/efi/linuxia32.efi.stub</filename></para>
|
||||
<para><filename>/usr/lib/systemd/boot/efi/linuxaa64.efi.stub</filename></para>
|
||||
+ <para><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.addon.efi</filename></para>
|
||||
<para><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.cred</filename></para>
|
||||
<para><filename><replaceable>ESP</replaceable>/.../<replaceable>foo</replaceable>.efi.extra.d/*.raw</filename></para>
|
||||
+ <para><filename><replaceable>ESP</replaceable>/loader/addons/*.addon.efi</filename></para>
|
||||
<para><filename><replaceable>ESP</replaceable>/loader/credentials/*.cred</filename></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -148,11 +150,41 @@
|
||||
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>
|
||||
|
||||
+ <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.
|
||||
+ In case Secure Boot is enabled, these files will be validated using keys in UEFI DB, Shim's DB or
|
||||
+ Shim's MOK, and will be rejected otherwise. Additionally, if the both the addon and the UKI contain a
|
||||
+ a <literal>.uname</literal> section, the addon will be rejected if they do not exactly match. It is
|
||||
+ recommended to always add a <literal>.sbat</literal> section to all signed addons, so that they may be
|
||||
+ revoked with a SBAT policy update, without requiring blocklisting via DBX/MOKX. The
|
||||
+ <citerefentry><refentrytitle>ukify</refentrytitle><manvolnum>1</manvolnum></citerefentry> tool will
|
||||
+ add a SBAT policy by default if none is passed when building addons. For more information on SBAT see
|
||||
+ <ulink url="https://github.com/rhboot/shim/blob/main/SBAT.md">Shim's documentation.</ulink>
|
||||
+ Addons are supposed to be used to pass additional kernel command line parameters, regardless of the
|
||||
+ kernel image being booted, for example to allow platform vendors to ship platform-specific
|
||||
+ configuration. The loaded command line addon files are sorted, loaded, measured into TPM PCR 12 (if a
|
||||
+ TPM is present) and appended to the kernel command line. UKI command line options are listed first,
|
||||
+ then options from addons in <filename>/loader/addons/*.addon.efi</filename> are appended next, and
|
||||
+ finally UKI-specific addons are appended last. Addons are always loaded in the same order based on the
|
||||
+ filename, so that, given the same set of addons, the same set of measurements can be expected in
|
||||
+ PCR12, however note that the filename is not protected by the PE signature, and as such an attacker
|
||||
+ with write access to the ESP could potentially rename these files to change the order in which they
|
||||
+ are loaded, in a way that could alter the functionality of the kernel, as some options might be order
|
||||
+ dependent. If you sign such addons, you should pay attention to the PCR12 values and make use of an
|
||||
+ attestation service so that improper use of your signed addons can be detected and dealt with using
|
||||
+ one of the aforementioned revocation mechanisms.</para></listitem>
|
||||
+
|
||||
<listitem><para>Files <filename>/loader/credentials/*.cred</filename> are packed up in a
|
||||
<command>cpio</command> archive and placed in the <filename>/.extra/global_credentials/</filename>
|
||||
directory of the initrd file hierarchy. This is supposed to be used to pass additional credentials to
|
||||
the initrd, regardless of the kernel being booted. The generated <command>cpio</command> archive is
|
||||
measured into TPM PCR 12 (if a TPM is present)</para></listitem>
|
||||
+
|
||||
+ <listitem><para>Additionally, files <filename>/loader/addons/*.addon.efi</filename> are loaded and
|
||||
+ verified as PE binaries, and a <literal>.cmdline</literal> section is parsed from them. This is
|
||||
+ supposed to be used to pass additional command line parameters to the kernel, regardless of the kernel
|
||||
+ being booted.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>These mechanisms may be used to parameterize and extend trusted (i.e. signed), immutable initrd
|
||||
diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c
|
||||
index 0d95d40183..741c11f7ae 100644
|
||||
--- a/src/boot/efi/cpio.c
|
||||
+++ b/src/boot/efi/cpio.c
|
||||
@@ -341,7 +341,7 @@ static EFI_STATUS measure_cpio(
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
-static char16_t *get_dropin_dir(const EFI_DEVICE_PATH *file_path) {
|
||||
+char16_t *get_dropin_dir(const EFI_DEVICE_PATH *file_path) {
|
||||
if (!file_path)
|
||||
return NULL;
|
||||
|
||||
diff --git a/src/boot/efi/cpio.h b/src/boot/efi/cpio.h
|
||||
index e80e06723c..0f14edbf5f 100644
|
||||
--- a/src/boot/efi/cpio.h
|
||||
+++ b/src/boot/efi/cpio.h
|
||||
@@ -32,3 +32,5 @@ EFI_STATUS pack_cpio_literal(
|
||||
void **ret_buffer,
|
||||
size_t *ret_buffer_size,
|
||||
bool *ret_measured);
|
||||
+
|
||||
+char16_t *get_dropin_dir(const EFI_DEVICE_PATH *file_path);
|
||||
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
|
||||
index 9e5d535b5b..b84ceb8c9f 100644
|
||||
--- a/src/boot/efi/meson.build
|
||||
+++ b/src/boot/efi/meson.build
|
||||
@@ -386,6 +386,7 @@ common_sources = files(
|
||||
'pe.c',
|
||||
'random-seed.c',
|
||||
'secure-boot.c',
|
||||
+ 'shim.c',
|
||||
'ticks.c',
|
||||
'util.c',
|
||||
'vmm.c',
|
||||
@@ -393,7 +394,6 @@ common_sources = files(
|
||||
|
||||
systemd_boot_sources = files(
|
||||
'boot.c',
|
||||
- 'shim.c',
|
||||
)
|
||||
|
||||
stub_sources = files(
|
||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
||||
index a195612f0e..2c7c56de3e 100644
|
||||
--- a/src/boot/efi/stub.c
|
||||
+++ b/src/boot/efi/stub.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "pe.h"
|
||||
#include "random-seed.h"
|
||||
#include "secure-boot.h"
|
||||
+#include "shim.h"
|
||||
#include "splash.h"
|
||||
#include "tpm-pcr.h"
|
||||
#include "util.h"
|
||||
@@ -181,6 +182,189 @@ static bool use_load_options(
|
||||
return true;
|
||||
}
|
||||
|
||||
+static EFI_STATUS load_addons_from_dir(
|
||||
+ EFI_FILE *root,
|
||||
+ const char16_t *prefix,
|
||||
+ char16_t ***items,
|
||||
+ size_t *n_items,
|
||||
+ size_t *n_allocated) {
|
||||
+
|
||||
+ _cleanup_(file_closep) EFI_FILE *extra_dir = NULL;
|
||||
+ _cleanup_free_ EFI_FILE_INFO *dirent = NULL;
|
||||
+ size_t dirent_size = 0;
|
||||
+ EFI_STATUS err;
|
||||
+
|
||||
+ assert(root);
|
||||
+ assert(prefix);
|
||||
+ assert(items);
|
||||
+ assert(n_items);
|
||||
+ assert(n_allocated);
|
||||
+
|
||||
+ err = open_directory(root, prefix, &extra_dir);
|
||||
+ if (err == EFI_NOT_FOUND)
|
||||
+ /* No extra subdir, that's totally OK */
|
||||
+ return EFI_SUCCESS;
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status(err, "Failed to open addons directory '%ls': %m", prefix);
|
||||
+
|
||||
+ for (;;) {
|
||||
+ _cleanup_free_ char16_t *d = NULL;
|
||||
+
|
||||
+ err = readdir_harder(extra_dir, &dirent, &dirent_size);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status(err, "Failed to read addons directory of loaded image: %m");
|
||||
+ if (!dirent) /* End of directory */
|
||||
+ break;
|
||||
+
|
||||
+ if (dirent->FileName[0] == '.')
|
||||
+ continue;
|
||||
+ if (FLAGS_SET(dirent->Attribute, EFI_FILE_DIRECTORY))
|
||||
+ continue;
|
||||
+ if (!is_ascii(dirent->FileName))
|
||||
+ continue;
|
||||
+ if (strlen16(dirent->FileName) > 255) /* Max filename size on Linux */
|
||||
+ continue;
|
||||
+ if (!endswith_no_case(dirent->FileName, u".addon.efi"))
|
||||
+ continue;
|
||||
+
|
||||
+ d = xstrdup16(dirent->FileName);
|
||||
+
|
||||
+ if (*n_items + 2 > *n_allocated) {
|
||||
+ /* We allocate 16 entries at a time, as a matter of optimization */
|
||||
+ if (*n_items > (SIZE_MAX / sizeof(uint16_t)) - 16) /* Overflow check, just in case */
|
||||
+ return log_oom();
|
||||
+
|
||||
+ size_t m = *n_items + 16;
|
||||
+ *items = xrealloc(*items, *n_allocated * sizeof(uint16_t *), m * sizeof(uint16_t *));
|
||||
+ *n_allocated = m;
|
||||
+ }
|
||||
+
|
||||
+ (*items)[(*n_items)++] = TAKE_PTR(d);
|
||||
+ (*items)[*n_items] = NULL; /* Let's always NUL terminate, to make freeing via strv_free() easy */
|
||||
+ }
|
||||
+
|
||||
+ return EFI_SUCCESS;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static EFI_STATUS cmdline_append_and_measure_addons(
|
||||
+ EFI_HANDLE stub_image,
|
||||
+ EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
|
||||
+ const char16_t *prefix,
|
||||
+ const char *uname,
|
||||
+ bool *ret_parameters_measured,
|
||||
+ char16_t **cmdline_append) {
|
||||
+
|
||||
+ _cleanup_(strv_freep) char16_t **items = NULL;
|
||||
+ _cleanup_(file_closep) EFI_FILE *root = NULL;
|
||||
+ _cleanup_free_ char16_t *buffer = NULL;
|
||||
+ size_t n_items = 0, n_allocated = 0;
|
||||
+ EFI_STATUS err;
|
||||
+
|
||||
+ assert(stub_image);
|
||||
+ assert(loaded_image);
|
||||
+ assert(prefix);
|
||||
+ assert(ret_parameters_measured);
|
||||
+ assert(cmdline_append);
|
||||
+
|
||||
+ if (!loaded_image->DeviceHandle)
|
||||
+ return EFI_SUCCESS;
|
||||
+
|
||||
+ err = open_volume(loaded_image->DeviceHandle, &root);
|
||||
+ if (err == EFI_UNSUPPORTED)
|
||||
+ /* Error will be unsupported if the bootloader doesn't implement the file system protocol on
|
||||
+ * its file handles. */
|
||||
+ return EFI_SUCCESS;
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status(err, "Unable to open root directory: %m");
|
||||
+
|
||||
+ err = load_addons_from_dir(root, prefix, &items, &n_items, &n_allocated);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return err;
|
||||
+
|
||||
+ if (n_items == 0)
|
||||
+ return EFI_SUCCESS; /* Empty directory */
|
||||
+
|
||||
+ /* Now, sort the files we found, to make this uniform and stable (and to ensure the TPM measurements
|
||||
+ * are not dependent on read order) */
|
||||
+ sort_pointer_array((void**) items, n_items, (compare_pointer_func_t) strcmp16);
|
||||
+
|
||||
+ for (size_t i = 0; i < n_items; i++) {
|
||||
+ size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {};
|
||||
+ _cleanup_free_ EFI_DEVICE_PATH *addon_path = NULL;
|
||||
+ _cleanup_(unload_imagep) EFI_HANDLE addon = NULL;
|
||||
+ EFI_LOADED_IMAGE_PROTOCOL *loaded_addon = NULL;
|
||||
+ _cleanup_free_ char16_t *addon_spath = NULL;
|
||||
+
|
||||
+ addon_spath = xasprintf("%ls\\%ls", prefix, items[i]);
|
||||
+ err = make_file_device_path(loaded_image->DeviceHandle, addon_spath, &addon_path);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status(err, "Error making device path for %ls: %m", addon_spath);
|
||||
+
|
||||
+ /* By using shim_load_image, we cover both the case where the PE files are signed with MoK
|
||||
+ * and with DB, and running with or without shim. */
|
||||
+ err = shim_load_image(stub_image, addon_path, &addon);
|
||||
+ if (err != EFI_SUCCESS) {
|
||||
+ log_error_status(err,
|
||||
+ "Failed to read '%ls' from '%ls', ignoring: %m",
|
||||
+ items[i],
|
||||
+ addon_spath);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ err = BS->HandleProtocol(addon,
|
||||
+ MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL),
|
||||
+ (void **) &loaded_addon);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ return log_error_status(err, "Failed to find protocol in %ls: %m", items[i]);
|
||||
+
|
||||
+ err = pe_memory_locate_sections(loaded_addon->ImageBase, unified_sections, addrs, szs);
|
||||
+ if (err != EFI_SUCCESS || szs[UNIFIED_SECTION_CMDLINE] == 0) {
|
||||
+ if (err == EFI_SUCCESS)
|
||||
+ err = EFI_NOT_FOUND;
|
||||
+ log_error_status(err,
|
||||
+ "Unable to locate embedded .cmdline section in %ls, ignoring: %m",
|
||||
+ items[i]);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* We want to enforce that addons are not UKIs, i.e.: they must not embed a kernel. */
|
||||
+ if (szs[UNIFIED_SECTION_LINUX] > 0) {
|
||||
+ log_error_status(EFI_INVALID_PARAMETER, "%ls is a UKI, not an addon, ignoring: %m", items[i]);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Also enforce that, in case it is specified, .uname matches as a quick way to allow
|
||||
+ * enforcing compatibility with a specific UKI only */
|
||||
+ if (uname && szs[UNIFIED_SECTION_UNAME] > 0 &&
|
||||
+ !strneq8(uname,
|
||||
+ (char *)loaded_addon->ImageBase + addrs[UNIFIED_SECTION_UNAME],
|
||||
+ szs[UNIFIED_SECTION_UNAME])) {
|
||||
+ log_error(".uname mismatch between %ls and UKI, ignoring", items[i]);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ _cleanup_free_ char16_t *tmp = TAKE_PTR(buffer),
|
||||
+ *extra16 = xstrn8_to_16((char *)loaded_addon->ImageBase + addrs[UNIFIED_SECTION_CMDLINE],
|
||||
+ szs[UNIFIED_SECTION_CMDLINE]);
|
||||
+ buffer = xasprintf("%ls%ls%ls", strempty(tmp), isempty(tmp) ? u"" : u" ", extra16);
|
||||
+ }
|
||||
+
|
||||
+ mangle_stub_cmdline(buffer);
|
||||
+
|
||||
+ if (!isempty(buffer)) {
|
||||
+ _cleanup_free_ char16_t *tmp = TAKE_PTR(*cmdline_append);
|
||||
+ bool m = false;
|
||||
+
|
||||
+ (void) tpm_log_load_options(buffer, &m);
|
||||
+ *ret_parameters_measured = m;
|
||||
+
|
||||
+ *cmdline_append = xasprintf("%ls%ls%ls", strempty(tmp), isempty(tmp) ? u"" : u" ", buffer);
|
||||
+ }
|
||||
+
|
||||
+ return EFI_SUCCESS;
|
||||
+}
|
||||
+
|
||||
static EFI_STATUS real_main(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;
|
||||
@@ -191,6 +375,7 @@ static EFI_STATUS real_main(EFI_HANDLE image) {
|
||||
size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {};
|
||||
_cleanup_free_ char16_t *cmdline = NULL;
|
||||
int sections_measured = -1, parameters_measured = -1;
|
||||
+ _cleanup_free_ char *uname = NULL;
|
||||
bool sysext_measured = false, m;
|
||||
uint64_t loader_features = 0;
|
||||
EFI_STATUS err;
|
||||
@@ -263,6 +448,10 @@ static EFI_STATUS real_main(EFI_HANDLE image) {
|
||||
/* Show splash screen as early as possible */
|
||||
graphics_splash((const uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_SPLASH], szs[UNIFIED_SECTION_SPLASH]);
|
||||
|
||||
+ if (szs[UNIFIED_SECTION_UNAME] > 0)
|
||||
+ uname = xstrndup8((char *)loaded_image->ImageBase + addrs[UNIFIED_SECTION_UNAME],
|
||||
+ szs[UNIFIED_SECTION_UNAME]);
|
||||
+
|
||||
if (use_load_options(image, loaded_image, szs[UNIFIED_SECTION_CMDLINE] > 0, &cmdline)) {
|
||||
/* Let's measure the passed kernel command line into the TPM. Note that this possibly
|
||||
* duplicates what we already did in the boot menu, if that was already used. However, since
|
||||
@@ -278,6 +467,33 @@ static EFI_STATUS real_main(EFI_HANDLE image) {
|
||||
mangle_stub_cmdline(cmdline);
|
||||
}
|
||||
|
||||
+ /* If we have any extra command line to add via PE addons, load them now and append, and
|
||||
+ * measure the additions separately, after the embedded options, but before the smbios ones,
|
||||
+ * so that the order is reversed from "most hardcoded" to "most dynamic". The global addons are
|
||||
+ * loaded first, and the image-specific ones later, for the same reason. */
|
||||
+ err = cmdline_append_and_measure_addons(
|
||||
+ image,
|
||||
+ loaded_image,
|
||||
+ u"\\loader\\addons",
|
||||
+ uname,
|
||||
+ &m,
|
||||
+ &cmdline);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ log_error_status(err, "Error loading global addons, ignoring: %m");
|
||||
+ parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m);
|
||||
+
|
||||
+ _cleanup_free_ char16_t *dropin_dir = get_dropin_dir(loaded_image->FilePath);
|
||||
+ err = cmdline_append_and_measure_addons(
|
||||
+ image,
|
||||
+ loaded_image,
|
||||
+ dropin_dir,
|
||||
+ uname,
|
||||
+ &m,
|
||||
+ &cmdline);
|
||||
+ if (err != EFI_SUCCESS)
|
||||
+ log_error_status(err, "Error loading UKI-specific addons, ignoring: %m");
|
||||
+ parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m);
|
||||
+
|
||||
const char *extra = smbios_find_oem_string("io.systemd.stub.kernel-cmdline-extra");
|
||||
if (extra) {
|
||||
_cleanup_free_ char16_t *tmp = TAKE_PTR(cmdline), *extra16 = xstr8_to_16(extra);
|
29
0701-TODO-remove-fixed-item.patch
Normal file
29
0701-TODO-remove-fixed-item.patch
Normal file
@ -0,0 +1,29 @@
|
||||
From a84abc0caba660444d8210107da4c03c03150cd4 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Wed, 24 May 2023 11:18:18 +0100
|
||||
Subject: [PATCH] TODO: remove fixed item
|
||||
|
||||
(cherry picked from commit f19b62756071cd6fc28b800062f591a3af88fe6a)
|
||||
|
||||
Related: RHEL-16952
|
||||
---
|
||||
TODO | 6 ------
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
diff --git a/TODO b/TODO
|
||||
index c512bedb92..abe8faf5e8 100644
|
||||
--- a/TODO
|
||||
+++ b/TODO
|
||||
@@ -249,12 +249,6 @@ Features:
|
||||
parametrization, if needed. This matches our usual rule that admin config
|
||||
should win over vendor defaults.
|
||||
|
||||
-* sd-stub: optionally allow users to configure manual kernel command line even
|
||||
- in SecureBoot by authenticating it via shim's APIs, integrating with MOK and
|
||||
- similar: instead of authenticating just PE code shim should be capable of
|
||||
- authenticating any kind of data for us, including files containing kernel
|
||||
- command lines.
|
||||
-
|
||||
* write a "search path" spec, that documents the prefixes to search in
|
||||
(i.e. the usual /etc/, /run/, /usr/lib/ dance, potentially /usr/etc/), how to
|
||||
sort found entries, how masking works and overriding.
|
@ -0,0 +1,78 @@
|
||||
From 529df7ab684596d7dae85da8360138647fa0c46b Mon Sep 17 00:00:00 2001
|
||||
From: Maanya Goenka <maanyagoenka@microsoft.com>
|
||||
Date: Wed, 27 Sep 2023 15:44:04 +0000
|
||||
Subject: [PATCH] fix: do not check/verify slice units if recursive errors are
|
||||
to be ignored
|
||||
|
||||
Before this fix, when recursive-errors was set to 'no' during a systemd-analyze
|
||||
verification, the parent slice was checked regardless. The 'no' setting means that,
|
||||
only the specified unit should be looked at and verified and errors in the slices should be
|
||||
ignored. This commit fixes that issue.
|
||||
|
||||
Example:
|
||||
|
||||
Say we have a sample.service file:
|
||||
|
||||
[Unit]
|
||||
Description=Sample Service
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/echo "a"
|
||||
Slice=support.slice
|
||||
|
||||
Before Change:
|
||||
|
||||
systemd-analyze verify --recursive-errors=no maanya/sample.service
|
||||
Assertion 'u' failed at src/core/unit.c:153, function unit_has_name(). Aborting.
|
||||
Aborted (core dumped)
|
||||
|
||||
After Change:
|
||||
systemd-analyze verify --recursive-errors=no maanya/sample.service
|
||||
{No errors}
|
||||
|
||||
(cherry picked from commit f660c7fa56b247c278fdb2ebcfea37912f249524)
|
||||
|
||||
Related: RHEL-1086
|
||||
---
|
||||
src/core/slice.c | 4 ++++
|
||||
test/units/testsuite-65.sh | 12 ++++++++++++
|
||||
2 files changed, 16 insertions(+)
|
||||
|
||||
diff --git a/src/core/slice.c b/src/core/slice.c
|
||||
index c453aa033e..8f913a8d45 100644
|
||||
--- a/src/core/slice.c
|
||||
+++ b/src/core/slice.c
|
||||
@@ -96,6 +96,10 @@ static int slice_verify(Slice *s) {
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(UNIT(s), r, "Failed to determine parent slice: %m");
|
||||
|
||||
+ /* If recursive errors are to be ignored, the parent slice should not be verified */
|
||||
+ if (UNIT(s)->manager && FLAGS_SET(UNIT(s)->manager->test_run_flags, MANAGER_TEST_RUN_IGNORE_DEPENDENCIES))
|
||||
+ return 0;
|
||||
+
|
||||
if (parent ? !unit_has_name(UNIT_GET_SLICE(UNIT(s)), parent) : !!UNIT_GET_SLICE(UNIT(s)))
|
||||
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Located outside of parent slice. Refusing.");
|
||||
|
||||
diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh
|
||||
index 4093c5a2a7..7c34948f82 100755
|
||||
--- a/test/units/testsuite-65.sh
|
||||
+++ b/test/units/testsuite-65.sh
|
||||
@@ -217,6 +217,18 @@ set -e
|
||||
rm /tmp/testfile.service
|
||||
rm /tmp/testfile2.service
|
||||
|
||||
+cat <<EOF >/tmp/sample.service
|
||||
+[Unit]
|
||||
+Description = A Sample Service
|
||||
+
|
||||
+[Service]
|
||||
+ExecStart = echo hello
|
||||
+Slice=support.slice
|
||||
+EOF
|
||||
+
|
||||
+# Zero exit status since no additional dependencies are recursively loaded when the unit file is loaded
|
||||
+systemd-analyze verify --recursive-errors=no /tmp/sample.service
|
||||
+
|
||||
cat <<EOF >/tmp/testfile.service
|
||||
[Service]
|
||||
ExecStart = echo hello
|
104
systemd.spec
104
systemd.spec
@ -21,7 +21,7 @@
|
||||
Name: systemd
|
||||
Url: https://systemd.io
|
||||
Version: 252
|
||||
Release: 27%{?dist}
|
||||
Release: 28%{?dist}
|
||||
# For a breakdown of the licensing, see README
|
||||
License: LGPLv2+ and MIT and GPLv2+
|
||||
Summary: System and Service Manager
|
||||
@ -735,6 +735,56 @@ Patch0649: 0649-test-modernize-test-journal-flush.patch
|
||||
Patch0650: 0650-journal-file-util-do-not-fail-when-journal_file_set_.patch
|
||||
Patch0651: 0651-journal-file-util-Prefer-punching-holes-instead-of-t.patch
|
||||
Patch0652: 0652-test-add-reproducer-for-SIGBUS-issue-caused-by-journ.patch
|
||||
Patch0653: 0653-random-seed-shorten-a-bit-may_credit.patch
|
||||
Patch0654: 0654-random-seed-make-one-more-use-of-random_write_entrop.patch
|
||||
Patch0655: 0655-random-seed-use-getopt.patch
|
||||
Patch0656: 0656-random-seed-make-the-logic-to-calculate-the-number-o.patch
|
||||
Patch0657: 0657-random-seed-no-need-to-pass-mode-argument-when-openi.patch
|
||||
Patch0658: 0658-random-seed-split-out-run.patch
|
||||
Patch0659: 0659-random_seed-minor-improvement-in-run.patch
|
||||
Patch0660: 0660-random-seed-downgrade-some-messages.patch
|
||||
Patch0661: 0661-random-seed-clarify-one-comment.patch
|
||||
Patch0662: 0662-random-seed-make-sure-to-load-machine-id-even-if-the.patch
|
||||
Patch0663: 0663-chase-symlinks-add-new-flag-for-prohibiting-any-foll.patch
|
||||
Patch0664: 0664-bootctl-bootspec-make-use-of-CHASE_PROHIBIT_SYMLINKS.patch
|
||||
Patch0665: 0665-boot-implement-kernel-EFI-RNG-seed-protocol-with-pro.patch
|
||||
Patch0666: 0666-random-seed-refresh-EFI-boot-seed-when-writing-a-new.patch
|
||||
Patch0667: 0667-random-seed-handle-post-merge-review-nits.patch
|
||||
Patch0668: 0668-boot-do-not-truncate-random-seed-file.patch
|
||||
Patch0669: 0669-bootctl-install-system-token-on-virtualized-systems.patch
|
||||
Patch0670: 0670-boot-remove-random-seed-mode.patch
|
||||
Patch0671: 0671-stub-handle-random-seed-like-sd-boot-does.patch
|
||||
Patch0672: 0672-efi-add-efi_guid_equal-helper.patch
|
||||
Patch0673: 0673-efi-add-common-implementation-for-loop-finding-EFI-c.patch
|
||||
Patch0674: 0674-boot-Detect-hypervisors-using-SMBIOS-info.patch
|
||||
Patch0675: 0675-boot-Skip-soft-brick-warning-when-in-a-VM.patch
|
||||
Patch0676: 0676-boot-Replace-UINTN-with-size_t.patch
|
||||
Patch0677: 0677-boot-Use-unsigned-for-beep-counting.patch
|
||||
Patch0678: 0678-boot-Use-unicode-literals.patch
|
||||
Patch0679: 0679-macro-add-generic-IS_ALIGNED32-anf-friends.patch
|
||||
Patch0680: 0680-meson-use-0-1-for-SD_BOOT.patch
|
||||
Patch0681: 0681-boot-Add-printf-functions.patch
|
||||
Patch0682: 0682-boot-Use-printf-for-error-logging.patch
|
||||
Patch0683: 0683-boot-Introduce-log_wait.patch
|
||||
Patch0684: 0684-boot-Add-log_trace-debugging-helper.patch
|
||||
Patch0685: 0685-tree-wide-Use-__func__-in-asserts.patch
|
||||
Patch0686: 0686-boot-Drop-use-of-xpool_print-SPrint.patch
|
||||
Patch0687: 0687-boot-Drop-use-of-Print.patch
|
||||
Patch0688: 0688-boot-Rework-GUID-handling.patch
|
||||
Patch0689: 0689-efi-string-Fix-strchr-null-byte-handling.patch
|
||||
Patch0690: 0690-efi-string-Add-startswith8.patch
|
||||
Patch0691: 0691-efi-string-Add-efi_memchr.patch
|
||||
Patch0692: 0692-vmm-Add-more-const.patch
|
||||
Patch0693: 0693-vmm-Add-smbios_find_oem_string.patch
|
||||
Patch0694: 0694-stub-Read-extra-kernel-command-line-items-from-SMBIO.patch
|
||||
Patch0695: 0695-vmm-Modernize-get_smbios_table.patch
|
||||
Patch0696: 0696-stub-measure-SMBIOS-kernel-cmdline-extra-in-PCR12.patch
|
||||
Patch0697: 0697-efi-support-passing-empty-cmdline-to-mangle_stub_cmd.patch
|
||||
Patch0698: 0698-efi-set-EFIVAR-to-stop-Shim-from-uninstalling-its-pr.patch
|
||||
Patch0699: 0699-ukify-use-empty-stub-for-addons.patch
|
||||
Patch0700: 0700-stub-allow-loading-and-verifying-cmdline-addons.patch
|
||||
Patch0701: 0701-TODO-remove-fixed-item.patch
|
||||
Patch0702: 0702-fix-do-not-check-verify-slice-units-if-recursive-err.patch
|
||||
|
||||
# Downstream-only patches (9000–9999)
|
||||
|
||||
@ -1600,6 +1650,58 @@ systemd-hwdb update &>/dev/null || :
|
||||
%{_prefix}/lib/dracut/modules.d/70rhel-net-naming-sysattrs/*
|
||||
|
||||
%changelog
|
||||
* Tue Feb 20 2024 systemd maintenance team <systemd-maint@redhat.com> - 252-28
|
||||
- random-seed: shorten a bit may_credit() (RHEL-16952)
|
||||
- random-seed: make one more use of random_write_entropy() (RHEL-16952)
|
||||
- random-seed: use getopt() (RHEL-16952)
|
||||
- random-seed: make the logic to calculate the number of bytes read from the random seed file clearer (RHEL-16952)
|
||||
- random-seed: no need to pass 'mode' argument when opening /dev/urandom (RHEL-16952)
|
||||
- random-seed: split out run() (RHEL-16952)
|
||||
- random_seed: minor improvement in run() (RHEL-16952)
|
||||
- random-seed: downgrade some messages (RHEL-16952)
|
||||
- random-seed: clarify one comment (RHEL-16952)
|
||||
- random-seed: make sure to load machine id even if the seed file is missing (RHEL-16952)
|
||||
- chase-symlinks: add new flag for prohibiting any following of symlinks (RHEL-16952)
|
||||
- bootctl,bootspec: make use of CHASE_PROHIBIT_SYMLINKS whenever we access the ESP/XBOOTLDR (RHEL-16952)
|
||||
- boot: implement kernel EFI RNG seed protocol with proper hashing (RHEL-16952)
|
||||
- random-seed: refresh EFI boot seed when writing a new seed (RHEL-16952)
|
||||
- random-seed: handle post-merge review nits (RHEL-16952)
|
||||
- boot: do not truncate random seed file (RHEL-16952)
|
||||
- bootctl: install system token on virtualized systems (RHEL-16952)
|
||||
- boot: remove random-seed-mode (RHEL-16952)
|
||||
- stub: handle random seed like sd-boot does (RHEL-16952)
|
||||
- efi: add efi_guid_equal() helper (RHEL-16952)
|
||||
- efi: add common implementation for loop finding EFI configuration tables (RHEL-16952)
|
||||
- boot: Detect hypervisors using SMBIOS info (RHEL-16952)
|
||||
- boot: Skip soft-brick warning when in a VM (RHEL-16952)
|
||||
- boot: Replace UINTN with size_t (RHEL-16952)
|
||||
- boot: Use unsigned for beep counting (RHEL-16952)
|
||||
- boot: Use unicode literals (RHEL-16952)
|
||||
- macro: add generic IS_ALIGNED32() anf friends (RHEL-16952)
|
||||
- meson: use 0|1 for SD_BOOT (RHEL-16952)
|
||||
- boot: Add printf functions (RHEL-16952)
|
||||
- boot: Use printf for error logging (RHEL-16952)
|
||||
- boot: Introduce log_wait (RHEL-16952)
|
||||
- boot: Add log_trace debugging helper (RHEL-16952)
|
||||
- tree-wide: Use __func__ in asserts (RHEL-16952)
|
||||
- boot: Drop use of xpool_print/SPrint (RHEL-16952)
|
||||
- boot: Drop use of Print (RHEL-16952)
|
||||
- boot: Rework GUID handling (RHEL-16952)
|
||||
- efi-string: Fix strchr() null byte handling (RHEL-16952)
|
||||
- efi-string: Add startswith8() (RHEL-16952)
|
||||
- efi-string: Add efi_memchr() (RHEL-16952)
|
||||
- vmm: Add more const (RHEL-16952)
|
||||
- vmm: Add smbios_find_oem_string() (RHEL-16952)
|
||||
- stub: Read extra kernel command line items from SMBIOS (RHEL-16952)
|
||||
- vmm: Modernize get_smbios_table() (RHEL-16952)
|
||||
- stub: measure SMBIOS kernel-cmdline-extra in PCR12 (RHEL-16952)
|
||||
- efi: support passing empty cmdline to mangle_stub_cmdline() (RHEL-16952)
|
||||
- efi: set EFIVAR to stop Shim from uninstalling its protocol (RHEL-16952)
|
||||
- ukify: use empty stub for addons (RHEL-16952)
|
||||
- stub: allow loading and verifying cmdline addons (RHEL-16952)
|
||||
- TODO: remove fixed item (RHEL-16952)
|
||||
- fix: do not check/verify slice units if recursive errors are to be ignored (RHEL-1086)
|
||||
|
||||
* Thu Feb 15 2024 systemd maintenance team <systemd-maint@redhat.com> - 252-27
|
||||
- test: merge TEST-20-MAINPIDGAMES into TEST-07-PID1 (fixup) (RHEL-1086)
|
||||
- test: use the default nsec3-iterations value (RHEL-1086)
|
||||
|
Loading…
Reference in New Issue
Block a user