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.
This commit is contained in:
cinap_lenrek 2012-11-18 12:00:13 +01:00
parent 28452d3fe5
commit bcaf52ebcd
5 changed files with 130 additions and 117 deletions

View file

@ -78,14 +78,14 @@ usersparseline(char *l, PUser **u, int *nu)
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;
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 @@ usersload(Fs *fs, Chan *ch)
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 @@ cmdnewuser(int argc, char **argv)
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 @@ found:
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;
}

View file

@ -80,7 +80,7 @@ newdev(char *file)
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;

View file

@ -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 *);

View file

@ -110,32 +110,21 @@ chancreat(Chan *ch, char *name, int perm, int mode)
Loc *l;
FLoc f;
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;
}
if(!namevalid(name) || ch->open != 0){
werrstr(Einval);
chend(ch);
return -1;
}
if(isdir = ((perm & DMDIR) != 0))
if((mode & (OWRITE | OEXEC | ORCLOSE | OTRUNC)) != 0){
werrstr(Einval);
chend(ch);
return -1;
}
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
if(b == nil){
chend(ch);
return -1;
}
b = nil;
l = nil;
chbegin(ch);
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)
goto inval;
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
if(b == nil)
goto error;
d = getdent(ch->loc, b);
if(d == nil)
goto error;
@ -143,7 +132,7 @@ chancreat(Chan *ch, char *name, int perm, int mode)
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 @@ chancreat(Chan *ch, char *name, int perm, int mode)
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 @@ chancreat(Chan *ch, char *name, int perm, int mode)
}
b->op |= BDELWRI;
putbuf(b);
switch(mode & OEXEC){
case ORDWR:
ch->open |= CHREAD;
@ -199,7 +186,8 @@ chancreat(Chan *ch, char *name, int perm, int mode)
}
chend(ch);
return 1;
inval:
werrstr(Einval);
error:
if(l != nil)
putloc(ch->fs, l, 0);
@ -214,47 +202,45 @@ chanopen(Chan *ch, int mode)
{
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((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((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((ch->loc->type & QTEXCL) != 0){
qlock(&ch->loc->ex);
@ -265,7 +251,7 @@ chanopen(Chan *ch, int mode)
}else{
qunlock(&ch->loc->ex);
werrstr(Elocked);
goto err;
goto error;
}
}
switch(mode & OEXEC){
@ -289,6 +275,16 @@ chanopen(Chan *ch, int mode)
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,13 +397,12 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
Buf *b, *c;
Dentry *d;
chbegin(ch);
if((ch->loc->type & QTEXCL) != 0 && checklock(ch) < 0){
chend(ch);
return -1;
}
if((ch->open & CHREAD) == 0){
werrstr(Einval);
return -1;
}
chbegin(ch);
if((ch->loc->type & QTEXCL) != 0 && checklock(ch) < 0){
chend(ch);
return -1;
}
@ -419,11 +414,8 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
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 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
putbuf(b);
chend(ch);
return n;
error:
putbuf(b);
chend(ch);
@ -478,7 +469,7 @@ statbuf(Fs *fs, Dentry *d, Dir *di, char *buf)
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 @@ chanclunk(Chan *ch)
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 @@ done:
chend(ch);
free(ch);
return rc;
inval:
werrstr(Einval);
error:
rc = -1;
goto done;
}
int
@ -685,16 +677,12 @@ chanwstat(Chan *ch, Dir *di)
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 @@ chanwstat(Chan *ch, Dir *di)
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 @@ chanwstat(Chan *ch, Dir *di)
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 @@ chanwstat(Chan *ch, Dir *di)
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 @@ chanwstat(Chan *ch, Dir *di)
putbuf(b);
chend(ch);
return 1;
inval:
werrstr(Einval);
goto error;

View file

@ -27,6 +27,26 @@ emalloc(int c)
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 @@ threadmain(int argc, char **argv)
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)