[syslinux:master] core: Fix stack overflow when reloading config

syslinux-bot for Sylvain Gault sylvain.gault at gmail.com
Tue Jan 19 03:57:04 PST 2016


Commit-ID:  19d0d592ee115e8772b7dc6d5594748a49b63b0c
Gitweb:     http://www.syslinux.org/commit/19d0d592ee115e8772b7dc6d5594748a49b63b0c
Author:     Sylvain Gault <sylvain.gault at gmail.com>
AuthorDate: Tue, 13 Oct 2015 05:26:30 +0200
Committer:  Sylvain Gault <sylvain.gault at gmail.com>
CommitDate: Tue, 13 Oct 2015 05:44:33 +0200

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 at gmail.com>

---
 core/elflink/load_env32.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c
index 492cc09..db19c7a 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)
 {


More information about the Syslinux-commits mailing list