aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorSylvain Gault <sylvain.gault@gmail.com>2015-10-13 05:26:30 +0200
committerSylvain Gault <sylvain.gault@gmail.com>2015-10-13 05:44:33 +0200
commit19d0d592ee115e8772b7dc6d5594748a49b63b0c (patch)
tree94b225ea932739e3261888515905d90d5301cfbb /core
parent7bb4e1335435397243c9b63a64a5c61c82691357 (diff)
downloadsyslinux-19d0d592ee115e8772b7dc6d5594748a49b63b0c.tar.gz
syslinux-19d0d592ee115e8772b7dc6d5594748a49b63b0c.tar.xz
syslinux-19d0d592ee115e8772b7dc6d5594748a49b63b0c.zip
core: Fix stack overflow when reloading config
The behavior when running a "CONFIG" command line is to reload ldlinux.c32 with the new file as argument. This call never return. In order to avoid stacking up the calls to start_ldlinux, this patch introduce a setjmp/longjmp to return to the first call to start_ldlinux, thus freeing all the stack space. Signed-off-by: Sylvain Gault <sylvain.gault@gmail.com>
Diffstat (limited to 'core')
-rw-r--r--core/elflink/load_env32.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c
index 492cc095..db19c7aa 100644
--- a/core/elflink/load_env32.c
+++ b/core/elflink/load_env32.c
@@ -55,7 +55,7 @@ void init_module_subsystem(struct elf_module *module)
list_add(&module->list, &modules_head);
}
-__export int start_ldlinux(int argc, char **argv)
+static int _start_ldlinux(int argc, char **argv)
{
int rv;
@@ -96,6 +96,62 @@ again:
return rv;
}
+__export int start_ldlinux(int argc, char **argv)
+{
+ /* These variables are static to survive the longjmp. */
+ static int has_jmpbuf = 0;
+ static jmp_buf restart;
+ static int savedargc;
+ static char *heapargs;
+ static size_t argsmem = 0;
+ char **stackargv;
+ char *stackargs;
+ char *p, *q;
+ int i;
+
+
+ /* 1. Save the arguments on the heap */
+ for (i = 0; i < argc; i++)
+ argsmem += strlen(argv[i]) + 1;
+
+ savedargc = argc;
+ heapargs = malloc(argsmem);
+
+ p = heapargs;
+ for (i = 0; i < savedargc; i++) {
+ q = argv[i];
+ while (*q)
+ *p++ = *q++;
+
+ *p++ = '\0';
+ }
+
+ /* 2. Undo the stack if we're restarting ldlinux */
+ if (has_jmpbuf)
+ longjmp(restart, 1);
+
+ setjmp(restart);
+ has_jmpbuf = 1;
+
+ /* 3. Convert the heap memory to stack memory to avoid memory leaks */
+ stackargs = alloca(argsmem);
+ stackargv = alloca(savedargc * (sizeof(char *) + 1));
+
+ memcpy(stackargs, heapargs, argsmem);
+
+ p = stackargs;
+ for (i = 0; i < savedargc; i++) {
+ stackargv[i] = p;
+ p += strlen(p) + 1;
+ }
+
+ stackargv[savedargc] = NULL;
+
+ free(heapargs);
+
+ return _start_ldlinux(savedargc, stackargv);
+}
+
/* note to self: do _*NOT*_ use static key word on this function */
void load_env32(com32sys_t * regs __unused)
{