From 80b1bfe1cb2f20225fb2d8f11d44af4a9d765396 Mon Sep 17 00:00:00 2001 From: Arvind Sankar Date: Wed, 20 May 2020 20:29:21 -0400 Subject: 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 Link: https://lore.kernel.org/r/20200521002921.69650-1-nivedita@alum.mit.edu Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/efi-stub-helper.c | 28 +++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers/firmware/efi') 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 +#include #include #include #include /* For CONSOLE_LOGLEVEL_* */ #include +#include #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 */ -- cgit v1.2.3