From 09835de3ccfee80703d00cd16978de2c296706ed Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 20 May 2020 19:22:09 +0200 Subject: [PATCH] proc-cmdline: make checking of EFI options variable optional And do not use it in the IMPORT{cmdline} udev code. Wherever we expose direct interfaces to check the kernel cmdline, let's not consult our systemd-specific EFI variable, but strictly use the actual kernel variable, because that's what we claim we do. i.e. it's fine to use the EFI variable for our own settings, but for the generic APIs to the kernel cmdline we should not use it. Specifically, this applies to IMPORT{cmdline} and ConditionKernelCommandLine=. In the latter case we weren#t checking the EFI variable anyway, hence let's do the same for the udev case, too. Fixes: #15739 --- src/basic/proc-cmdline.c | 28 ++++++++++++++++++---------- src/basic/proc-cmdline.h | 7 ++++--- src/udev/udev-rules.c | 2 +- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c index 5545543fbdd..eb45682f3a4 100644 --- a/src/basic/proc-cmdline.c +++ b/src/basic/proc-cmdline.c @@ -119,15 +119,18 @@ int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, ProcCmdlineF /* We parse the EFI variable first, because later settings have higher priority. */ - r = systemd_efi_options_variable(&line); - if (r < 0 && r != -ENODATA) - log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m"); + if (!FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) { + r = systemd_efi_options_variable(&line); + if (r < 0 && r != -ENODATA) + log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m"); - r = proc_cmdline_parse_given(line, parse_item, data, flags); - if (r < 0) - return r; + r = proc_cmdline_parse_given(line, parse_item, data, flags); + if (r < 0) + return r; + + line = mfree(line); + } - line = mfree(line); r = proc_cmdline(&line); if (r < 0) return r; @@ -245,6 +248,9 @@ 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(line, key, flags, ret_value); + r = cmdline_get_key(line, key, flags, ret_value ? &v : NULL); if (r < 0) return r; @@ -307,9 +313,11 @@ int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) { /* This call may clobber arguments on failure! */ - r = systemd_efi_options_variable(&line); - if (r < 0 && r != -ENODATA) - log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m"); + if (!FLAGS_SET(flags, PROC_CMDLINE_IGNORE_EFI_OPTIONS)) { + r = systemd_efi_options_variable(&line); + if (r < 0 && r != -ENODATA) + log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m"); + } p = line; for (;;) { diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h index 275f46c89ec..077d3a99fb9 100644 --- a/src/basic/proc-cmdline.h +++ b/src/basic/proc-cmdline.h @@ -6,9 +6,10 @@ #include "log.h" 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_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 */ } ProcCmdlineFlags; typedef int (*proc_cmdline_parse_t)(const char *key, const char *value, void *data); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 4c955b0c079..e9975030aae 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -1814,7 +1814,7 @@ static int udev_rule_apply_token_to_event( case TK_M_IMPORT_CMDLINE: { _cleanup_free_ char *value = NULL; - r = proc_cmdline_get_key(token->value, PROC_CMDLINE_VALUE_OPTIONAL, &value); + r = proc_cmdline_get_key(token->value, PROC_CMDLINE_VALUE_OPTIONAL|PROC_CMDLINE_IGNORE_EFI_OPTIONS, &value); if (r < 0) return log_rule_error_errno(dev, rules, r, "Failed to read '%s' option from /proc/cmdline: %m", -- 2.47.3