shithub: riscv

Download patch

ref: 87d7a3c8750ca4f61c2cae5269b3eda04cce7e6c
parent: 281729551fd7351b410f788d267c9041ae1ef15f
author: cinap_lenrek <[email protected]>
date: Thu Aug 6 09:20:41 EDT 2015

kernel: have to validate argv[] again when copying to the new stack

we have to validaddr() and vmemchr() all argv[] elements a second
time when we copy to the new stack to deal with the fact that another
process can come in and modify the memory of the process doing the
exec. so the argv[] strings could have changed and increased in
length. we just make sure the data being copied will fit into the
new stack and error when we would overflow.

also make sure to free the ESEG in case the copy pass errors.

--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -295,8 +295,13 @@
 		free(elem);
 		free(args);
 		/* Disaster after commit */
-		if(!up->seg[SSEG])
+		if(up->seg[SSEG] == nil)
 			pexit(up->errstr, 1);
+		s = up->seg[ESEG];
+		if(s != nil){
+			putseg(s);
+			up->seg[ESEG] = nil;
+		}
 		nexterror();
 	}
 	align = BY2PG;
@@ -438,7 +443,6 @@
 
 	argv = (char**)(tstk - ssize);
 	charp = (char*)(tstk - nbytes);
-	a = charp;
 	if(indir)
 		argp = progarg;
 	else
@@ -450,12 +454,22 @@
 			argp = argp0;
 		}
 		*argv++ = charp + (USTKTOP-tstk);
-		n = strlen(*argp) + 1;
-		memmove(charp, *argp++, n);
+		a = *argp++;
+		if(indir)
+			e = strchr(a, 0);
+		else {
+			validaddr((uintptr)a, 1, 0);
+			e = vmemchr(a, 0, (char*)tstk - charp);
+			if(e == nil)
+				error(Ebadarg);
+		}
+		n = (e - a) + 1;
+		memmove(charp, a, n);
 		charp += n;
 	}
 
 	/* copy args; easiest from new process's stack */
+	a = (char*)(tstk - nbytes);
 	n = charp - a;
 	if(n > 128)	/* don't waste too much space on huge arg lists */
 		n = 128;