summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFilipe Brandenburger <filbranden@gmail.com>2020-06-10 15:11:32 -0700
committerLennart Poettering <lennart@poettering.net>2020-06-13 14:46:57 +0200
commit209b2592ed5883bdfc7a0f2e5b7277c5c4fe834e (patch)
tree5941e3b132a3948a15181a89af49eaf668b9122a /src
parent6d0f38017c7476883103080372505d4811112346 (diff)
downloadsystemd-209b2592ed5883bdfc7a0f2e5b7277c5c4fe834e.tar.gz
efi: Cache contents of EFI variable SystemdOptions
Cache it early in startup of the system manager, right after `/run/systemd` is created, so that further access to it can be done without accessing the EFI filesystem at all.
Diffstat (limited to 'src')
-rw-r--r--src/basic/efivars.c73
-rw-r--r--src/basic/efivars.h1
-rw-r--r--src/core/main.c5
3 files changed, 59 insertions, 20 deletions
diff --git a/src/basic/efivars.c b/src/basic/efivars.c
index 3954bd62f5..e7edd17d0b 100644
--- a/src/basic/efivars.c
+++ b/src/basic/efivars.c
@@ -14,6 +14,7 @@
#include "chattr-util.h"
#include "efivars.h"
#include "fd-util.h"
+#include "fileio.h"
#include "io-util.h"
#include "macro.h"
#include "stdio-util.h"
@@ -40,6 +41,17 @@ char* efi_variable_path(sd_id128_t vendor, const char *name) {
return p;
}
+static char* efi_variable_cache_path(sd_id128_t vendor, const char *name) {
+ char *p;
+
+ if (asprintf(&p,
+ "/run/systemd/efivars/%s-" SD_ID128_UUID_FORMAT_STR,
+ name, SD_ID128_FORMAT_VAL(vendor)) < 0)
+ return NULL;
+
+ return p;
+}
+
int efi_get_variable(
sd_id128_t vendor,
const char *name,
@@ -323,32 +335,17 @@ bool is_efi_secure_boot_setup_mode(void) {
return cache > 0;
}
-int systemd_efi_options_variable(char **line) {
- const char *e;
+int cache_efi_options_variable(void) {
+ _cleanup_free_ char *line = NULL, *cachepath = NULL;
int r;
- assert(line);
-
- /* For testing purposes it is sometimes useful to be able to override this */
- e = secure_getenv("SYSTEMD_EFI_OPTIONS");
- if (e) {
- char *m;
-
- m = strdup(e);
- if (!m)
- return -ENOMEM;
-
- *line = m;
- return 0;
- }
-
/* In SecureBoot mode this is probably not what you want. As your cmdline is cryptographically signed
* like when using Type #2 EFI Unified Kernel Images (https://systemd.io/BOOT_LOADER_SPECIFICATION/)
* The user's intention is then that the cmdline should not be modified. You want to make sure that
* the system starts up as exactly specified in the signed artifact.
*
- * (NB: to make testing purposes we still check the $SYSTEMD_EFI_OPTIONS env var above, even when in
- * SecureBoot mode.) */
+ * (NB: For testing purposes, we still check the $SYSTEMD_EFI_OPTIONS env var before accessing this
+ * cache, even when in SecureBoot mode.) */
if (is_efi_secure_boot()) {
_cleanup_free_ char *k;
@@ -365,10 +362,46 @@ int systemd_efi_options_variable(char **line) {
return -EPERM;
}
- r = efi_get_variable_string(EFI_VENDOR_SYSTEMD, "SystemdOptions", line);
+ r = efi_get_variable_string(EFI_VENDOR_SYSTEMD, "SystemdOptions", &line);
if (r == -ENOENT)
return -ENODATA;
+ if (r < 0)
+ return r;
+ cachepath = efi_variable_cache_path(EFI_VENDOR_SYSTEMD, "SystemdOptions");
+ if (!cachepath)
+ return -ENOMEM;
+
+ return write_string_file(cachepath, line, WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755);
+}
+
+int systemd_efi_options_variable(char **line) {
+ const char *e;
+ _cleanup_free_ char *cachepath = NULL;
+ int r;
+
+ assert(line);
+
+ /* For testing purposes it is sometimes useful to be able to override this */
+ e = secure_getenv("SYSTEMD_EFI_OPTIONS");
+ if (e) {
+ char *m;
+
+ m = strdup(e);
+ if (!m)
+ return -ENOMEM;
+
+ *line = m;
+ return 0;
+ }
+
+ cachepath = efi_variable_cache_path(EFI_VENDOR_SYSTEMD, "SystemdOptions");
+ if (!cachepath)
+ return -ENOMEM;
+
+ r = read_one_line_file(cachepath, line);
+ if (r == -ENOENT)
+ return -ENODATA;
return r;
}
#endif
diff --git a/src/basic/efivars.h b/src/basic/efivars.h
index 13a33c6605..80854677f4 100644
--- a/src/basic/efivars.h
+++ b/src/basic/efivars.h
@@ -32,6 +32,7 @@ bool is_efi_boot(void);
bool is_efi_secure_boot(void);
bool is_efi_secure_boot_setup_mode(void);
+int cache_efi_options_variable(void);
int systemd_efi_options_variable(char **line);
#else
diff --git a/src/core/main.c b/src/core/main.c
index a88d779448..6e606d412a 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -33,6 +33,7 @@
#include "dbus.h"
#include "def.h"
#include "efi-random.h"
+#include "efivars.h"
#include "emergency-action.h"
#include "env-util.h"
#include "exit-status.h"
@@ -2630,6 +2631,10 @@ int main(int argc, char *argv[]) {
/* The efivarfs is now mounted, let's read the random seed off it */
(void) efi_take_random_seed();
+
+ /* Cache command-line options passed from EFI variables */
+ if (!skip_setup)
+ (void) cache_efi_options_variable();
}
/* Save the original RLIMIT_NOFILE/RLIMIT_MEMLOCK so that we can reset it later when