shithub: riscv

Download patch

ref: a1b2b9b126e540007ae51e128c457a8fc924b20f
parent: 5d8300d2ebaaba3a648d25015cadd80ddd2d016e
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Sep 19 01:22:26 EDT 2014

lib9p: fix nil dereference crash in remove for directory permission check

file->parent can be nil when the file has been previously removed.
removefile() deals with this, so skip the permission check in
that case and let removefile() error out.

--- a/sys/src/lib9p/srv.c
+++ b/sys/src/lib9p/srv.c
@@ -365,6 +365,23 @@
 	}
 }
 
+static int
+dirwritable(Fid *fid)
+{
+	File *f;
+
+	f = fid->file;
+	if(f){
+		rlock(f);
+		if(f->parent && !hasperm(f->parent, fid->uid, AWRITE)){
+			runlock(f);
+			return 0;
+		}
+		runlock(f);
+	}
+	return 1;
+}
+
 static void
 sopen(Srv *srv, Req *r)
 {
@@ -410,9 +427,7 @@
 			respond(r, Eperm);
 			return;
 		}
-	/* BUG RACE */
-		if((r->ifcall.mode&ORCLOSE)
-		&& !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
+		if((r->ifcall.mode&ORCLOSE) && !dirwritable(r->fid)){
 			respond(r, Eperm);
 			return;
 		}
@@ -574,8 +589,7 @@
 		respond(r, Eunknownfid);
 		return;
 	}
-	/* BUG RACE */
-	if(r->fid->file && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
+	if(!dirwritable(r->fid)){
 		respond(r, Eperm);
 		return;
 	}