efivars: kill SystemdOptions efi var support

This has been depracted since v254 (2023). Let's kill it for
good now, it has been long enough with 2y. Noone has shown up who wants
to keep it. And given it doesn't work in SB world anyway, and is not
measured is quite problematic security wise.
This commit is contained in:
Lennart Poettering
2025-02-26 17:28:43 +01:00
parent 2dbc2d1d0f
commit 14871a6529
15 changed files with 9 additions and 295 deletions
-86
View File
@@ -382,90 +382,4 @@ SecureBootMode efi_get_secure_boot_mode(void) {
return (cache = decode_secure_boot_mode(secure, audit > 0, deployed > 0, setup > 0));
}
static int read_efi_options_variable(char **ret) {
int r;
/* 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://uapi-group.org/specifications/specs/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: 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()) {
/* Let's be helpful with the returned error and check if the variable exists at all. If it
* does, let's return a recognizable error (EPERM), and if not ENODATA. */
if (access(EFIVAR_PATH(EFI_SYSTEMD_VARIABLE_STR("SystemdOptions")), F_OK) < 0)
return errno == ENOENT ? -ENODATA : -errno;
return -EPERM;
}
r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE_STR("SystemdOptions"), ret);
if (r == -ENOENT)
return -ENODATA;
return r;
}
int cache_efi_options_variable(void) {
_cleanup_free_ char *line = NULL;
int r;
r = read_efi_options_variable(&line);
if (r < 0)
return r;
return write_string_file(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE_STR("SystemdOptions")), line,
WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755);
}
int systemd_efi_options_variable(char **ret) {
const char *e;
int r;
/* Returns the contents of the variable for current boot from the cache. */
assert(ret);
/* For testing purposes it is sometimes useful to be able to override this */
e = secure_getenv("SYSTEMD_EFI_OPTIONS");
if (e)
return strdup_to(ret, e);
r = read_one_line_file(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE_STR("SystemdOptions")), ret);
if (r == -ENOENT)
return -ENODATA;
return r;
}
static int compare_stat_mtime(const struct stat *a, const struct stat *b) {
return CMP(timespec_load(&a->st_mtim), timespec_load(&b->st_mtim));
}
int systemd_efi_options_efivarfs_if_newer(char **ret) {
struct stat a = {}, b;
int r;
if (stat(EFIVAR_PATH(EFI_SYSTEMD_VARIABLE_STR("SystemdOptions")), &a) < 0 && errno != ENOENT)
return log_debug_errno(errno, "Failed to stat EFI variable SystemdOptions: %m");
if (stat(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE_STR("SystemdOptions")), &b) < 0) {
if (errno != ENOENT)
log_debug_errno(errno, "Failed to stat "EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE_STR("SystemdOptions"))": %m");
} else if (compare_stat_mtime(&a, &b) > 0)
log_debug("Variable SystemdOptions in evifarfs is newer than in cache.");
else {
log_debug("Variable SystemdOptions in cache is up to date.");
*ret = NULL;
return 0;
}
r = read_efi_options_variable(ret);
if (r < 0)
return log_debug_errno(r, "Failed to read SystemdOptions EFI variable: %m");
return 0;
}
#endif
-16
View File
@@ -53,10 +53,6 @@ bool is_efi_boot(void);
bool is_efi_secure_boot(void);
SecureBootMode efi_get_secure_boot_mode(void);
int cache_efi_options_variable(void);
int systemd_efi_options_variable(char **ret);
int systemd_efi_options_efivarfs_if_newer(char **ret);
#else
static inline int efi_get_variable(const char *variable, uint32_t *attribute, void **value, size_t *size) {
@@ -90,18 +86,6 @@ static inline bool is_efi_secure_boot(void) {
static inline SecureBootMode efi_get_secure_boot_mode(void) {
return SECURE_BOOT_UNKNOWN;
}
static inline int cache_efi_options_variable(void) {
return -EOPNOTSUPP;
}
static inline int systemd_efi_options_variable(char **line) {
return -ENODATA;
}
static inline int systemd_efi_options_efivarfs_if_newer(char **line) {
return -ENODATA;
}
#endif
static inline char *efi_tilt_backslashes(char *s) {
+3 -79
View File
@@ -218,28 +218,6 @@ int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, ProcCmdlineF
* for proc_cmdline_parse(), let's make this clear. */
assert(!(flags & (PROC_CMDLINE_VALUE_OPTIONAL|PROC_CMDLINE_TRUE_WHEN_MISSING)));
/* We parse the EFI variable first, because later settings have higher priority. */
if (!FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) {
_cleanup_free_ char *line = NULL;
r = systemd_efi_options_variable(&line);
if (r < 0) {
if (r != -ENODATA)
log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m");
} else {
r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
if (r < 0)
return r;
r = proc_cmdline_parse_strv(args, parse_item, data, flags);
if (r < 0)
return r;
args = strv_free(args);
}
}
r = proc_cmdline_strv_internal(&args, /* filter_pid1_args = */ true);
if (r < 0)
return r;
@@ -326,11 +304,9 @@ static int cmdline_get_key(char **args, const char *key, ProcCmdlineFlags flags,
int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_value) {
_cleanup_strv_free_ char **args = NULL;
_cleanup_free_ char *line = NULL, *v = NULL;
int r;
/* Looks for a specific key on the kernel command line and (with lower priority) the EFI variable.
* Supports three modes:
/* Looks for a specific key on the kernel command line. Supports three modes:
*
* a) The "ret_value" parameter is used. In this case a parameter beginning with the "key" string followed by
* "=" is searched for, and the value following it is returned in "ret_value".
@@ -356,34 +332,6 @@ int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_val
if (r < 0)
return r;
if (FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) /* Shortcut */
return cmdline_get_key(args, key, flags, ret_value);
r = cmdline_get_key(args, key, flags, ret_value ? &v : NULL);
if (r < 0)
return r;
if (r > 0) {
if (ret_value)
*ret_value = TAKE_PTR(v);
return r;
}
r = systemd_efi_options_variable(&line);
if (r == -ENODATA) {
if (ret_value)
*ret_value = NULL;
return false; /* Not found */
}
if (r < 0)
return r;
args = strv_free(args);
r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
if (r < 0)
return r;
return cmdline_get_key(args, key, flags, ret_value);
}
@@ -448,7 +396,7 @@ static int cmdline_get_key_ap(ProcCmdlineFlags flags, char* const* args, va_list
int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) {
_cleanup_strv_free_ char **args = NULL;
int r, ret = 0;
int r;
va_list ap;
/* The PROC_CMDLINE_VALUE_OPTIONAL and PROC_CMDLINE_TRUE_WHEN_MISSING flags don't really make sense
@@ -457,28 +405,6 @@ int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) {
/* This call may clobber arguments on failure! */
if (!FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) {
_cleanup_free_ char *line = NULL;
r = systemd_efi_options_variable(&line);
if (r < 0 && r != -ENODATA)
log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m");
if (r >= 0) {
r = strv_split_full(&args, line, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
if (r < 0)
return r;
va_start(ap, flags);
r = cmdline_get_key_ap(flags, args, ap);
va_end(ap);
if (r < 0)
return r;
ret = r;
args = strv_free(args);
}
}
r = proc_cmdline_strv(&args);
if (r < 0)
return r;
@@ -486,8 +412,6 @@ int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) {
va_start(ap, flags);
r = cmdline_get_key_ap(flags, args, ap);
va_end(ap);
if (r < 0)
return r;
return ret + r;
return r;
}
+1 -2
View File
@@ -9,8 +9,7 @@ typedef enum ProcCmdlineFlags {
PROC_CMDLINE_STRIP_RD_PREFIX = 1 << 0, /* automatically strip "rd." prefix if it is set (and we are in the initrd, since otherwise we'd not consider it anyway) */
PROC_CMDLINE_VALUE_OPTIONAL = 1 << 1, /* the value is optional (for boolean switches that can omit the value) */
PROC_CMDLINE_RD_STRICT = 1 << 2, /* ignore this in the initrd */
PROC_CMDLINE_IGNORE_EFI_OPTIONS = 1 << 3, /* don't check systemd's private EFI variable */
PROC_CMDLINE_TRUE_WHEN_MISSING = 1 << 4, /* default to true when the key is missing for bool */
PROC_CMDLINE_TRUE_WHEN_MISSING = 1 << 3, /* default to true when the key is missing for bool */
} ProcCmdlineFlags;
typedef int (*proc_cmdline_parse_t)(const char *key, const char *value, void *data);