git: plan9front

Download patch

ref: 15341e1116cd0fe31dcf3fb989d2004a8d3a3e8f
parent: d8cf26110d5c98a0568260caf772ed8c10b2a395
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Aug 30 14:46:50 EDT 2024

gefs: fix Fid refcounting bugs

The AuthRpc was attached to the Fid, but this doesnt
work as it does not handle dupfid() properly.

Instead attach the AuthRpc to the directory entry,
which is refcounted.

The dupfid() function retuns the new Fid* struct with
an extra reference. If we don't use it, we have to
putfid() it.

Use ainc()/adec() consistently and dont mix it with
agetl().

--- a/sys/src/cmd/gefs/blk.c
+++ b/sys/src/cmd/gefs/blk.c
@@ -806,7 +806,7 @@
 		p = agetp(&fs->limbo[ge]);
 		l->next = p;
 		if(acasp(&fs->limbo[ge], p, l)){
-			aincl(&fs->nlimbo, 1);
+			ainc(&fs->nlimbo);
 			break;
 		}
 	}
@@ -955,7 +955,7 @@
 		default:
 			abort();
 		}
-		aincl(&fs->nlimbo, -1);
+		adec(&fs->nlimbo);
 	}
 }
 
@@ -1082,7 +1082,7 @@
 
 	q = p;
 	if(waserror()){
-		aincl(&fs->rdonly, 1);
+		ainc(&fs->rdonly);
 		fprint(2, "error syncing: %s\n", errmsg());
 		return;
 	}
--- a/sys/src/cmd/gefs/check.c
+++ b/sys/src/cmd/gefs/check.c
@@ -255,7 +255,7 @@
 	Blk *b;
 
 	ok = 1;
-	aincl(&fs->rdonly, 1);
+	ainc(&fs->rdonly);
 	epochwait();
 	if(waserror()){
 		fprint(fd, "error checking %s\n", errmsg());
@@ -300,7 +300,7 @@
 		poperror();
 	}
 	btexit(&s);
-	aincl(&fs->rdonly, -1);
+	adec(&fs->rdonly);
 	poperror();
 	return ok;
 }
--- a/sys/src/cmd/gefs/dat.h
+++ b/sys/src/cmd/gefs/dat.h
@@ -629,7 +629,10 @@
 	char	gone;
 	char	trunc;
 
-	char	buf[Maxent];
+	union {
+		char	buf[Maxent];
+		void	*auth;
+	};
 };
 
 struct Mount {
@@ -685,7 +688,6 @@
 	Dent	*dent;	/* (pqid, name) ref, modified on rename */
 	Dent	*dir;
 	Amsg	*rclose;	
-	void	*auth;
 
 	u32int	fid;
 	vlong	qpath;
--- a/sys/src/cmd/gefs/fs.c
+++ b/sys/src/cmd/gefs/fs.c
@@ -12,6 +12,8 @@
 static void	rerror(Fmsg*, char*, ...);
 static void	clunkfid(Conn*, Fid*, Amsg**);
 
+static void	authfree(AuthRpc*);
+
 int
 walk1(Tree *t, vlong up, char *name, Qid *qid, vlong *len)
 {
@@ -228,7 +230,7 @@
 			return;
 		}
 		if(t->nlbl == 1 && t->nref <= 1 && t->succ == -1){
-			aincl(&t->memref, 1);
+			ainc(&t->memref);
 			*tp = t;
 		}
 		delsnap(t, t->succ, a->old);
@@ -676,8 +678,11 @@
 
 	if(de == nil)
 		return;
-	if(de->qid.type & QTAUTH && adec(&de->ref) == 0){
-		free(de);
+	if(de->qid.type & QTAUTH){
+		if(adec(&de->ref) == 0){
+			authfree(de->auth);
+			free(de);
+		}
 		return;
 	}
 	lock(&mnt->dtablk);
@@ -797,8 +802,8 @@
 		f->dent->gone = 1;
 		wunlock(f->dent);
 
-		aincl(&f->dent->ref, 1);
-		aincl(&f->mnt->ref, 1);
+		ainc(&f->dent->ref);
+		ainc(&f->mnt->ref);
 		(*ao)->op = AOrclose;
 		(*ao)->mnt = f->mnt;
 		(*ao)->qpath = f->qpath;
@@ -837,7 +842,7 @@
 		free(m);
 		return -1;
 	}
-	aincl(&c->ref, 1);
+	ainc(&c->ref);
 	m->conn = c;
 	m->sz = sz;
 	PBIT32(m->buf, sz);
@@ -870,7 +875,7 @@
 	respond(m, &r);
 }
 
-void
+static void
 authfree(AuthRpc *auth)
 {
 	AuthRpc *rpc;
@@ -911,7 +916,7 @@
 	AuthRpc *rpc;
 	User *u;
 
-	if((rpc = f->auth) == nil)
+	if((f->dir->qid.type & QTAUTH) == 0 || (rpc = f->dir->auth) == nil)
 		error(Etype);
 
 	switch(auth_rpc(rpc, "read", nil, 0)){
@@ -947,7 +952,7 @@
 {
 	AuthRpc *rpc;
 
-	if((rpc = f->auth) == nil)
+	if((f->dir->qid.type & QTAUTH) == 0 || (rpc = f->dir->auth) == nil)
 		error(Etype);
 	if(auth_rpc(rpc, "write", data, count) != ARok)
 		error(Ebotch);
@@ -961,7 +966,7 @@
 {
 	Dent *de;
 	Fcall r;
-	Fid f;
+	Fid f, *nf;
 
 	if(fs->noauth){
 		rerror(m, Eauth);
@@ -976,6 +981,11 @@
 		return;
 	}
 	memset(de, 0, sizeof(Dent));
+	de->auth = authnew();
+	if(de->auth == nil){
+		rerror(m, errmsg());
+		return;
+	}
 	de->ref = 0;
 	de->qid.type = QTAUTH;
 	de->qid.path = aincv(&fs->nextqid, 1);
@@ -997,9 +1007,10 @@
 	f.duid = -1;
 	f.dgid = -1;
 	f.dmode = 0600;
-	f.auth = authnew();
-	if(dupfid(m->conn, m->afid, &f) == nil){
+	nf = dupfid(m->conn, m->afid, &f);
+	if(nf == nil){
 		rerror(m, Efid);
+		authfree(de->auth);
 		free(de);
 		return;
 	}
@@ -1006,6 +1017,7 @@
 	r.type = Rauth;
 	r.aqid = de->qid;
 	respond(m, &r);
+	putfid(nf);
 }
 
 static int
@@ -1105,7 +1117,7 @@
 	Xdir d;
 	Kvp kv;
 	Key dk;
-	Fid f, *af;
+	Fid f, *af, *nf;
 	int uid;
 
 	de = nil;
@@ -1188,12 +1200,13 @@
 	}
 	if(strcmp(aname, "dump") == 0)
 		f.fromdump = 1;
-	if(dupfid(m->conn, m->fid, &f) == nil)
+	nf = dupfid(m->conn, m->fid, &f);
+	if(nf == nil)
 		error(Efid);
-
 	r.type = Rattach;
 	r.qid = d.qid;
 	respond(m, &r);
+	putfid(nf);
 	poperror();
 
 
@@ -1307,6 +1320,12 @@
 		if((f = dupfid(m->conn, m->newfid, o)) == nil)
 			error(Efid);
 		putfid(o);
+		poperror();
+		if(waserror()){
+			rerror(m, errmsg());
+			putfid(f);
+			return;
+		}
 	}
 	if(i > 0 && i == m->nwname){
 		lock(f);
@@ -1349,8 +1368,8 @@
 		unlock(f);
 	}
 	respond(m, &r);
-	poperror();
 	putfid(f);
+	poperror();
 }
 
 static void
@@ -1457,8 +1476,8 @@
 				qlock(&de->trunclk);
 				de->trunc = 1;
 				qunlock(&de->trunclk);
-				aincl(&de->ref, 1);
-				aincl(&f->mnt->ref, 1);
+				ainc(&de->ref);
+				ainc(&f->mnt->ref);
 				(*ao)->op = AOclear;
 				(*ao)->mnt = f->mnt;
 				(*ao)->qpath = f->qpath;
@@ -1829,7 +1848,7 @@
 	}else{
 		if(*ao == nil)
 			*ao = emalloc(sizeof(Amsg), 1);
-		aincl(&f->mnt->ref, 1);
+		ainc(&f->mnt->ref);
 		(*ao)->op = AOclear;
 		(*ao)->mnt = f->mnt;
 		(*ao)->qpath = f->qpath;
@@ -1922,8 +1941,8 @@
 		qlock(&f->dent->trunclk);
 		f->dent->trunc = 1;
 		qunlock(&f->dent->trunclk);
-		aincl(&f->dent->ref, 1);
-		aincl(&f->mnt->ref, 1);
+		ainc(&f->dent->ref);
+		ainc(&f->mnt->ref);
 		(*ao)->op = AOclear;
 		(*ao)->mnt = f->mnt;
 		(*ao)->qpath = f->qpath;
@@ -2275,7 +2294,7 @@
 	Fid *f;
 	int i;
 
-	if(aincl(&c->ref, -1))
+	if(adec(&c->ref) != 0)
 		return;
 
 	lock(&fs->connlk);
@@ -2297,16 +2316,12 @@
 		lock(&c->fidtablk[i]);
 		for(f = c->fidtab[i]; f != nil; f = f->next){
 			lock(f);
-			if(waserror()){
-				unlock(f);
-				continue;
-			}
 			a = nil;
 			clunkfid(c, f, &a);
 			unlock(f);
+			putfid(f);
 			if(a != nil)
 				chsend(fs->admchan, a);
-			nexterror();
 		}
 		unlock(&c->fidtablk[i]);
 	}
@@ -2414,9 +2429,11 @@
 					rerror(m, Enofid);
 					continue;
 				}
+				lock(f);
 				clunkfid(m->conn, f, &a);
 				/* read only: ignore rclose */
 				f->rclose = nil;
+				unlock(f);
 				free(a);
 				putfid(f);
 			}
--- a/sys/src/cmd/gefs/main.c
+++ b/sys/src/cmd/gefs/main.c
@@ -119,7 +119,7 @@
 {
 	va_list ap;
 
-	aincl(&fs->rdonly, 1);
+	ainc(&fs->rdonly);
 	va_start(ap, fmt);
 	errorv(fmt, ap, 1);
 }
--