diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-12-03 05:35:33 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-12-03 05:35:33 +0100 |
commit | eb9de925c63990f6b19494698e4db1eb9682e46d (patch) | |
tree | 774c129eaad9c5e0e8922885f9d310c8d6863e22 /sys/src/ape/lib/ap/plan9/execve.c | |
parent | f3842de5fd405859f0a2de9a6f9fed0311c4629c (diff) |
ape: fix more bugs, use /env and /proc instead of #e and #p, cleanup
remove envname length limitation in _envsetup()
by using allocated buffer and use /env instead of #e
use /proc and getpid() instead of #p and #c in
readprocfdinit()
fix buffer overflow in execlp(), check if name
of failed exec starts with / . or is \0
make sure not to close our own filedescriptors
for FD_CLOEXEC in execve(), fix wrong length
check for flushing buffer to /env/_fdinfo.
fix error handling cases. copy the enviroment
before decoding \1 to \0 because the strings in
environ[] array might not be writable.
remove bogus close if we fail to open ppid file
in getppid() and use /dev/ppid instead of #c/ppid
Diffstat (limited to 'sys/src/ape/lib/ap/plan9/execve.c')
-rw-r--r-- | sys/src/ape/lib/ap/plan9/execve.c | 81 |
1 files changed, 49 insertions, 32 deletions
diff --git a/sys/src/ape/lib/ap/plan9/execve.c b/sys/src/ape/lib/ap/plan9/execve.c index 1d5c3c2fe..e11ca1c21 100644 --- a/sys/src/ape/lib/ap/plan9/execve.c +++ b/sys/src/ape/lib/ap/plan9/execve.c @@ -14,8 +14,7 @@ execve(const char *name, const char *argv[], const char *envp[]) char **e, *ss, *se; Fdinfo *fi; unsigned long flags; - char nam[256+5]; - char buf[1000]; + char buf[1024]; _RFORK(RFCENVG); /* @@ -24,31 +23,40 @@ execve(const char *name, const char *argv[], const char *envp[]) * in $_fdinfo (for open fd's) */ - f = _CREATE("#e/_fdinfo", OWRITE, 0666); + f = _CREATE("/env/_fdinfo", OWRITE, 0666); ss = buf; - for(n = 0; n<OPEN_MAX; n++){ - fi = &_fdinfo[n]; + for(i = 0; i<OPEN_MAX; i++){ + if(i == f) + continue; + fi = &_fdinfo[i]; flags = fi->flags; if(flags&FD_CLOEXEC){ - _CLOSE(n); + _CLOSE(i); fi->flags = 0; fi->oflags = 0; }else if(flags&FD_ISOPEN){ - ss = _ultoa(ss, n); + if(f < 0) + continue; + ss = _ultoa(ss, i); *ss++ = ' '; ss = _ultoa(ss, flags); *ss++ = ' '; ss = _ultoa(ss, fi->oflags); *ss++ = '\n'; - if(ss-buf < sizeof(buf)-50){ - _WRITE(f, buf, ss-buf); + n = ss-buf; + if(n > sizeof(buf)-50){ + if(_WRITE(f, buf, n) != n) + break; ss = buf; } } } - if(ss > buf) - _WRITE(f, buf, ss-buf); - _CLOSE(f); + if(f >= 0){ + if(ss > buf) + _WRITE(f, buf, ss-buf); + _CLOSE(f); + } + /* * To pass _sighdlr[] across exec, set $_sighdlr * to list of blank separated fd's that have @@ -57,43 +65,52 @@ execve(const char *name, const char *argv[], const char *envp[]) * are ignored, in case the current value of the * variable ignored some. */ - f = _CREATE("#e/_sighdlr", OWRITE, 0666); + f = _CREATE("/env/_sighdlr", OWRITE, 0666); if(f >= 0){ ss = buf; - for(i = 0, n=0; i <=MAXSIG && ss < &buf[sizeof(buf)]-5; i++) { + for(i = 0; i <=MAXSIG; i++) { if(_sighdlr[i] == SIG_IGN) { ss = _ultoa(ss, i); *ss++ = ' '; + n = ss-buf; + if(n > sizeof(buf)-20){ + if(_WRITE(f, buf, n) != n) + break; + ss = buf; + } } } - _WRITE(f, buf, ss-buf); + if(ss > buf) + _WRITE(f, buf, ss-buf); _CLOSE(f); } if(envp){ - strcpy(nam, "#e/"); for(e = envp; (ss = *e); e++) { se = strchr(ss, '='); if(!se || ss==se) continue; /* what is name? value? */ n = se-ss; - if(n >= sizeof(nam)-3) - n = sizeof(nam)-3-1; - memcpy(nam+3, ss, n); - nam[3+n] = 0; - f = _CREATE(nam, OWRITE, 0666); + if(n >= sizeof(buf)-5) + continue; /* name too long */ + strcpy(buf, "/env/"); + memcpy(buf+5, ss, n); + buf[5+n] = 0; + f = _CREATE(buf, OWRITE, 0666); if(f < 0) continue; - se++; /* past = */ - n = strlen(se); - /* temporarily decode nulls (see _envsetup()) */ - for(i=0; i < n; i++) - if(se[i] == 1) - se[i] = 0; - _WRITE(f, se, n); - /* put nulls back */ - for(i=0; i < n; i++) - if(se[i] == 0) - se[i] = 1; + ss = ++se; /* past = */ + se += strlen(ss); + while((n = (se - ss)) > 0){ + if(n > sizeof(buf)) + n = sizeof(buf); + /* decode nulls (see _envsetup()) */ + for(i=0; i<n; i++) + if((buf[i] = ss[i]) == 1) + buf[i] = 0; + if(_WRITE(f, buf, n) != n) + break; + ss += n; + } _CLOSE(f); } } |