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:
parent
28452d3fe5
commit
bcaf52ebcd
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
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){
|
||||
chend(ch);
|
||||
return -1;
|
||||
}
|
||||
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 permerr;
|
||||
if((ch->flags & CHFRO) != 0 && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0){
|
||||
werrstr(Einval);
|
||||
goto err;
|
||||
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;
|
||||
goto error;
|
||||
if((ch->flags & CHFNOPERM) == 0)
|
||||
if(!permcheck(ch->fs, d, ch->uid, OWRITE)){
|
||||
werrstr(Eperm);
|
||||
goto err;
|
||||
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,6 +692,7 @@ chanwstat(Chan *ch, Dir *di)
|
|||
d = getdent(ch->loc->next, pb);
|
||||
if(d == nil)
|
||||
goto error;
|
||||
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);
|
||||
|
@ -719,10 +708,14 @@ 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((ch->flags & CHFNOPERM) == 0)
|
||||
if(di->length != d->size && !permcheck(ch->fs, d, ch->uid, OWRITE))
|
||||
goto perm;
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue