Skip to content

Commit

Permalink
core: Fix stack overflow when reloading config
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sylvain Gault committed Oct 13, 2015
1 parent 7bb4e13 commit 19d0d59
Showing 1 changed file with 57 additions and 1 deletion.
58 changes: 57 additions & 1 deletion core/elflink/load_env32.c
Expand Up @@ -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;

Expand Down Expand Up @@ -96,6 +96,62 @@ __export int start_ldlinux(int argc, char **argv)
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)
{
Expand Down

0 comments on commit 19d0d59

Please sign in to comment.