diff options
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 */ |