Merge pull request #15870 from poettering/proc-cmdline-efi-fix

udev /proc/cmdline handling fixes
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2020-05-21 09:07:27 +02:00 committed by GitHub
commit 7c15a55f8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 19 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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",