diff options
author | Ard Biesheuvel <ardb@kernel.org> | 2020-02-10 17:02:46 +0100 |
---|---|---|
committer | Ard Biesheuvel <ardb@kernel.org> | 2020-02-23 21:57:15 +0100 |
commit | 91d150c0cc637b9d9d6394936add7cd2b7ccc410 (patch) | |
tree | cc604ef224f2a8c476d19984b6d0ef42454c25f0 /drivers/firmware/efi/libstub/efi-stub-helper.c | |
parent | efi/libstub: Take soft and hard memory limits into account for initrd loading (diff) | |
download | linux-91d150c0cc637b9d9d6394936add7cd2b7ccc410.tar.xz linux-91d150c0cc637b9d9d6394936add7cd2b7ccc410.zip |
efi/libstub: Clean up command line parsing routine
We currently parse the command non-destructively, to avoid having to
allocate memory for a copy before passing it to the standard parsing
routines that are used by the core kernel, and which modify the input
to delineate the parsed tokens with NUL characters.
Instead, we call strstr() and strncmp() to go over the input multiple
times, and match prefixes rather than tokens, which implies that we
would match, e.g., 'nokaslrfoo' in the stub and disable KASLR, while
the kernel would disregard the option and run with KASLR enabled.
In order to avoid having to reason about whether and how this behavior
may be abused, let's clean up the parsing routines, and rebuild them
on top of the existing helpers.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Diffstat (limited to 'drivers/firmware/efi/libstub/efi-stub-helper.c')
-rw-r--r-- | drivers/firmware/efi/libstub/efi-stub-helper.c | 79 |
1 files changed, 26 insertions, 53 deletions
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index db23be5dc69b..49008ac88b63 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -68,66 +68,39 @@ void efi_printk(char *str) */ efi_status_t efi_parse_options(char const *cmdline) { - char *str; - - str = strstr(cmdline, "nokaslr"); - if (str == cmdline || (str && str > cmdline && *(str - 1) == ' ')) - efi_nokaslr = true; - - str = strstr(cmdline, "quiet"); - if (str == cmdline || (str && str > cmdline && *(str - 1) == ' ')) - efi_quiet = true; - - /* - * If no EFI parameters were specified on the cmdline we've got - * nothing to do. - */ - str = strstr(cmdline, "efi="); - if (!str) - return EFI_SUCCESS; - - /* Skip ahead to first argument */ - str += strlen("efi="); - - /* - * Remember, because efi= is also used by the kernel we need to - * skip over arguments we don't understand. - */ - while (*str && *str != ' ') { - if (!strncmp(str, "nochunk", 7)) { - str += strlen("nochunk"); - efi_nochunk = true; - } + size_t len = strlen(cmdline) + 1; + efi_status_t status; + char *str, *buf; - if (!strncmp(str, "novamap", 7)) { - str += strlen("novamap"); - efi_novamap = true; - } + status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, len, (void **)&buf); + if (status != EFI_SUCCESS) + return status; - if (IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) && - !strncmp(str, "nosoftreserve", 7)) { - str += strlen("nosoftreserve"); - efi_nosoftreserve = true; - } + str = skip_spaces(memcpy(buf, cmdline, len)); - if (!strncmp(str, "disable_early_pci_dma", 21)) { - str += strlen("disable_early_pci_dma"); - efi_disable_pci_dma = true; - } + while (*str) { + char *param, *val; - if (!strncmp(str, "no_disable_early_pci_dma", 24)) { - str += strlen("no_disable_early_pci_dma"); - efi_disable_pci_dma = false; - } + str = next_arg(str, ¶m, &val); - /* Group words together, delimited by "," */ - while (*str && *str != ' ' && *str != ',') - str++; + if (!strcmp(param, "nokaslr")) { + efi_nokaslr = true; + } else if (!strcmp(param, "quiet")) { + efi_quiet = true; + } else if (!strcmp(param, "efi") && val) { + efi_nochunk = parse_option_str(val, "nochunk"); + efi_novamap = parse_option_str(val, "novamap"); - if (*str == ',') - str++; - } + efi_nosoftreserve = IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) && + parse_option_str(val, "nosoftreserve"); + if (parse_option_str(val, "disable_early_pci_dma")) + efi_disable_pci_dma = true; + if (parse_option_str(val, "no_disable_early_pci_dma")) + efi_disable_pci_dma = false; + } + } + efi_bs_call(free_pool, buf); return EFI_SUCCESS; } |