aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2013-01-04 19:16:39 +0000
committerMatt Fleming <matt.fleming@intel.com>2013-01-04 19:52:26 +0000
commit96f02b37a56382c0e297fdbe4b7002f8ffb8829c (patch)
tree26522588ff2efa74af1e410ff8cbbab77cbcc4a1
parente1680d483ead4a0afdc672ce9c5c7942941f985b (diff)
downloadsyslinux-96f02b37a56382c0e297fdbe4b7002f8ffb8829c.tar.gz
syslinux-96f02b37a56382c0e297fdbe4b7002f8ffb8829c.tar.xz
syslinux-96f02b37a56382c0e297fdbe4b7002f8ffb8829c.zip
ldlinux: Dynamically alloc memory for kernel and initrd filenames
Absolutely no bounds checking is performed when copying filenames to 'cmdline_buf' and 'initrd_name' which means that sufficiently long strings will scribble over the stack. At best, the files will simply fail to load because the name is garbled. Allocate space for the cmdline at runtime to avoid these overflow problems. Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r--com32/elflink/ldlinux/kernel.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/com32/elflink/ldlinux/kernel.c b/com32/elflink/ldlinux/kernel.c
index 1cfb6508..920246fc 100644
--- a/com32/elflink/ldlinux/kernel.c
+++ b/com32/elflink/ldlinux/kernel.c
@@ -15,35 +15,45 @@ const char *append = NULL;
/* Will be called from readconfig.c */
int new_linux_kernel(char *okernel, char *ocmdline)
{
- const char *kernel_name = NULL;
+ const char *kernel_name = NULL, *args = NULL;
struct initramfs *initramfs = NULL;
char *temp;
void *kernel_data;
- size_t kernel_len;
+ size_t kernel_len, cmdline_len;
bool opt_quiet = false;
- char initrd_name[256];
- char cmdline_buf[256], *cmdline;
+ char *initrd_name, *cmdline;
dprintf("okernel = %s, ocmdline = %s", okernel, ocmdline);
- cmdline = cmdline_buf;
-
- temp = cmdline;
-
if (okernel)
kernel_name = okernel;
else if (globaldefault)
kernel_name = globaldefault;
- strcpy(temp, kernel_name);
- temp += strlen(kernel_name);
-
- *temp = ' ';
- temp++;
if (ocmdline)
- strcpy(temp, ocmdline);
+ args = ocmdline;
else if (append)
- strcpy(temp, append);
+ args = append;
+
+ cmdline_len = strlen(kernel_name);
+ if (args) {
+ /* +1 for the space (' ') between kernel and args */
+ cmdline_len += strlen(args) + 1;
+ }
+
+ /* +1 for NUL termination */
+ cmdline_len++;
+
+ cmdline = malloc(cmdline_len);
+ if (!cmdline) {
+ printf("Failed to alloc memory for cmdline\n");
+ return 1;
+ }
+
+ if (args)
+ snprintf(cmdline, cmdline_len, "%s %s", kernel_name, args);
+ else
+ snprintf(cmdline, cmdline_len, "%s", kernel_name);
/* "keeppxe" handling */
#if IS_PXELINUX
@@ -79,13 +89,25 @@ int new_linux_kernel(char *okernel, char *ocmdline)
temp += 6; /* strlen("initrd") */
do {
- char *p = initrd_name;
+ size_t n = 0;
+ char *p;
temp++; /* Skip = or , */
- while (*temp != ' ' && *temp != ',' && *temp)
- *p++ = *temp++;
- *p = '\0';
+ p = temp;
+ while (*p != ' ' && *p != ',' && *p) {
+ p++;
+ n++;
+ }
+
+ initrd_name = malloc(n + 1);
+ if (!initrd_name) {
+ printf("Failed to allocate space for initrd\n");
+ goto bail;
+ }
+
+ snprintf(initrd_name, n + 1, "%s", temp);
+ temp += n;
if (!opt_quiet)
printf("Loading %s...", initrd_name);
@@ -93,10 +115,13 @@ int new_linux_kernel(char *okernel, char *ocmdline)
if (initramfs_load_archive(initramfs, initrd_name)) {
if (opt_quiet)
printf("Loading %s ", initrd_name);
+ free(initrd_name);
printf("failed: ");
goto bail;
}
+ free(initrd_name);
+
if (!opt_quiet)
printf("ok\n");
} while (*temp == ',');
@@ -107,6 +132,7 @@ int new_linux_kernel(char *okernel, char *ocmdline)
printf("Booting kernel failed: ");
bail:
+ free(cmdline);
printf("%s\n", strerror(errno));
return 1;
}