diff options
author | Doug Anderson <dianders@chromium.org> | 2011-10-05 13:31:14 -0700 |
---|---|---|
committer | Doug Anderson <dianders@chromium.org> | 2011-10-07 08:47:15 -0700 |
commit | 73829d2ccaafe12dca5e324cc348b037a079b73b (patch) | |
tree | a5f96e20a3bd709d55b07a51dcf06aaee76a68b9 /common/cmd_bootm.c | |
parent | bd3303c4525fc91667fde0b2f64795d3b0d2d35f (diff) |
CHROMIUM: bootm: Avoid 256-byte overflow in fixup_silent_linux()
This makes fixup_silent_linux() use malloc() to allocate its
working space, meaning that our maximum kernel command line
should only be limited by malloc(). Previously it was silently
overflowing the stack.
BUG=chromium-os:21313
TEST=Manual:
1. Built with:
USE="-cros-debug" emerge-${BOARD} \
chromeos-u-boot \
chromeos-bootimage
2. Flashed with:
cros_write_firmware --board=${BOARD} /build/${BOARD}/firmware/image.bin
3. Saw that I could boot.
TEST=Manually copied unittest code (included in next checkin) to a
C file and then ran it. All tests pass. Note that there is no
automated way to run unittests like this in u-boot yet.
Change-Id: I0b5fd0d4a3cd09b7545d676a201a11b4a9b7dada
Signed-off-by: Doug Anderson <dianders@chromium.org>
Reviewed-on: http://gerrit.chromium.org/gerrit/8815
Reviewed-by: Che-Liang Chiou <clchiou@chromium.org>
Diffstat (limited to 'common/cmd_bootm.c')
-rw-r--r-- | common/cmd_bootm.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 9cad7e0fb1..ba0b4a5759 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -1209,9 +1209,38 @@ U_BOOT_CMD( /* helper routines */ /*******************************************************************/ #ifdef CONFIG_SILENT_CONSOLE + +/** + * Wrap malloc to print a warning (if in DEBUG mode) upon failure. + * + * Note that even though a warning will be printed, NULL can still be returned + * by this function. + * + * This is expected to be called through the macro chkmalloc(), which handles + * filling in the file and line parameters. + * + * @param size Number of bytes to allocate + * @param file File name; filled in by chkmalloc() wrapper. + * @param line Line number; filled in by chkmalloc() wrapper. + * @return memory allocated, or NULL. + */ +static void *do_chkmalloc(size_t size, const char *file, unsigned int line) +{ + void *p = malloc(size); + if (!p) + debug("WARNING: malloc of %lu bytes failed (%s:%u)\n", + (unsigned long)size, file, line); + return p; +} +#define chkmalloc(size) do_chkmalloc(size, __FILE__, __LINE__) + + +#define CONSOLE_ARG "console=" +#define CONSOLE_ARG_LEN (sizeof(CONSOLE_ARG) - 1) + static void fixup_silent_linux(void) { - char buf[256], *start, *end; + char *buf; char *cmdline = getenv("bootargs"); /* Only fix cmdline when requested */ @@ -1219,25 +1248,40 @@ static void fixup_silent_linux(void) return; debug("before silent fix-up: %s\n", cmdline); - if (cmdline) { - start = strstr(cmdline, "console="); + if (cmdline && (cmdline[0] != '\0')) { + char *start = strstr(cmdline, "console="); if (start) { - end = strchr(start, ' '); - strncpy(buf, cmdline, (start - cmdline + 8)); + char *end = strchr(start, ' '); + int num_start_bytes = start - cmdline + CONSOLE_ARG_LEN; + + /* We know cmdline bytes will be more than enough. */ + buf = chkmalloc(strlen(cmdline) + 1); + if (!buf) + return; + + strncpy(buf, cmdline, num_start_bytes); if (end) - strcpy(buf + (start - cmdline + 8), end); + strcpy(buf + num_start_bytes, end); else - buf[start - cmdline + 8] = '\0'; + buf[num_start_bytes] = '\0'; } else { - strcpy(buf, cmdline); - strcat(buf, " console="); + buf = chkmalloc(strlen(cmdline) + 1 + + CONSOLE_ARG_LEN + 1); + if (!buf) + return; + sprintf(buf, "%s %s", cmdline, CONSOLE_ARG); } } else { - strcpy(buf, "console="); + buf = strdup("console="); + if (!buf) { + debug("WARNING: strdup failed in fixup_silent_linux\n"); + return; + } } setenv("bootargs", buf); debug("after silent fix-up: %s\n", buf); + free(buf); } #endif /* CONFIG_SILENT_CONSOLE */ |