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); free(v.memb);
return; 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); strcpy(v.memb[v.nmemb++], r);
if(s == nil) if(s == nil)
r = nil; r = nil;
else else
r = s + 1; r = s + 1;
} }
*u = realloc(*u, (*nu + 1) * sizeof(PUser)); *u = erealloc(*u, (*nu + 1) * sizeof(PUser));
memcpy(&(*u)[(*nu)++], &v, sizeof(PUser)); memcpy(&(*u)[(*nu)++], &v, sizeof(PUser));
} }
@ -137,7 +137,7 @@ usersload(Fs *fs, Chan *ch)
nu = 0; nu = 0;
for(;;){ for(;;){
if((bufl & 1023) == 0) if((bufl & 1023) == 0)
buf = realloc(buf, bufl + 1024); buf = erealloc(buf, bufl + 1024);
rc = chanread(ch, buf + bufl, 1024, bufl); rc = chanread(ch, buf + bufl, 1024, bufl);
if(rc < 0) if(rc < 0)
goto err; goto err;
@ -411,7 +411,7 @@ cmdnewuser(int argc, char **argv)
gid++; gid++;
} }
resort = 1; 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++; u = fs->udata + fs->nudata++;
strcpy(u->name, argv[1]); strcpy(u->name, argv[1]);
u->nmemb = 0; u->nmemb = 0;
@ -447,9 +447,9 @@ found:
if(u->memb[j] != v->uid) if(u->memb[j] != v->uid)
goto erropt; goto erropt;
memmove(&u->memb[j], &u->memb[j + 1], sizeof(short) * (u->nmemb - j - 1)); 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{ }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)); memmove(&u->memb[j + 1], &u->memb[j], sizeof(short) * (u->nmemb - j - 1));
u->memb[j] = v->uid; u->memb[j] = v->uid;
} }

View file

@ -80,7 +80,7 @@ newdev(char *file)
werrstr("device file too short"); werrstr("device file too short");
goto error; goto error;
} }
d->name = strdup(file); d->name = estrdup(file);
for(b = d->buf; b < d->buf + BUFHASH + 1; b++) for(b = d->buf; b < d->buf + BUFHASH + 1; b++)
b->dnext = b->dprev = b; b->dnext = b->dprev = b;
d->workr.l = &d->workl; d->workr.l = &d->workl;

View file

@ -1,4 +1,6 @@
void* emalloc(int); void* emalloc(int);
void* erealloc(void*,int);
char* estrdup(char*);
void bufinit(int); void bufinit(int);
Buf* getbuf(Dev *, uvlong, int, int); Buf* getbuf(Dev *, uvlong, int, int);
void putbuf(Buf *); void putbuf(Buf *);

View file

@ -110,32 +110,21 @@ chancreat(Chan *ch, char *name, int perm, int mode)
Loc *l; Loc *l;
FLoc f; FLoc f;
if((ch->flags & CHFRO) != 0){ b = nil;
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;
}
l = 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); d = getdent(ch->loc, b);
if(d == nil) if(d == nil)
goto error; goto error;
@ -143,7 +132,7 @@ chancreat(Chan *ch, char *name, int perm, int mode)
werrstr(Enotadir); werrstr(Enotadir);
goto error; goto error;
} }
if((ch->flags & CHFNOPERM) == 0) /* for console */ if((ch->flags & CHFNOPERM) == 0)
if(!permcheck(ch->fs, d, ch->uid, OWRITE)){ if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
werrstr(Eperm); werrstr(Eperm);
goto error; goto error;
@ -162,7 +151,6 @@ chancreat(Chan *ch, char *name, int perm, int mode)
b->op |= BDELWRI; b->op |= BDELWRI;
putbuf(b); putbuf(b);
b = nil; b = nil;
if(willmodify(ch->fs, l, ch->flags & CHFNOLOCK) < 0) if(willmodify(ch->fs, l, ch->flags & CHFNOLOCK) < 0)
goto error; goto error;
b = getbuf(ch->fs->d, l->blk, TDENTRY, 0); 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; b->op |= BDELWRI;
putbuf(b); putbuf(b);
switch(mode & OEXEC){ switch(mode & OEXEC){
case ORDWR: case ORDWR:
ch->open |= CHREAD; ch->open |= CHREAD;
@ -199,7 +186,8 @@ chancreat(Chan *ch, char *name, int perm, int mode)
} }
chend(ch); chend(ch);
return 1; return 1;
inval:
werrstr(Einval);
error: error:
if(l != nil) if(l != nil)
putloc(ch->fs, l, 0); putloc(ch->fs, l, 0);
@ -214,47 +202,45 @@ chanopen(Chan *ch, int mode)
{ {
Buf *b; Buf *b;
Dentry *d; Dentry *d;
int isdir;
b = nil;
chbegin(ch); chbegin(ch);
if(ch->open != 0){ if(ch->open != 0)
werrstr(Einval); goto inval;
chend(ch); if((ch->flags & CHFRO) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0)
return -1; goto inval;
}
if((mode & OTRUNC) != 0) if((mode & OTRUNC) != 0)
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0){ if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
chend(ch); goto error;
return -1; if((mode & ORCLOSE) != 0){
} if(ch->loc->next == nil)
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0); goto inval;
if(b == nil){ b = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
chend(ch); if(b == nil)
return -1; 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); d = getdent(ch->loc, b);
if(d == nil) if(d == nil)
goto err; goto error;
if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC)){
permerr:
werrstr(Eperm);
err:
putbuf(b);
chend(ch);
return -1;
}
if((d->type & QTAPPEND) != 0) if((d->type & QTAPPEND) != 0)
mode &= ~OTRUNC; mode &= ~OTRUNC;
isdir = (d->type & QTDIR) != 0; if((d->type & QTDIR) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0)
if(isdir && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0){ goto inval;
werrstr(Einval); if((ch->flags & CHFNOPERM) == 0){
goto err; if(!permcheck(ch->fs, d, ch->uid, mode & OEXEC))
} goto perm;
if((mode & OTRUNC) != 0 && !permcheck(ch->fs, d, ch->uid, OWRITE)) if((mode & OTRUNC) != 0 && !permcheck(ch->fs, d, ch->uid, OWRITE))
goto permerr; goto perm;
if((ch->flags & CHFRO) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0){
werrstr(Einval);
goto err;
} }
if((ch->loc->type & QTEXCL) != 0){ if((ch->loc->type & QTEXCL) != 0){
qlock(&ch->loc->ex); qlock(&ch->loc->ex);
@ -265,7 +251,7 @@ chanopen(Chan *ch, int mode)
}else{ }else{
qunlock(&ch->loc->ex); qunlock(&ch->loc->ex);
werrstr(Elocked); werrstr(Elocked);
goto err; goto error;
} }
} }
switch(mode & OEXEC){ switch(mode & OEXEC){
@ -289,6 +275,16 @@ chanopen(Chan *ch, int mode)
putbuf(b); putbuf(b);
chend(ch); chend(ch);
return 1; return 1;
inval:
werrstr(Einval);
goto error;
perm:
werrstr(Eperm);
error:
if(b != nil)
putbuf(b);
chend(ch);
return -1;
} }
static int static int
@ -401,13 +397,12 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
Buf *b, *c; Buf *b, *c;
Dentry *d; Dentry *d;
chbegin(ch);
if((ch->loc->type & QTEXCL) != 0 && checklock(ch) < 0){
chend(ch);
return -1;
}
if((ch->open & CHREAD) == 0){ if((ch->open & CHREAD) == 0){
werrstr(Einval); werrstr(Einval);
return -1;
}
chbegin(ch);
if((ch->loc->type & QTEXCL) != 0 && checklock(ch) < 0){
chend(ch); chend(ch);
return -1; return -1;
} }
@ -419,11 +414,8 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
return -1; return -1;
} }
d = getdent(ch->loc, b); d = getdent(ch->loc, b);
if(d == nil){ if(d == nil)
putbuf(b); goto error;
chend(ch);
return -1;
}
if(off >= d->size) if(off >= d->size)
n = 0; n = 0;
else if(off + n > d->size) else if(off + n > d->size)
@ -460,7 +452,6 @@ chanread(Chan *ch, void *buf, ulong n, uvlong off)
putbuf(b); putbuf(b);
chend(ch); chend(ch);
return n; return n;
error: error:
putbuf(b); putbuf(b);
chend(ch); chend(ch);
@ -478,7 +469,7 @@ statbuf(Fs *fs, Dentry *d, Dir *di, char *buf)
if(d->type & QTDIR) if(d->type & QTDIR)
di->length = 0; di->length = 0;
if(buf == nil){ if(buf == nil){
di->name = strdup(d->name); di->name = estrdup(d->name);
di->uid = uid2name(fs, d->uid, nil); di->uid = uid2name(fs, d->uid, nil);
di->gid = uid2name(fs, d->gid, nil); di->gid = uid2name(fs, d->gid, nil);
di->muid = uid2name(fs, d->muid, nil); di->muid = uid2name(fs, d->muid, nil);
@ -612,37 +603,33 @@ chanclunk(Chan *ch)
int rc; int rc;
Dentry *d; Dentry *d;
chbegin(ch);
rc = 1; rc = 1;
b = p = nil; b = p = nil;
chbegin(ch);
if(ch->open & CHRCLOSE){ if(ch->open & CHRCLOSE){
if((ch->flags & CHFRO) != 0) if((ch->flags & CHFRO) != 0)
goto inval; goto inval;
if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0) if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0)
goto err; goto error;
if(ch->loc->next == nil){ if(ch->loc->next == nil)
inval: goto inval;
werrstr(Einval);
err:
rc = -1;
goto done;
}
p = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0); p = getbuf(ch->fs->d, ch->loc->next->blk, TDENTRY, 0);
if(p == nil) if(p == nil)
goto err; goto error;
b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0); b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0);
if(b == nil) if(b == nil)
goto err; goto error;
d = getdent(ch->loc->next, p); d = getdent(ch->loc->next, p);
if(d == nil) if(d == nil)
goto err; goto error;
if(!permcheck(ch->fs, d, ch->uid, OWRITE)){ if((ch->flags & CHFNOPERM) == 0)
werrstr(Eperm); if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
goto err; werrstr(Eperm);
} goto error;
}
d = getdent(ch->loc, b); d = getdent(ch->loc, b);
if(d == nil) if(d == nil)
goto err; goto error;
if((d->type & QTDIR) != 0 && findentry(ch->fs, ch->loc, b, nil, nil, ch->flags & CHFDUMP) != 0) if((d->type & QTDIR) != 0 && findentry(ch->fs, ch->loc, b, nil, nil, ch->flags & CHFDUMP) != 0)
goto inval; goto inval;
if((d->mode & DGONE) != 0) if((d->mode & DGONE) != 0)
@ -675,6 +662,11 @@ done:
chend(ch); chend(ch);
free(ch); free(ch);
return rc; return rc;
inval:
werrstr(Einval);
error:
rc = -1;
goto done;
} }
int int
@ -685,16 +677,12 @@ chanwstat(Chan *ch, Dir *di)
int isdir, owner, rc; int isdir, owner, rc;
short nuid, ngid; 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; 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(*di->name){
if(!namevalid(di->name) || ch->loc->next == nil) if(!namevalid(di->name) || ch->loc->next == nil)
goto inval; goto inval;
@ -704,8 +692,9 @@ chanwstat(Chan *ch, Dir *di)
d = getdent(ch->loc->next, pb); d = getdent(ch->loc->next, pb);
if(d == nil) if(d == nil)
goto error; goto error;
if(!permcheck(ch->fs, d, ch->uid, OWRITE)) if((ch->flags & CHFNOPERM) == 0)
goto perm; if(!permcheck(ch->fs, d, ch->uid, OWRITE))
goto perm;
rc = findentry(ch->fs, ch->loc->next, pb, di->name, nil, ch->flags & CHFDUMP); rc = findentry(ch->fs, ch->loc->next, pb, di->name, nil, ch->flags & CHFDUMP);
if(rc > 0) if(rc > 0)
werrstr(Eexists); werrstr(Eexists);
@ -719,12 +708,16 @@ chanwstat(Chan *ch, Dir *di)
if(d == nil) if(d == nil)
goto error; goto error;
isdir = (d->type & QTDIR) != 0; 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((uvlong)~di->length){
if(isdir && di->length != 0) if(isdir && di->length != 0)
goto inval; goto inval;
if(di->length != d->size && !permcheck(ch->fs, d, ch->uid, OWRITE)) if((ch->flags & CHFNOPERM) == 0)
goto perm; if(di->length != d->size && !permcheck(ch->fs, d, ch->uid, OWRITE))
goto perm;
} }
if((ulong)~di->atime) if((ulong)~di->atime)
goto inval; goto inval;
@ -742,7 +735,6 @@ chanwstat(Chan *ch, Dir *di)
goto inval; goto inval;
if((nuid != NOUID || ngid != NOUID) && !owner) if((nuid != NOUID || ngid != NOUID) && !owner)
goto perm; goto perm;
if((uvlong)~di->length && !isdir){ if((uvlong)~di->length && !isdir){
trunc(ch->fs, ch->loc, b, di->length); trunc(ch->fs, ch->loc, b, di->length);
modified(ch, d); modified(ch, d);
@ -767,7 +759,6 @@ chanwstat(Chan *ch, Dir *di)
putbuf(b); putbuf(b);
chend(ch); chend(ch);
return 1; return 1;
inval: inval:
werrstr(Einval); werrstr(Einval);
goto error; goto error;

View file

@ -27,6 +27,26 @@ emalloc(int c)
return v; 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 * ThrData *
getthrdata(void) getthrdata(void)
{ {
@ -88,8 +108,8 @@ threadmain(int argc, char **argv)
case 'r': doream++; break; case 'r': doream++; break;
case 'S': flags |= FSNOPERM | FSCHOWN; break; case 'S': flags |= FSNOPERM | FSCHOWN; break;
case 's': stdio++; break; case 's': stdio++; break;
case 'f': file = strdup(EARGF(usage())); break; case 'f': file = estrdup(EARGF(usage())); break;
case 'n': service = strdup(EARGF(usage())); break; case 'n': service = estrdup(EARGF(usage())); break;
case 'm': case 'm':
nbuf = muldiv(atoi(EARGF(usage())), 1048576, sizeof(Buf)); nbuf = muldiv(atoi(EARGF(usage())), 1048576, sizeof(Buf));
if(nbuf < 10) if(nbuf < 10)