diff options
author | Arvind Sankar <nivedita@alum.mit.edu> | 2020-05-21 03:29:21 +0300 |
---|---|---|
committer | Ard Biesheuvel <ardb@kernel.org> | 2020-05-22 17:50:03 +0300 |
commit | 80b1bfe1cb2f20225fb2d8f11d44af4a9d765396 (patch) | |
tree | cd6f70557c1fe4a91be370bb79c8df837a9487ad /drivers/firmware | |
parent | 04b24409b42a9fcae2379a6ddcf9c827b9af7a45 (diff) | |
download | linux-80b1bfe1cb2f20225fb2d8f11d44af4a9d765396.tar.xz |
efi/libstub: Don't parse overlong command lines
Check if the command line passed in is larger than COMMAND_LINE_SIZE,
and truncate it to the last full argument if so.
Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
Link: https://lore.kernel.org/r/20200521002921.69650-1-nivedita@alum.mit.edu
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efi/libstub/efi-stub-helper.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 9fb107e9355b..dbfaf8dcdda2 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -9,10 +9,12 @@ #include <stdarg.h> +#include <linux/ctype.h> #include <linux/efi.h> #include <linux/kernel.h> #include <linux/printk.h> /* For CONSOLE_LOGLEVEL_* */ #include <asm/efi.h> +#include <asm/setup.h> #include "efistub.h" @@ -217,22 +219,33 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, unsigned long cmdline_addr = 0; int options_chars = efi_table_attr(image, load_options_size) / 2; const u16 *options = efi_table_attr(image, load_options); - int options_bytes = 0; /* UTF-8 bytes */ + int options_bytes = 0, safe_options_bytes = 0; /* UTF-8 bytes */ + bool in_quote = false; efi_status_t status; if (options) { s2 = options; - while (options_chars--) { + while (options_bytes < COMMAND_LINE_SIZE && options_chars--) { u16 c = *s2++; - if (c == L'\0' || c == L'\n') - break; + if (c < 0x80) { + if (c == L'\0' || c == L'\n') + break; + if (c == L'"') + in_quote = !in_quote; + else if (!in_quote && isspace((char)c)) + safe_options_bytes = options_bytes; + + options_bytes++; + continue; + } + /* * Get the number of UTF-8 bytes corresponding to a * UTF-16 character. * The first part handles everything in the BMP. */ - options_bytes += 1 + (c >= 0x80) + (c >= 0x800); + options_bytes += 2 + (c >= 0x800); /* * Add one more byte for valid surrogate pairs. Invalid * surrogates will be replaced with 0xfffd and take up @@ -253,6 +266,11 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, } } } + if (options_bytes >= COMMAND_LINE_SIZE) { + options_bytes = safe_options_bytes; + efi_err("Command line is too long: truncated to %d bytes\n", + options_bytes); + } } options_bytes++; /* NUL termination */ |