diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-09-19 05:22:26 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-09-19 05:22:26 +0200 |
commit | a1b2b9b126e540007ae51e128c457a8fc924b20f (patch) | |
tree | 33dd08662ec14b376f9cf4525c825f240ecf5747 | |
parent | 5d8300d2ebaaba3a648d25015cadd80ddd2d016e (diff) |
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.
-rw-r--r-- | sys/src/lib9p/srv.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/sys/src/lib9p/srv.c b/sys/src/lib9p/srv.c index 4b91b86ce..3f93ed9fb 100644 --- a/sys/src/lib9p/srv.c +++ b/sys/src/lib9p/srv.c @@ -365,6 +365,23 @@ rwalk(Req *r, char *error) } } +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 @@ sopen(Srv *srv, Req *r) 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 @@ sremove(Srv *srv, Req *r) 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; } |