ref: 7d9677ed9930b8509a4dc6ff3bf40332e4b0e013
parent: bffaa325f1fbbb3edf7048f132303cf4f6c41634
author: cinap_lenrek <cinap_lenrek@felloff.net>
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;
--
⑨