shithub: riscv

Download patch

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)