From bcaf52ebcde1933f4891c3e6f994951aa7c012f7 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 18 Nov 2012 12:00:13 +0100 Subject: [PATCH] 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. --- sys/src/cmd/hjfs/auth.c | 12 +-- sys/src/cmd/hjfs/dev.c | 2 +- sys/src/cmd/hjfs/fns.h | 2 + sys/src/cmd/hjfs/fs2.c | 207 +++++++++++++++++++--------------------- sys/src/cmd/hjfs/main.c | 24 ++++- 5 files changed, 130 insertions(+), 117 deletions(-) diff --git a/sys/src/cmd/hjfs/auth.c b/sys/src/cmd/hjfs/auth.c index a72b0e397..1e032de25 100644 --- a/sys/src/cmd/hjfs/auth.c +++ b/sys/src/cmd/hjfs/auth.c @@ -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; } diff --git a/sys/src/cmd/hjfs/dev.c b/sys/src/cmd/hjfs/dev.c index 9afdeba16..45c3a9e09 100644 --- a/sys/src/cmd/hjfs/dev.c +++ b/sys/src/cmd/hjfs/dev.c @@ -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; diff --git a/sys/src/cmd/hjfs/fns.h b/sys/src/cmd/hjfs/fns.h index 26e525e27..c75ff8e9f 100644 --- 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 *); diff --git a/sys/src/cmd/hjfs/fs2.c b/sys/src/cmd/hjfs/fs2.c index d2fd918a4..95b6a1997 100644 --- a/sys/src/cmd/hjfs/fs2.c +++ b/sys/src/cmd/hjfs/fs2.c @@ -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; diff --git a/sys/src/cmd/hjfs/main.c b/sys/src/cmd/hjfs/main.c index 85c06ed6b..6a6c4697e 100644 --- a/sys/src/cmd/hjfs/main.c +++ b/sys/src/cmd/hjfs/main.c @@ -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)