shithub: riscv

Download patch

ref: 5993760e143bfab2a29fa3d5a4655ed5842fd21f
parent: b56909157f0cd2491cd2918f7923676f22b5707c
author: cinap_lenrek <[email protected]>
date: Sat Sep 21 19:28:37 EDT 2019

devip: fix permission checking

permission checking had the "other" and "owner" bits swapped plus incoming
connections where always owned by "network" instead of the owner of
the listening connection. also, ipwstat() was not effective as the uid
strings where not parsed.

this fixes the permission checks for data/ctl/err file and makes incoming
connections inherit the owner from the listening connection.

we also allow ipwstat() to change ownership to the commonuser() or anyone
if we are eve.

we might have to add additional restrictions for none at a later point...

--- a/sys/src/9/ip/devip.c
+++ b/sys/src/9/ip/devip.c
@@ -355,7 +355,7 @@
 	default:
 		break;
 	case Qndb:
-		if(omode & (OWRITE|OTRUNC) && !iseve())
+		if((omode & (OWRITE|OTRUNC)) != 0 && !iseve())
 			error(Eperm);
 		if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC))
 			f->ndb[0] = 0;
@@ -412,15 +412,12 @@
 			qunlock(p);
 			nexterror();
 		}
-		if((perm & (cv->perm>>6)) != perm) {
-			if(strcmp(ATTACHER(c), cv->owner) != 0)
-				error(Eperm);
-		 	if((perm & cv->perm) != perm)
-				error(Eperm);
+		if(strcmp(ATTACHER(c), cv->owner) == 0)
+			perm <<= 6;
+		if((perm & cv->perm) != perm && !iseve())
+			error(Eperm);
 
-		}
-		cv->inuse++;
-		if(cv->inuse == 1){
+		if(++cv->inuse == 1){
 			kstrdup(&cv->owner, ATTACHER(c));
 			cv->perm = 0660;
 		}
@@ -430,24 +427,26 @@
 		break;
 	case Qlisten:
 		cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
-		if((perm & (cv->perm>>6)) != perm) {
-			if(strcmp(ATTACHER(c), cv->owner) != 0)
-				error(Eperm);
-		 	if((perm & cv->perm) != perm)
-				error(Eperm);
-
+		qlock(cv);
+		if(waserror()){
+			qunlock(cv);
+			nexterror();
 		}
+		if(strcmp(ATTACHER(c), cv->owner) == 0)
+			perm <<= 6;
+		if((perm & cv->perm) != perm && !iseve())
+			error(Eperm);
 
 		if(cv->state != Announced)
 			error("not announced");
 
+		cv->inuse++;
+		qunlock(cv);
+		poperror();
 		if(waserror()){
 			closeconv(cv);
 			nexterror();
 		}
-		qlock(cv);
-		cv->inuse++;
-		qunlock(cv);
 
 		nc = nil;
 		while(nc == nil) {
@@ -469,7 +468,6 @@
 			if(nc != nil){
 				cv->incall = nc->next;
 				mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
-				kstrdup(&cv->owner, ATTACHER(c));
 			}
 			qunlock(cv);
 
@@ -502,10 +500,9 @@
 static int
 ipwstat(Chan *c, uchar *dp, int n)
 {
-	Dir d;
+	Dir *dir;
 	Conv *cv;
 	Fs *f;
-	Proto *p;
 
 	f = ipfs[c->dev];
 	switch(TYPE(c->qid)) {
@@ -517,16 +514,36 @@
 		break;
 	}
 
-	n = convM2D(dp, n, &d, nil);
-	if(n > 0){
-		p = f->p[PROTO(c->qid)];
-		cv = p->conv[CONV(c->qid)];
-		if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
+	dir = smalloc(sizeof(Dir)+n);
+	if(waserror()){
+		free(dir);
+		nexterror();
+	}
+	n = convM2D(dp, n, &dir[0], (char*)&dir[1]);
+	if(n == 0)
+		error(Eshortstat);
+
+	cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
+	qlock(cv);
+	if(waserror()){
+		qunlock(cv);
+		nexterror();
+	}
+	if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
+		error(Eperm);
+	if(!emptystr(dir->uid)){
+		if(strcmp(dir->uid, commonuser()) != 0 && !iseve())
 			error(Eperm);
-		if(d.uid[0])
-			kstrdup(&cv->owner, d.uid);
-		cv->perm = d.mode & 0777;
+		kstrdup(&cv->owner, dir->uid);
 	}
+	if(dir->mode != ~0UL)
+		cv->perm = dir->mode & 0666;
+	qunlock(cv);
+	poperror();
+
+	free(dir);
+	poperror();
+
 	return n;
 }
 
@@ -1394,7 +1411,7 @@
 	}
 
 	/* find a free conversation */
-	nc = Fsprotoclone(c->p, network);
+	nc = Fsprotoclone(c->p, c->owner);
 	if(nc == nil) {
 		qunlock(c);
 		return nil;