ref: bcaf52ebcde1933f4891c3e6f994951aa7c012f7
parent: 28452d3fe553c1c61321d1973ee5db57b4dcc3a5
author: cinap_lenrek <[email protected]>
date: Sun Nov 18 07:00:13 EST 2012
hjfs: ORCLOSE parent check, estrdup / erealloc, CHFNOPERM consistency check for write premission in the parent directory for open with ORCLOSE. honor CHFNOPERM not just in chancreat(), pikeshedd the error handling. added estrdup()/erealloc() that call sysfatal instead of returning nil.
--- a/sys/src/cmd/hjfs/auth.c
+++ b/sys/src/cmd/hjfs/auth.c
@@ -78,7 +78,7 @@
free(v.memb);
return;
}
- v.memb = realloc(v.memb, (v.nmemb + 1) * USERLEN);
+ v.memb = erealloc(v.memb, (v.nmemb + 1) * USERLEN);
strcpy(v.memb[v.nmemb++], r);
if(s == nil)
r = nil;
@@ -85,7 +85,7 @@
else
r = s + 1;
}
- *u = realloc(*u, (*nu + 1) * sizeof(PUser));
+ *u = erealloc(*u, (*nu + 1) * sizeof(PUser));
memcpy(&(*u)[(*nu)++], &v, sizeof(PUser));
}
@@ -137,7 +137,7 @@
nu = 0;
for(;;){
if((bufl & 1023) == 0)
- buf = realloc(buf, bufl + 1024);
+ buf = erealloc(buf, bufl + 1024);
rc = chanread(ch, buf + bufl, 1024, bufl);
if(rc < 0)
goto err;
@@ -411,7 +411,7 @@
gid++;
}
resort = 1;
- fs->udata = realloc(fs->udata, sizeof(User) * (fs->nudata + 1));
+ fs->udata = erealloc(fs->udata, sizeof(User) * (fs->nudata + 1));
u = fs->udata + fs->nudata++;
strcpy(u->name, argv[1]);
u->nmemb = 0;
@@ -447,9 +447,9 @@
if(u->memb[j] != v->uid)
goto erropt;
memmove(&u->memb[j], &u->memb[j + 1], sizeof(short) * (u->nmemb - j - 1));
- u->memb = realloc(u->memb, sizeof(short) * --u->nmemb);
+ u->memb = erealloc(u->memb, sizeof(short) * --u->nmemb);
}else{
- u->memb = realloc(u->memb, sizeof(short) * ++u->nmemb);
+ u->memb = erealloc(u->memb, sizeof(short) * ++u->nmemb);
memmove(&u->memb[j + 1], &u->memb[j], sizeof(short) * (u->nmemb - j - 1));
u->memb[j] = v->uid;
}
--- a/sys/src/cmd/hjfs/dev.c
+++ b/sys/src/cmd/hjfs/dev.c
@@ -80,7 +80,7 @@
werrstr("device file too short");
goto error;
}
- d->name = strdup(file);
+ d->name = estrdup(file);
for(b = d->buf; b < d->buf + BUFHASH + 1; b++)
b->dnext = b->dprev = b;
d->workr.l = &d->workl;
--- a/sys/src/cmd/hjfs/fns.h
+++ b/sys/src/cmd/hjfs/fns.h
@@ -1,4 +1,6 @@
void* emalloc(int);
+void* erealloc(void*,int);
+char* estrdup(char*);
void bufinit(int);
Buf* getbuf(Dev *, uvlong, int, int);
void putbuf(Buf *);
--- a/sys/src/cmd/hjfs/fs2.c
+++ b/sys/src/cmd/hjfs/fs2.c
@@ -110,32 +110,21 @@
Loc *l;
FLoc f;
- if((ch->flags & CHFRO) != 0){
- werrstr(Einval);
- return -1;
- }
+ b = nil;
+ l = nil;
chbegin(ch);
- if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0){
- chend(ch);
- return -1;
- }
- if(!namevalid(name) || ch->open != 0){
- werrstr(Einval);
- chend(ch);
- return -1;
- }
+ if(!namevalid(name) || ch->open != 0)
+ goto inval;
+ if((ch->flags & CHFRO) != 0)
+ goto inval;
+ if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
+ goto error;
if(isdir = ((perm & DMDIR) != 0))
- if((mode & (OWRITE | OEXEC | ORCLOSE | OTRUNC)) != 0){
- werrstr(Einval);
- chend(ch);
- return -1;
- }
+ if((mode & (OWRITE | OEXEC | ORCLOSE | OTRUNC)) != 0)
+ goto inval;
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
- if(b == nil){
- chend(ch);
- return -1;
- }
- l = nil;
+ if(b == nil)
+ goto error;
d = getdent(ch->loc, b);
if(d == nil)
goto error;
@@ -143,7 +132,7 @@
werrstr(Enotadir);
goto error;
}
- if((ch->flags & CHFNOPERM) == 0) /* for console */
+ if((ch->flags & CHFNOPERM) == 0)
if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
werrstr(Eperm);
goto error;
@@ -162,7 +151,6 @@
b->op |= BDELWRI;
putbuf(b);
b = nil;
-
if(willmodify(ch->fs, l, ch->flags & CHFNOLOCK) < 0)
goto error;
b = getbuf(ch->fs->d, l->blk, TDENTRY, 0);
@@ -185,7 +173,6 @@
}
b->op |= BDELWRI;
putbuf(b);
-
switch(mode & OEXEC){
case ORDWR:
ch->open |= CHREAD;
@@ -199,7 +186,8 @@
}
chend(ch);
return 1;
-
+inval:
+ werrstr(Einval);
error:
if(l != nil)
putloc(ch->fs, l, 0);
@@ -214,48 +202,46 @@
{
Buf *b;
Dentry *d;
- int isdir;
+ b = nil;
chbegin(ch);
- if(ch->open != 0){
- werrstr(Einval);
- chend(ch);
- return -1;
- }
+ if(ch->open != 0)
+ goto inval;
+ if((ch->flags & CHFRO) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0)
+ goto inval;
if((mode & OTRUNC) != 0)
- if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0){
- chend(ch);
- return -1;
- }
- b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
- if(b == nil){
- chend(ch);
- return -1;
+ if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
+ goto error;
+ if((mode & ORCLOSE) != 0){
+ if(ch->loc->next == nil)
+ goto inval;
+ b = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
+ if(b == nil)
+ goto error;
+ d = getdent(ch->loc->next, b);
+ if(d == nil)
+ goto error;
+ if((ch->flags & CHFNOPERM) == 0)
+ if(!permcheck(ch->fs, d, ch->uid, OWRITE))
+ goto perm;
+ putbuf(b);
}
+ b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
+ if(b == nil)
+ goto error;
d = getdent(ch->loc, b);
if(d == nil)
- goto err;
- if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC)){
- permerr:
- werrstr(Eperm);
- err:
- putbuf(b);
- chend(ch);
- return -1;
- }
+ goto error;
if((d->type & QTAPPEND) != 0)
mode &= ~OTRUNC;
- isdir = (d->type & QTDIR) != 0;
- if(isdir && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0){
- werrstr(Einval);
- goto err;
+ if((d->type & QTDIR) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0)
+ goto inval;
+ if((ch->flags & CHFNOPERM) == 0){
+ if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC))
+ goto perm;
+ if((mode & OTRUNC) != 0 && !permcheck(ch->fs, d, ch->uid, OWRITE))
+ goto perm;
}
- if((mode & OTRUNC) != 0 && !permcheck(ch->fs, d, ch->uid, OWRITE))
- goto permerr;
- if((ch->flags & CHFRO) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0){
- werrstr(Einval);
- goto err;
- }
if((ch->loc->type & QTEXCL) != 0){
qlock(&ch->loc->ex);
if(ch->loc->exlock == nil || ch->loc->lwrite < time(0) - EXCLDUR){
@@ -265,7 +251,7 @@
}else{
qunlock(&ch->loc->ex);
werrstr(Elocked);
- goto err;
+ goto error;
}
}
switch(mode & OEXEC){
@@ -289,6 +275,16 @@
putbuf(b);
chend(ch);
return 1;
+inval:
+ werrstr(Einval);
+ goto error;
+perm:
+ werrstr(Eperm);
+error:
+ if(b != nil)
+ putbuf(b);
+ chend(ch);
+ return -1;
}
static int
@@ -401,16 +397,15 @@
Buf *b, *c;
Dentry *d;
+ if((ch->open & CHREAD) == 0){
+ werrstr(Einval);
+ return -1;
+ }
chbegin(ch);
if((ch->loc->type & QTEXCL) != 0 && checklock(ch) < 0){
chend(ch);
return -1;
}
- if((ch->open & CHREAD) == 0){
- werrstr(Einval);
- chend(ch);
- return -1;
- }
if((ch->loc->Qid.type & QTDIR) != 0)
return chandirread(ch, buf, n, off);
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
@@ -419,11 +414,8 @@
return -1;
}
d = getdent(ch->loc, b);
- if(d == nil){
- putbuf(b);
- chend(ch);
- return -1;
- }
+ if(d == nil)
+ goto error;
if(off >= d->size)
n = 0;
else if(off + n > d->size)
@@ -460,7 +452,6 @@
putbuf(b);
chend(ch);
return n;
-
error:
putbuf(b);
chend(ch);
@@ -478,7 +469,7 @@
if(d->type & QTDIR)
di->length = 0;
if(buf == nil){
- di->name = strdup(d->name);
+ di->name = estrdup(d->name);
di->uid = uid2name(fs, d->uid, nil);
di->gid = uid2name(fs, d->gid, nil);
di->muid = uid2name(fs, d->muid, nil);
@@ -612,37 +603,33 @@
int rc;
Dentry *d;
- chbegin(ch);
rc = 1;
b = p = nil;
+ chbegin(ch);
if(ch->open & CHRCLOSE){
if((ch->flags & CHFRO) != 0)
goto inval;
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
- goto err;
- if(ch->loc->next == nil){
- inval:
- werrstr(Einval);
- err:
- rc = -1;
- goto done;
- }
+ goto error;
+ if(ch->loc->next == nil)
+ goto inval;
p = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
if(p == nil)
- goto err;
+ goto error;
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
if(b == nil)
- goto err;
+ goto error;
d = getdent(ch->loc->next, p);
if(d == nil)
- goto err;
- if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
- werrstr(Eperm);
- goto err;
- }
+ goto error;
+ if((ch->flags & CHFNOPERM) == 0)
+ if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
+ werrstr(Eperm);
+ goto error;
+ }
d = getdent(ch->loc, b);
if(d == nil)
- goto err;
+ goto error;
if((d->type & QTDIR) != 0 && findentry(ch->fs, ch->loc, b, nil, nil, ch->flags & CHFDUMP) != 0)
goto inval;
if((d->mode & DGONE) != 0)
@@ -675,6 +662,11 @@
chend(ch);
free(ch);
return rc;
+inval:
+ werrstr(Einval);
+error:
+ rc = -1;
+ goto done;
}
int
@@ -685,16 +677,12 @@
int isdir, owner, rc;
short nuid, ngid;
- if((ch->flags & CHFRO) != 0){
- werrstr(Einval);
- return -1;
- }
- chbegin(ch);
- if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0){
- chend(ch);
- return -1;
- }
b = pb = nil;
+ chbegin(ch);
+ if((ch->flags & CHFRO) != 0)
+ goto inval;
+ if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
+ goto error;
if(*di->name){
if(!namevalid(di->name) || ch->loc->next == nil)
goto inval;
@@ -704,8 +692,9 @@
d = getdent(ch->loc->next, pb);
if(d == nil)
goto error;
- if(!permcheck(ch->fs, d, ch->uid, OWRITE))
- goto perm;
+ if((ch->flags & CHFNOPERM) == 0)
+ if(!permcheck(ch->fs, d, ch->uid, OWRITE))
+ goto perm;
rc = findentry(ch->fs, ch->loc->next, pb, di->name, nil, ch->flags & CHFDUMP);
if(rc > 0)
werrstr(Eexists);
@@ -719,12 +708,16 @@
if(d == nil)
goto error;
isdir = (d->type & QTDIR) != 0;
- owner = ch->uid == d->uid || ingroup(ch->fs, ch->uid, d->gid, 1) || (ch->fs->flags & FSNOPERM) != 0;
+ owner = ch->uid == d->uid ||
+ ingroup(ch->fs, ch->uid, d->gid, 1) ||
+ (ch->fs->flags & FSNOPERM) != 0 ||
+ (ch->flags & CHFNOPERM) != 0;
if((uvlong)~di->length){
if(isdir && di->length != 0)
goto inval;
- if(di->length != d->size && !permcheck(ch->fs, d, ch->uid, OWRITE))
- goto perm;
+ if((ch->flags & CHFNOPERM) == 0)
+ if(di->length != d->size && !permcheck(ch->fs, d, ch->uid, OWRITE))
+ goto perm;
}
if((ulong)~di->atime)
goto inval;
@@ -742,7 +735,6 @@
goto inval;
if((nuid != NOUID || ngid != NOUID) && !owner)
goto perm;
-
if((uvlong)~di->length && !isdir){
trunc(ch->fs, ch->loc, b, di->length);
modified(ch, d);
@@ -767,7 +759,6 @@
putbuf(b);
chend(ch);
return 1;
-
inval:
werrstr(Einval);
goto error;
--- a/sys/src/cmd/hjfs/main.c
+++ b/sys/src/cmd/hjfs/main.c
@@ -27,6 +27,26 @@
return v;
}
+void*
+erealloc(void *v, int c)
+{
+ v = realloc(v, c);
+ if(v == 0)
+ sysfatal("realloc: %r");
+ setrealloctag(v, getcallerpc(&c));
+ return v;
+}
+
+char*
+estrdup(char *s)
+{
+ s = strdup(s);
+ if(s == 0)
+ sysfatal("strdup: %r");
+ setmalloctag(s, getcallerpc(&s));
+ return s;
+}
+
ThrData *
getthrdata(void)
{
@@ -88,8 +108,8 @@
case 'r': doream++; break;
case 'S': flags |= FSNOPERM | FSCHOWN; break;
case 's': stdio++; break;
- case 'f': file = strdup(EARGF(usage())); break;
- case 'n': service = strdup(EARGF(usage())); break;
+ case 'f': file = estrdup(EARGF(usage())); break;
+ case 'n': service = estrdup(EARGF(usage())); break;
case 'm':
nbuf = muldiv(atoi(EARGF(usage())), 1048576, sizeof(Buf));
if(nbuf < 10)