changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: devip: fix permission checking

changeset 7395: 4b1fae89dd27
parent 7394: ecaa7c8abd9c
child 7396: 8eff72134197
author: cinap_lenrek@felloff.net
date: Sat, 21 Sep 2019 23:28:37 +0200
files: sys/src/9/ip/devip.c
description: 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...
     1.1--- a/sys/src/9/ip/devip.c
     1.2+++ b/sys/src/9/ip/devip.c
     1.3@@ -355,7 +355,7 @@ ipopen(Chan* c, int omode)
     1.4 	default:
     1.5 		break;
     1.6 	case Qndb:
     1.7-		if(omode & (OWRITE|OTRUNC) && !iseve())
     1.8+		if((omode & (OWRITE|OTRUNC)) != 0 && !iseve())
     1.9 			error(Eperm);
    1.10 		if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC))
    1.11 			f->ndb[0] = 0;
    1.12@@ -412,15 +412,12 @@ ipopen(Chan* c, int omode)
    1.13 			qunlock(p);
    1.14 			nexterror();
    1.15 		}
    1.16-		if((perm & (cv->perm>>6)) != perm) {
    1.17-			if(strcmp(ATTACHER(c), cv->owner) != 0)
    1.18-				error(Eperm);
    1.19-		 	if((perm & cv->perm) != perm)
    1.20-				error(Eperm);
    1.21+		if(strcmp(ATTACHER(c), cv->owner) == 0)
    1.22+			perm <<= 6;
    1.23+		if((perm & cv->perm) != perm && !iseve())
    1.24+			error(Eperm);
    1.25 
    1.26-		}
    1.27-		cv->inuse++;
    1.28-		if(cv->inuse == 1){
    1.29+		if(++cv->inuse == 1){
    1.30 			kstrdup(&cv->owner, ATTACHER(c));
    1.31 			cv->perm = 0660;
    1.32 		}
    1.33@@ -430,24 +427,26 @@ ipopen(Chan* c, int omode)
    1.34 		break;
    1.35 	case Qlisten:
    1.36 		cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
    1.37-		if((perm & (cv->perm>>6)) != perm) {
    1.38-			if(strcmp(ATTACHER(c), cv->owner) != 0)
    1.39-				error(Eperm);
    1.40-		 	if((perm & cv->perm) != perm)
    1.41-				error(Eperm);
    1.42-
    1.43+		qlock(cv);
    1.44+		if(waserror()){
    1.45+			qunlock(cv);
    1.46+			nexterror();
    1.47 		}
    1.48+		if(strcmp(ATTACHER(c), cv->owner) == 0)
    1.49+			perm <<= 6;
    1.50+		if((perm & cv->perm) != perm && !iseve())
    1.51+			error(Eperm);
    1.52 
    1.53 		if(cv->state != Announced)
    1.54 			error("not announced");
    1.55 
    1.56+		cv->inuse++;
    1.57+		qunlock(cv);
    1.58+		poperror();
    1.59 		if(waserror()){
    1.60 			closeconv(cv);
    1.61 			nexterror();
    1.62 		}
    1.63-		qlock(cv);
    1.64-		cv->inuse++;
    1.65-		qunlock(cv);
    1.66 
    1.67 		nc = nil;
    1.68 		while(nc == nil) {
    1.69@@ -469,7 +468,6 @@ ipopen(Chan* c, int omode)
    1.70 			if(nc != nil){
    1.71 				cv->incall = nc->next;
    1.72 				mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
    1.73-				kstrdup(&cv->owner, ATTACHER(c));
    1.74 			}
    1.75 			qunlock(cv);
    1.76 
    1.77@@ -502,10 +500,9 @@ ipremove(Chan*)
    1.78 static int
    1.79 ipwstat(Chan *c, uchar *dp, int n)
    1.80 {
    1.81-	Dir d;
    1.82+	Dir *dir;
    1.83 	Conv *cv;
    1.84 	Fs *f;
    1.85-	Proto *p;
    1.86 
    1.87 	f = ipfs[c->dev];
    1.88 	switch(TYPE(c->qid)) {
    1.89@@ -517,16 +514,36 @@ ipwstat(Chan *c, uchar *dp, int n)
    1.90 		break;
    1.91 	}
    1.92 
    1.93-	n = convM2D(dp, n, &d, nil);
    1.94-	if(n > 0){
    1.95-		p = f->p[PROTO(c->qid)];
    1.96-		cv = p->conv[CONV(c->qid)];
    1.97-		if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
    1.98+	dir = smalloc(sizeof(Dir)+n);
    1.99+	if(waserror()){
   1.100+		free(dir);
   1.101+		nexterror();
   1.102+	}
   1.103+	n = convM2D(dp, n, &dir[0], (char*)&dir[1]);
   1.104+	if(n == 0)
   1.105+		error(Eshortstat);
   1.106+
   1.107+	cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
   1.108+	qlock(cv);
   1.109+	if(waserror()){
   1.110+		qunlock(cv);
   1.111+		nexterror();
   1.112+	}
   1.113+	if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
   1.114+		error(Eperm);
   1.115+	if(!emptystr(dir->uid)){
   1.116+		if(strcmp(dir->uid, commonuser()) != 0 && !iseve())
   1.117 			error(Eperm);
   1.118-		if(d.uid[0])
   1.119-			kstrdup(&cv->owner, d.uid);
   1.120-		cv->perm = d.mode & 0777;
   1.121+		kstrdup(&cv->owner, dir->uid);
   1.122 	}
   1.123+	if(dir->mode != ~0UL)
   1.124+		cv->perm = dir->mode & 0666;
   1.125+	qunlock(cv);
   1.126+	poperror();
   1.127+
   1.128+	free(dir);
   1.129+	poperror();
   1.130+
   1.131 	return n;
   1.132 }
   1.133 
   1.134@@ -1394,7 +1411,7 @@ Fsnewcall(Conv *c, uchar *raddr, ushort 
   1.135 	}
   1.136 
   1.137 	/* find a free conversation */
   1.138-	nc = Fsprotoclone(c->p, network);
   1.139+	nc = Fsprotoclone(c->p, c->owner);
   1.140 	if(nc == nil) {
   1.141 		qunlock(c);
   1.142 		return nil;