git: 9front

Download patch

ref: 2e97e6ec19ebbceeefe4a2d1ed7d2a24af5e7784
parent: 117b1e300a41e48ec4ff13b8f0de27d5ac1c69ee
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Mon Dec 3 00:35:33 EST 2012

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

--- a/sys/src/ape/lib/ap/plan9/_envsetup.c
+++ b/sys/src/ape/lib/ap/plan9/_envsetup.c
@@ -21,7 +21,6 @@
 char **environ;
 int errno;
 unsigned long _clock;
-static char name[NAME_MAX+5] = "#e";
 static void fdsetup(char *, char *);
 static void sigsetup(char *, char *);
 
@@ -45,33 +44,32 @@
 	nohandle = 0;
 	fdinited = 0;
 	cnt = 0;
-	dfd = _OPEN(name, 0);
+	dfd = _OPEN("/env", 0);
 	if(dfd < 0) {
 		static char **emptyenvp = 0;
 		environ = emptyenvp;
 		return;
 	}
-	name[2] = '/';
-	ps = p = malloc(Envhunk);
 	psize = Envhunk;
+	ps = p = malloc(psize);
 	nd = _dirreadall(dfd, &d9a);
 	_CLOSE(dfd);
 	for(j=0; j<nd; j++){
 		d9 = &d9a[j];
 		n = strlen(d9->name);
-		if(n >= sizeof(name)-4)
-			continue;
 		m = d9->length;
 		i = p - ps;
-		if(i+n+1+m+1 > psize) {
-			psize += (n+m+2 < Envhunk)? Envhunk : n+m+2;
+		if(i+n+5+m+1 > psize) {
+			psize += (n+m+6 < Envhunk)? Envhunk : n+m+6;
 			ps = realloc(ps, psize);
 			p = ps + i;
 		}
+		strcpy(p, "/env/");
+		memcpy(p+5, d9->name, n+1);
+		f = _OPEN(p, 0);
+		memset(p, 0, n+6);
 		memcpy(p, d9->name, n);
 		p[n] = '=';
-		strcpy(name+3, d9->name);
-		f = _OPEN(name, O_RDONLY);
 		if(f < 0 || _READ(f, p+n+1, m) != m)
 			m = 0;
 		_CLOSE(f);
--- a/sys/src/ape/lib/ap/plan9/_fdinfo.c
+++ b/sys/src/ape/lib/ap/plan9/_fdinfo.c
@@ -2,6 +2,7 @@
 #include "lib.h"
 #include <sys/stat.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include "sys9.h"
 #include <string.h>
 
@@ -33,21 +34,12 @@
 	/* construct info from /proc/$pid/fd */
 	char buf[8192];
 	Fdinfo *fi;
-	int fd, pfd, pid, n, tot, m;
+	int fd, pfd, n, tot, m;
 	char *s, *nexts;
 
 	memset(buf, 0, sizeof buf);
-	pfd = _OPEN("#c/pid", 0);
-	if(pfd < 0)
-		return -1;
-	if(_PREAD(pfd, buf, 100, 0) < 0){
-		_CLOSE(pfd);
-		return -1;
-	}
-	_CLOSE(pfd);
-	pid = strtoul(buf, 0, 10);
-	strcpy(buf, "#p/");
-	_ultoa(buf+3, pid);
+	strcpy(buf, "/proc/");
+	_ultoa(buf+6, getpid());
 	strcat(buf, "/fd");
 	pfd = _OPEN(buf, 0);
 	if(pfd < 0)
@@ -77,10 +69,8 @@
 		fd = strtoul(s, &s, 10);
 		if(errno != 0)
 			return -1;
-		if(fd >= OPEN_MAX)
+		if(fd < 0 || fd == pfd || fd >= OPEN_MAX)
 			continue;
-		if(fd == pfd)
-			continue;
 		fi = &_fdinfo[fd];
 		fi->flags = FD_ISOPEN;
 		while(*s == ' ' || *s == '\t')
@@ -149,8 +139,6 @@
 	usedproc = 0;
 	if(readprocfdinit() == 0)
 		usedproc = 1;
-else
-_WRITE(2, "FAILED\n", 7);
 	if(s)
 		sfdinit(usedproc, s, se);
 	if(!s && !usedproc)
--- a/sys/src/ape/lib/ap/plan9/execlp.c
+++ b/sys/src/ape/lib/ap/plan9/execlp.c
@@ -16,9 +16,11 @@
 	char buf[PATH_MAX];
 
 	if((n=execve(name, &arg0, environ)) < 0){
+		if(strchr("/.", name[0]) != 0 || strlen(name) >= sizeof(buf)-5)
+			return n;
 		strcpy(buf, "/bin/");
 		strcpy(buf+5, name);
-		n = execve(buf, &name+1, environ);
+		n = execve(buf, &arg0, environ);
 	}
 	return n;
 }
--- a/sys/src/ape/lib/ap/plan9/execve.c
+++ b/sys/src/ape/lib/ap/plan9/execve.c
@@ -14,8 +14,7 @@
 	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 @@
 	 * 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 @@
 	 * 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);
 		}
 	}
--- a/sys/src/ape/lib/ap/plan9/getppid.c
+++ b/sys/src/ape/lib/ap/plan9/getppid.c
@@ -9,15 +9,14 @@
 pid_t
 getppid(void)
 {
-	int n, f;
-	char ppidbuf[15];
+	char b[20];
+	int f;
 
-	f = open("#c/ppid", 0);
-	n = read(f, ppidbuf, sizeof ppidbuf);
-	if(n < 0)
-		errno = EINVAL;
-	else
-		n = atoi(ppidbuf);
-	close(f);
-	return n;
+	memset(b, 0, sizeof(b));
+	f = open("/dev/ppid", 0);
+	if(f >= 0) {
+		read(f, b, sizeof(b));
+		close(f);
+	}
+	return atol(b);
 }
--