diff options
author | Sylvain Gault <sylvain.gault@gmail.com> | 2015-10-12 05:03:26 +0200 |
---|---|---|
committer | Sylvain Gault <sylvain.gault@gmail.com> | 2015-10-13 05:44:33 +0200 |
commit | 7bb4e1335435397243c9b63a64a5c61c82691357 (patch) | |
tree | 9520abd28cf3b4107efac11fd573f6b1019979db /com32/elflink/ldlinux/ldlinux.c | |
parent | 91463467e4633d7c29dfb98b4079c3c330fcde95 (diff) | |
download | syslinux-7bb4e1335435397243c9b63a64a5c61c82691357.tar.gz |
ldlinux: fix stack overflow when running COM32 modules
When a COM32 module exits, the functions never return and a new call to
ldlinux_enter_command is made. This could fill the stack and overflow on
some data present in memory.
This patch use setjmp/longjmp to return to the main function and restart
from there when a COM32 module exits.
Signed-off-by: Sylvain Gault <sylvain.gault@gmail.com>
Diffstat (limited to 'com32/elflink/ldlinux/ldlinux.c')
-rw-r--r-- | com32/elflink/ldlinux/ldlinux.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c index 9b01dd3a..0172117b 100644 --- a/com32/elflink/ldlinux/ldlinux.c +++ b/com32/elflink/ldlinux/ldlinux.c @@ -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. @@ -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(); @@ -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; } |