From: Suzuki K. Poulose <[email protected]>

Enforce size check for kernel command line to make sure it
doesn't overflow COMMAND_LINE_SIZE.

Reported-by: Nathan D. Miller <[email protected]>
Signed-off-by: Suzuki K. Poulose <[email protected]>
---
 kexec/arch/ppc/kexec-elf-ppc.c    |   41 ++++++++++++++++++-------------------
 kexec/arch/ppc/kexec-uImage-ppc.c |   31 ++++++++++++++--------------
 2 files changed, 35 insertions(+), 37 deletions(-)

diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index 5f63a64..7ba8421 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -156,7 +156,7 @@ int elf_ppc_load(int argc, char **argv,     const char 
*buf, off_t len,
 {
        struct mem_ehdr ehdr;
        char *command_line, *crash_cmdline, *cmdline_buf;
-       int command_line_len;
+       int command_line_len, crash_cmdline_len;
        char *dtb;
        int result;
        unsigned long max_addr, hole_addr;
@@ -233,27 +233,15 @@ int elf_ppc_load(int argc, char **argv,   const char 
*buf, off_t len,
        }
 
        command_line_len = 0;
-       if (command_line) {
-               command_line_len = strlen(command_line) + 1;
-       } else {
+       if (!command_line)
                command_line = get_command_line();
-               command_line_len = strlen(command_line) + 1;
-       }
+       command_line_len = strlen(command_line);
 
        if (ramdisk && reuse_initrd)
                die("Can't specify --ramdisk or --initrd with --reuseinitrd\n");
 
        fixup_nodes[cur_fixup] = NULL;
 
-       /* Need to append some command line parameters internally in case of
-        * taking crash dumps.
-        */
-       if (info->kexec_flags & KEXEC_ON_CRASH) {
-               crash_cmdline = xmalloc(COMMAND_LINE_SIZE);
-               memset((void *)crash_cmdline, 0, COMMAND_LINE_SIZE);
-       } else
-               crash_cmdline = NULL;
-
        /* Parse the Elf file */
        result = build_elf_exec_info(buf, len, &ehdr, 0);
        if (result < 0) {
@@ -291,26 +279,37 @@ int elf_ppc_load(int argc, char **argv,   const char 
*buf, off_t len,
                return result;
        }
 
-       /* If panic kernel is being loaded, additional segments need
-        * to be created.
+       /*
+        * Need to append some command line parameters internally in case of
+        * taking crash dumps. Additional segments have to be loaded for panic
+        * kernel.
         */
        if (info->kexec_flags & KEXEC_ON_CRASH) {
+               crash_cmdline = xmalloc(COMMAND_LINE_SIZE);
+               memset((void *)crash_cmdline, 0, COMMAND_LINE_SIZE);
                result = load_crashdump_segments(info, crash_cmdline,
                                                max_addr, 0);
                if (result < 0) {
                        free(crash_cmdline);
                        return -1;
                }
+               crash_cmdline_len = strlen(crash_cmdline);
+       } else {
+               crash_cmdline = NULL;
+               crash_cmdline_len = 0;
        }
 
+       if (crash_cmdline_len + command_line_len + 1 > COMMAND_LINE_SIZE) {
+               printf ("Command line buffer overflow\n");
+               return -1;
+       }
+               
        cmdline_buf = xmalloc(COMMAND_LINE_SIZE);
        memset((void *)cmdline_buf, 0, COMMAND_LINE_SIZE);
        if (command_line)
-               strncat(cmdline_buf, command_line, command_line_len);
+               strcpy(cmdline_buf, command_line);
        if (crash_cmdline)
-               strncat(cmdline_buf, crash_cmdline,
-                               sizeof(crash_cmdline) -
-                               strlen(crash_cmdline) - 1);
+               strncat(cmdline_buf, crash_cmdline, crash_cmdline_len);
 
        /*
         * In case of a toy we take the hardcoded things and an easy setup via
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c 
b/kexec/arch/ppc/kexec-uImage-ppc.c
index 900cd16..0c96bac 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -81,7 +81,7 @@ static int ppc_load_bare_bits(int argc, char **argv, const 
char *buf,
                unsigned int ep)
 {
        char *command_line, *cmdline_buf, *crash_cmdline;
-       int command_line_len;
+       int command_line_len, crash_cmdline_len;
        char *dtb;
        unsigned int addr;
        unsigned long dtb_addr;
@@ -140,13 +140,10 @@ static int ppc_load_bare_bits(int argc, char **argv, 
const char *buf,
                die("Can't specify --ramdisk or --initrd with --reuseinitrd\n");
 
        command_line_len = 0;
-       if (command_line) {
-               command_line_len = strlen(command_line) + 1;
-       } else {
+       if (!command_line)
                command_line = get_command_line();
-               command_line_len = strlen(command_line) + 1;
-       }
 
+       command_line_len = strlen(command_line);
        fixup_nodes[cur_fixup] = NULL;
 
        /*
@@ -179,25 +176,27 @@ static int ppc_load_bare_bits(int argc, char **argv, 
const char *buf,
        if (info->kexec_flags & KEXEC_ON_CRASH) {
                 crash_cmdline = xmalloc(COMMAND_LINE_SIZE);
                 memset((void *)crash_cmdline, 0, COMMAND_LINE_SIZE);
-        } else
-                crash_cmdline = NULL;
-
-       if (info->kexec_flags & KEXEC_ON_CRASH) {
                ret = load_crashdump_segments(info, crash_cmdline,
                                                max_addr, 0);
-               if (ret < 0) {
+               if (ret < 0)
                        return -1;
-               }
+               crash_cmdline_len = strlen(crash_cmdline);
+       } else {
+               crash_cmdline = NULL;
+               crash_cmdline_len = 0;
+       }
+
+       if (command_line_len + crash_cmdline_len + 1 > COMMAND_LINE_SIZE) {
+               printf("Command line buffer overflow \n");
+               return -1;
        }
 
        cmdline_buf = xmalloc(COMMAND_LINE_SIZE);
        memset((void *)cmdline_buf, 0, COMMAND_LINE_SIZE);
        if (command_line)
-               strncat(cmdline_buf, command_line, command_line_len);
+               strcpy(cmdline_buf, command_line);
        if (crash_cmdline)
-               strncat(cmdline_buf, crash_cmdline,
-                       sizeof(crash_cmdline) -
-                       strlen(crash_cmdline) - 1);
+               strncat(cmdline_buf, crash_cmdline, crash_cmdline_len);
 
        elf_rel_build_load(info, &info->rhdr, (const char *)purgatory,
                                purgatory_size, 0, -1, -1, 0);


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to