shithub: riscv

Download patch

ref: 022fd02b9632b0ca3ddd9547730446dd222ab93d
parent: d970ed6a5a243c2ec69857b69382b79eaaad1e87
author: cinap_lenrek <[email protected]>
date: Tue Feb 7 19:00:42 EST 2012

fix endless devwalk loops caused by genbuf truncation

--- a/sys/src/9/port/devenv.c
+++ b/sys/src/9/port/devenv.c
@@ -48,7 +48,7 @@
 	else if(s < eg->nent)
 		e = eg->ent[s];
 
-	if(e == 0) {
+	if(e == 0 || (strlen(e->name) >= sizeof(up->genbuf))) {
 		runlock(eg);
 		return -1;
 	}
@@ -146,6 +146,9 @@
 
 	if(c->qid.type != QTDIR)
 		error(Eperm);
+
+	if(strlen(name) >= sizeof(up->genbuf))
+		error(Egreg);
 
 	omode = openmode(omode);
 	eg = envgrp(c);
--- a/sys/src/9/port/devshr.c
+++ b/sys/src/9/port/devshr.c
@@ -298,13 +298,13 @@
 	sch = tosch(c);
 	switch(sch->level){
 	default:
-		error(Egreg);
+		return -1;
 	case Qroot:
 	case Qcroot:
 		qlock(&shrslk);
 		for(shr = shrs; shr && s; shr = shr->next)
 			s--;
-		if(shr == nil){
+		if(shr == nil || (strlen(shr->name) >= sizeof(up->genbuf))){
 			qunlock(&shrslk);
 			return -1;
 		}
@@ -323,11 +323,11 @@
 		rlock(&h->lock);
 		for(m = h->mount; m && s; m = m->next)
 			s--;
-		if(m == nil){
+		mpt = tompt(m);
+		if(m == nil || (strlen(mpt->name) >= sizeof(up->genbuf))){
 			runlock(&h->lock);
 			return -1;
 		}
-		mpt = tompt(m);
 		kstrcpy(up->genbuf, mpt->name, sizeof up->genbuf);
 		devdir(c, shrqid(Qcmpt, mpt->id), up->genbuf, 0, mpt->owner, mpt->perm, dp);
 		runlock(&h->lock);
@@ -460,7 +460,8 @@
 	case Qcroot:
 		if((perm & DMDIR) == 0 || openmode(omode) != OREAD)
 			error(Eperm);
-
+		if(strlen(name) >= sizeof(up->genbuf))
+			error(Egreg);
 		qlock(&shrslk);
 		if(waserror()){
 			qunlock(&shrslk);
@@ -497,6 +498,9 @@
 			error(Eperm);
 		devpermcheck(shr->owner, shr->perm, ORDWR);
 
+		if(strlen(name) >= sizeof(up->genbuf))
+			error(Egreg);
+
 		h = &shr->umh;
 		wlock(&h->lock);
 		if(waserror()){
@@ -652,6 +656,8 @@
 	if(d.name && *d.name && strcmp(ent->name, d.name) != 0) {
 		if(strchr(d.name, '/') != nil)
 			error(Ebadchar);
+		if(strlen(d.name) >= sizeof(up->genbuf))
+			error(Egreg);
 		kstrdup(&ent->name, d.name);
 	}
 	poperror();
@@ -658,8 +664,6 @@
 	free(strs);
 
 	switch(sch->level){
-	default:
-		error(Egreg);
 	case Qcshr:
 		poperror();
 		qunlock(&shrslk);
--- a/sys/src/9/port/devsrv.c
+++ b/sys/src/9/port/devsrv.c
@@ -21,8 +21,18 @@
 static Srv	*srv;
 static int	qidpath;
 
+static Srv*
+srvlookup(char *name, ulong qidpath)
+{
+	Srv *sp;
+	for(sp = srv; sp; sp = sp->link)
+		if(sp->path == qidpath || (name && strcmp(sp->name, name) == 0))
+			return sp;
+	return nil;
+}
+
 static int
-srvgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
+srvgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
 {
 	Srv *sp;
 	Qid q;
@@ -33,14 +43,16 @@
 	}
 
 	qlock(&srvlk);
-	for(sp = srv; sp && s; sp = sp->link)
-		s--;
-
-	if(sp == 0) {
+	if(name)
+		sp = srvlookup(name, -1);
+	else {
+		for(sp = srv; sp && s; sp = sp->link)
+			s--;
+	}
+	if(sp == 0 || (strlen(sp->name) >= sizeof(up->genbuf))) {
 		qunlock(&srvlk);
 		return -1;
 	}
-
 	mkqid(&q, sp->path, 0, QTFILE);
 	/* make sure name string continues to exist after we release lock */
 	kstrcpy(up->genbuf, sp->name, sizeof up->genbuf);
@@ -67,16 +79,6 @@
 	return devwalk(c, nc, name, nname, 0, 0, srvgen);
 }
 
-static Srv*
-srvlookup(char *name, ulong qidpath)
-{
-	Srv *sp;
-	for(sp = srv; sp; sp = sp->link)
-		if(sp->path == qidpath || (name && strcmp(sp->name, name) == 0))
-			return sp;
-	return nil;
-}
-
 static int
 srvstat(Chan *c, uchar *db, int n)
 {
@@ -145,6 +147,9 @@
 	if(openmode(omode) != OWRITE)
 		error(Eperm);
 
+	if(strlen(name) >= sizeof(up->genbuf))
+		error(Egreg);
+
 	sp = smalloc(sizeof *sp);
 	sname = smalloc(strlen(name)+1);
 
@@ -260,6 +265,8 @@
 	if(d.name && *d.name && strcmp(sp->name, d.name) != 0) {
 		if(strchr(d.name, '/') != nil)
 			error(Ebadchar);
+		if(strlen(d.name) >= sizeof(up->genbuf))
+			error(Egreg);
 		kstrdup(&sp->name, d.name);
 	}
 	qunlock(&srvlk);