git: 9front

Download patch

ref: 8d5989ae1c02160de05d8d5192b91fb01f4f864c
parent: 8b8df2b948e512e3ceb2e6bc802879c32b37975f
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Mar 15 22:37:07 EDT 2013

sysexec: fix possible segment overlap with temporary stack

the kernel uses fixed area (TSTKTOP, TSTKSIZ) of the address
space to temporarily map the new stack segment for exec. for
386 and arm, this area was right below the stack segment which
has the problem that the program can map arbitrary segments
there (even readonly).

alpha and ppc dont have this problem as they map the temporary
exec stack *above* the user reachable stack segement and segattach
prevents one from mapping anything above or overlaping the stack.

lots of arch code assumes USTKTOP being the end of userspace
address space and changing this to TSTKTOP would work, but results
in lots of hard to test changes.

instead, we'r going to map the temporary stack programmatically
finding a hole in the address space where to map it. we also lift
the size limitation for arguments and allow arguments to fill
the whole new stack segement.

the TSTKTOP and TSTKSIZ are not used anymore so they where removed.

references:

http://9fans.net/archive/2013/03/203
http://9fans.net/archive/2013/03/202
http://9fans.net/archive/2013/03/197
http://9fans.net/archive/2013/03/195
http://9fans.net/archive/2013/03/181

--- a/sys/src/9/alphapc/mem.h
+++ b/sys/src/9/alphapc/mem.h
@@ -72,11 +72,9 @@
  */
 #define	UZERO	0			/* base of user address space */
 #define	UTZERO	(UZERO+BY2PG)		/* first address in user text */
-#define	USTKTOP	(TSTKTOP-TSTKSIZ*BY2PG)	/* byte just beyond user stack */
-#define	TSTKTOP	KZERO			/* top of temporary stack */
-#define	TSTKSIZ 100
 #define	KZERO	0x80000000		/* base of kernel address space */
 #define	KTZERO	(KZERO+0x400000)	/* first address in kernel text */
+#define	USTKTOP	KZERO			/* byte just beyond user stack */
 #define	USTKSIZE	(4*1024*1024)	/* size of user stack */
 
 /*
--- a/sys/src/9/bcm/mem.h
+++ b/sys/src/9/bcm/mem.h
@@ -53,8 +53,6 @@
 #define	UTZERO		(UZERO+BY2PG)		/* user text start */
 #define	USTKTOP		0x20000000		/* user segment end +1 */
 #define	USTKSIZE	(8*1024*1024)		/* user stack size */
-#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* sysexec temporary stack */
-#define	TSTKSIZ	 	256
 
 /* address at which to copy and execute rebootcode */
 #define	REBOOTADDR	(KZERO+0x3400)
--- a/sys/src/9/bitsy/mem.h
+++ b/sys/src/9/bitsy/mem.h
@@ -57,8 +57,6 @@
 #define	NULLTOP		0xE8000000		/* ... */
 #define	USTKTOP		0x2000000		/* byte just beyond user stack */
 #define	USTKSIZE		(8*1024*1024)		/* size of user stack */
-#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
-#define	TSTKSIZ	 	100
 #define	MACHADDR	(KZERO+0x00001000)
 #define	EVECTORS	0xFFFF0000		/* virt base of exception vectors */
 
--- a/sys/src/9/kw/mem.h
+++ b/sys/src/9/kw/mem.h
@@ -71,8 +71,6 @@
 #define	UTZERO		(UZERO+BY2PG)		/* user text start */
 #define	USTKTOP		KZERO			/* user segment end +1 */
 #define	USTKSIZE	(8*1024*1024)		/* user stack size */
-#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* sysexec temporary stack */
-#define	TSTKSIZ	 	256
 
 /* address at which to copy and execute rebootcode */
 #define	REBOOTADDR	KADDR(0x100)
--- a/sys/src/9/mtx/mem.h
+++ b/sys/src/9/mtx/mem.h
@@ -170,12 +170,10 @@
 
 #define	UZERO	0			/* base of user address space */
 #define	UTZERO	(UZERO+BY2PG)		/* first address in user text */
-#define	USTKTOP	(TSTKTOP-TSTKSIZ*BY2PG)	/* byte just beyond user stack */
-#define	TSTKTOP	KZERO	/* top of temporary stack */
-#define	TSTKSIZ 100
 #define	KZERO	0x80000000		/* base of kernel address space */
-#define	KTZERO	(KZERO+0x4000)	/* first address in kernel text */
-#define	USTKSIZE	(4*1024*1024)		/* size of user stack */
+#define	KTZERO	(KZERO+0x4000)		/* first address in kernel text */
+#define	USTKTOP	KZERO			/* byte just beyond user stack */
+#define	USTKSIZE	(4*1024*1024)	/* size of user stack */
 #define	UREGSIZE	((8+32)*4)
 
 #define	PCIMEM0		0xf0000000
--- a/sys/src/9/omap/mem.h
+++ b/sys/src/9/omap/mem.h
@@ -75,8 +75,6 @@
 /* moved USTKTOP down to 512MB to keep MMIO space out of user space. */
 #define	USTKTOP		0x20000000		/* user segment end +1 */
 #define	USTKSIZE	(8*1024*1024)		/* user stack size */
-#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* sysexec temporary stack */
-#define	TSTKSIZ	 	256
 
 /* address at which to copy and execute rebootcode */
 #define	REBOOTADDR	KADDR(0x100)
--- a/sys/src/9/omap4/mem.h
+++ b/sys/src/9/omap4/mem.h
@@ -29,9 +29,7 @@
 
 #define KSTKSIZ		(16*KiB)
 #define KSTACK		KSTKSIZ
-#define TSTKSIZ		256
 #define USTKSIZE		(8*MiB)
-#define	TSTKTOP		(USTKTOP - USTKSIZE)
 #define HZ		100
 
 #define	MAXSYSARG	7
--- a/sys/src/9/pc/mem.h
+++ b/sys/src/9/pc/mem.h
@@ -51,8 +51,6 @@
 #define	UTZERO		(UZERO+BY2PG)		/* first address in user text */
 #define	USTKTOP		(VMAP-BY2PG)		/* byte just beyond user stack */
 #define	USTKSIZE	(16*1024*1024)		/* size of user stack */
-#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
-#define	TSTKSIZ 	100			/* pages in new stack; limits exec args */
 
 /*
  * Fundamental addresses - bottom 64kB saved for return to real mode
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -227,7 +227,7 @@
 	char **argv, **argp;
 	char *a, *charp, *args, *file, *file0;
 	char *progarg[sizeof(Exec)/2+1], *elem, progelem[64];
-	ulong ssize, spage, nargs, nbytes, n, bssend;
+	ulong ssize, tstk, nargs, nbytes, n, bssend;
 	int indir, commit;
 	Exec exec;
 	char line[sizeof(Exec)];
@@ -340,32 +340,38 @@
 	 */
 	if((ssize+4) & 7)
 		ssize += 4;
-	spage = (ssize+(BY2PG-1)) >> PGSHIFT;
 
+	if(PGROUND(ssize) >= USTKSIZE)
+		error(Enovmem);
+
 	/*
 	 * Build the stack segment, putting it in kernel virtual for the moment
 	 */
-	if(spage > TSTKSIZ)
-		error(Enovmem);
-
 	qlock(&up->seglock);
 	if(waserror()){
 		qunlock(&up->seglock);
 		nexterror();
 	}
-	up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
 
+	s = up->seg[SSEG];
+	do {
+		tstk = s->base;
+		if(tstk <= USTKSIZE)
+			error(Enovmem);
+	} while((s = isoverlap(up, tstk-USTKSIZE, USTKSIZE)) != nil);
+	up->seg[ESEG] = newseg(SG_STACK, tstk-USTKSIZE, USTKSIZE/BY2PG);
+
 	/*
 	 * Args: pass 2: assemble; the pages will be faulted in
 	 */
-	tos = (Tos*)(TSTKTOP - sizeof(Tos));
+	tos = (Tos*)(tstk - sizeof(Tos));
 	tos->cyclefreq = m->cyclefreq;
 	tos->kcycles = 0;
 	tos->pcycles = 0;
 	tos->clock = 0;
 
-	argv = (char**)(TSTKTOP - ssize);
-	charp = (char*)(TSTKTOP - nbytes);
+	argv = (char**)(tstk - ssize);
+	charp = (char*)(tstk - nbytes);
 	args = charp;
 	if(indir)
 		argp = progarg;
@@ -377,7 +383,7 @@
 			indir = 0;
 			argp = (char**)arg[1];
 		}
-		*argv++ = charp + (USTKTOP-TSTKTOP);
+		*argv++ = charp + (USTKTOP-tstk);
 		n = strlen(*argp) + 1;
 		memmove(charp, *argp++, n);
 		charp += n;
@@ -469,7 +475,7 @@
 	up->seg[ESEG] = 0;
 	s->base = USTKTOP-USTKSIZE;
 	s->top = USTKTOP;
-	relocateseg(s, USTKTOP-TSTKTOP);
+	relocateseg(s, USTKTOP-tstk);
 	up->seg[SSEG] = s;
 	qunlock(&up->seglock);
 	poperror();	/* seglock */
--- a/sys/src/9/ppc/mem.h
+++ b/sys/src/9/ppc/mem.h
@@ -209,9 +209,7 @@
 #define	KTZERO		0x80100000		/* first address in kernel text */
 #define	UZERO		0			/* base of user address space */
 #define	UTZERO		(UZERO+BY2PG)		/* first address in user text */
-#define	USTKTOP		(TSTKTOP-TSTKSIZ*BY2PG)	/* byte just beyond user stack */
-#define	TSTKTOP		KZERO			/* top of temporary stack */
-#define	TSTKSIZ		100
+#define	USTKTOP		KZERO			/* byte just beyond user stack */
 #define	USTKSIZE	(4*1024*1024)		/* size of user stack */
 #define	UREGSIZE	((8+40)*4)
 #define	MACHADDR	(KTZERO-MAXMACH*MACHSIZE)
--- a/sys/src/9/teg2/mem.h
+++ b/sys/src/9/teg2/mem.h
@@ -93,8 +93,6 @@
  */
 #define	USTKTOP		(0x40000000 - 64*KiB - MiB) /* user segment end +1 */
 #define	USTKSIZE	(8*1024*1024)		/* user stack size */
-#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* sysexec temporary stack */
-#define	TSTKSIZ	 	256
 
 /* address at which to copy and execute rebootcode */
 #define	REBOOTADDR	KADDR(0x100)
--