From 87d7a3c8750ca4f61c2cae5269b3eda04cce7e6c Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Thu, 6 Aug 2015 13:20:41 +0200 Subject: [PATCH] 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. --- sys/src/9/port/sysproc.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/sys/src/9/port/sysproc.c b/sys/src/9/port/sysproc.c index 733ab381d..6f13ea900 100644 --- a/sys/src/9/port/sysproc.c +++ b/sys/src/9/port/sysproc.c @@ -295,8 +295,13 @@ sysexec(va_list list) 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 @@ sysexec(va_list list) argv = (char**)(tstk - ssize); charp = (char*)(tstk - nbytes); - a = charp; if(indir) argp = progarg; else @@ -450,12 +454,22 @@ sysexec(va_list list) 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;