Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge 'git://github.com/Celelibi/syslinux.git/fix/bios/tail-call-stac…
…k-overflows'

FIXME: this circumvents some of the issue but is not the cleanest and may
	reoccur.
  • Loading branch information
geneC committed Jan 19, 2016
2 parents 496bb8c + 19d0d59 commit 7cd1ed6
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 10 deletions.
4 changes: 3 additions & 1 deletion com32/elflink/ldlinux/execute.c
Expand Up @@ -44,6 +44,7 @@ const struct image_types image_boot_types[] = {
{ NULL, 0 },
};

extern jmp_buf __return_to_command_prompt;
extern int create_args_and_load(char *);

__export void execute(const char *cmdline, uint32_t type, bool sysappend)
Expand Down Expand Up @@ -136,7 +137,8 @@ __export void execute(const char *cmdline, uint32_t type, bool sysappend)
/* Restore the console */
ldlinux_console_init();

ldlinux_enter_command();
/* Jump back to the main to call ldlinux_enter_command */
longjmp(__return_to_command_prompt, 1);
} else if (type == IMAGE_TYPE_CONFIG) {
char *argv[] = { LDLINUX, NULL, NULL };
char *config;
Expand Down
28 changes: 20 additions & 8 deletions com32/elflink/ldlinux/ldlinux.c
Expand Up @@ -31,6 +31,8 @@ static const struct file_ext file_extensions[] = {
{ NULL, 0 },
};

jmp_buf __return_to_command_prompt;

/*
* Return a pointer to one byte after the last character of the
* command.
Expand Down Expand Up @@ -302,6 +304,7 @@ __export int main(int argc __unused, char **argv)
const void *adv;
const char *cmdline;
size_t count = 0;
int retval;

ldlinux_console_init();

Expand Down Expand Up @@ -333,16 +336,25 @@ __export int main(int argc __unused, char **argv)
if (!syslinux_setadv(ADV_BOOTONCE, 0, NULL))
syslinux_adv_write();

load_kernel(cmdline); /* Shouldn't return */
ldlinux_enter_command();
}

if (!forceprompt && !shift_is_held())
ldlinux_auto_boot();
/*
* The corresponding longjmp is located in the execute function
* after a COM32 module has returned.
*/
retval = setjmp(__return_to_command_prompt);
if (retval == 0)
load_kernel(cmdline); /* Shouldn't return */
} else {
retval = setjmp(__return_to_command_prompt);
if (retval == 0) {
if (!forceprompt && !shift_is_held())
ldlinux_auto_boot();

if (defaultlevel > 1)
ldlinux_auto_boot();
if (defaultlevel > 1)
ldlinux_auto_boot();
}
}

retval = setjmp(__return_to_command_prompt);
ldlinux_enter_command();
return 0;
}
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 7cd1ed6

Please sign in to comment.