diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c index d8d30b0f1d..eb45682f3a 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; @@ -218,7 +221,7 @@ static int cmdline_get_key(const char *line, const char *key, ProcCmdlineFlags f } int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_value) { - _cleanup_free_ char *line = 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. @@ -245,14 +248,27 @@ int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_val if (r < 0) return r; - r = cmdline_get_key(line, key, flags, ret_value); - if (r != 0) /* Either error or true if found. */ + 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; + if (r > 0) { + if (ret_value) + *ret_value = TAKE_PTR(v); + + return r; + } line = mfree(line); r = systemd_efi_options_variable(&line); - if (r == -ENODATA) + if (r == -ENODATA) { + if (ret_value) + *ret_value = NULL; + return false; /* Not found */ + } if (r < 0) return r; @@ -286,6 +302,7 @@ int proc_cmdline_get_bool(const char *key, bool *ret) { int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) { _cleanup_free_ char *line = NULL; + bool processing_efi = true; const char *p; va_list ap; int r, ret = 0; @@ -296,9 +313,11 @@ int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) { /* This call may clobber arguments on failure! */ - r = proc_cmdline(&line); - if (r < 0) - return r; + 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 (;;) { @@ -307,8 +326,22 @@ int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) { r = proc_cmdline_extract_first(&p, &word, flags); if (r < 0) return r; - if (r == 0) + if (r == 0) { + /* We finished with this command line. If this was the EFI one, then let's proceed with the regular one */ + if (processing_efi) { + processing_efi = false; + + line = mfree(line); + r = proc_cmdline(&line); + if (r < 0) + return r; + + p = line; + continue; + } + break; + } va_start(ap, flags); diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h index 275f46c89e..077d3a99fb 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 4c955b0c07..e9975030aa 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",