kernel: reset up->setargs on sysexec(), fix race with devproc

up->setargs wasnt reset in sysexec(). also, up->args should only
be exchanged/freed under up->debug qlock. otherwise double free
could happen.
This commit is contained in:
cinap_lenrek 2013-09-18 01:07:06 +02:00
parent 8a7a6f778d
commit 34cd9dc4c4
2 changed files with 17 additions and 16 deletions

View file

@ -737,7 +737,7 @@ struct Proc
ulong qpc; /* pc calling last blocking qlock */ ulong qpc; /* pc calling last blocking qlock */
QLock *eql; /* interruptable eqlock */ QLock *eql; /* interruptable eqlock */
int setargs; int setargs; /* process changed its args */
void *ureg; /* User registers for notes */ void *ureg; /* User registers for notes */
void *dbgreg; /* User registers for devproc */ void *dbgreg; /* User registers for devproc */

View file

@ -252,19 +252,20 @@ sysexec(ulong *arg)
ulong magic, text, entry, data, bss; ulong magic, text, entry, data, bss;
Tos *tos; Tos *tos;
indir = 0; a = nil;
elem = nil; elem = nil;
validaddr(arg[0], 1, 0); validaddr(arg[0], 1, 0);
file0 = validnamedup((char*)arg[0], 1); file0 = validnamedup((char*)arg[0], 1);
if(waserror()){ if(waserror()){
free(file0); free(file0);
if(elem != up->text) free(elem);
free(elem); free(a);
/* Disaster after commit */ /* Disaster after commit */
if(!up->seg[SSEG]) if(!up->seg[SSEG])
pexit(up->errstr, 1); pexit(up->errstr, 1);
nexterror(); nexterror();
} }
indir = 0;
file = file0; file = file0;
for(;;){ for(;;){
tc = namec(file, Aopen, OEXEC, 0); tc = namec(file, Aopen, OEXEC, 0);
@ -405,28 +406,21 @@ sysexec(ulong *arg)
charp += n; charp += n;
} }
free(up->text);
up->text = elem;
/* copy args; easiest from new process's stack */ /* copy args; easiest from new process's stack */
n = charp - args; n = charp - args;
if(n > 128) /* don't waste too much space on huge arg lists */ if(n > 128) /* don't waste too much space on huge arg lists */
n = 128; n = 128;
a = up->args; a = smalloc(n);
up->args = nil; memmove(a, args, n);
free(a); if(n>0 && a[n-1]!='\0'){
up->args = smalloc(n);
memmove(up->args, args, n);
if(n>0 && up->args[n-1]!='\0'){
/* make sure last arg is NUL-terminated */ /* make sure last arg is NUL-terminated */
/* put NUL at UTF-8 character boundary */ /* put NUL at UTF-8 character boundary */
for(i=n-1; i>0; --i) for(i=n-1; i>0; --i)
if(fullrune(up->args+i, n-i)) if(fullrune(a+i, n-i))
break; break;
up->args[i] = 0; a[i] = 0;
n = i+1; n = i+1;
} }
up->nargs = n;
/* /*
* Committed. * Committed.
@ -501,6 +495,13 @@ sysexec(ulong *arg)
free(file0); free(file0);
qlock(&up->debug); qlock(&up->debug);
free(up->text);
up->text = elem;
free(up->args);
up->args = a;
up->nargs = n;
up->setargs = 0;
up->nnote = 0; up->nnote = 0;
up->notify = 0; up->notify = 0;
up->notified = 0; up->notified = 0;