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;