X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2Flib9p%2Fsrv.c;h=f3039e01231bfe8ddb2ffd6279d398f43dfe0a25;hb=53800208bd762b1ecf14b60585cb906f22db7de8;hp=33791cb18ed101c9b310907527e1459fece75fe1;hpb=9c844d90e117c9cb7b7fc16e4b0741a0df88456c;p=plan9front.git diff --git a/sys/src/lib9p/srv.c b/sys/src/lib9p/srv.c index 33791cb18..f3039e012 100644 --- a/sys/src/lib9p/srv.c +++ b/sys/src/lib9p/srv.c @@ -59,7 +59,8 @@ getreq(Srv *s) Req *r; qlock(&s->rlock); - if((n = read9pmsg(s->infd, s->rbuf, s->msize)) <= 0){ + n = read9pmsg(s->infd, s->rbuf, s->msize); + if(n <= 0){ qunlock(&s->rlock); return nil; } @@ -163,23 +164,35 @@ walkandclone(Req *r, char *(*walk1)(Fid*, char*, void*), char *(*clone)(Fid*, Fi } static void -sversion(Srv*, Req *r) +sversion(Srv *srv, Req *r) { + if(srv->rref.ref != 1){ + respond(r, Ebotch); + return; + } if(strncmp(r->ifcall.version, "9P", 2) != 0){ r->ofcall.version = "unknown"; + r->ofcall.msize = 256; respond(r, nil); return; } - r->ofcall.version = "9P2000"; - r->ofcall.msize = r->ifcall.msize; + if(r->ifcall.msize < 256){ + respond(r, "version: message size too small"); + return; + } + if(r->ifcall.msize < 1024*1024) + r->ofcall.msize = r->ifcall.msize; + else + r->ofcall.msize = 1024*1024; respond(r, nil); } + static void rversion(Req *r, char *error) { - assert(error == nil); - changemsize(r->srv, r->ofcall.msize); + if(error == nil) + changemsize(r->srv, r->ofcall.msize); } static void @@ -201,8 +214,14 @@ sauth(Srv *srv, Req *r) static void rauth(Req *r, char *error) { - if(error && r->afid) + if(r->afid == nil) + return; + if(error){ closefid(removefid(r->srv->fpool, r->afid->fid)); + return; + } + if(r->afid->omode == -1) + r->afid->omode = ORDWR; } static void @@ -352,6 +371,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) { @@ -372,7 +408,8 @@ sopen(Srv *srv, Req *r) r->ofcall.qid = r->fid->qid; switch(r->ifcall.mode&3){ default: - assert(0); + respond(r, Ebotch); + return; case OREAD: p = AREAD; break; @@ -397,9 +434,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; } @@ -415,21 +450,6 @@ sopen(Srv *srv, Req *r) else respond(r, nil); } -static void -ropen(Req *r, char *error) -{ - char errbuf[ERRMAX]; - if(error) - return; - if(chatty9p){ - snprint(errbuf, sizeof errbuf, "fid mode is 0x%ux\n", r->ifcall.mode); - write(2, errbuf, strlen(errbuf)); - } - r->fid->omode = r->ifcall.mode; - r->fid->qid = r->ofcall.qid; - if(r->ofcall.qid.type&QTDIR) - r->fid->diroffset = 0; -} static void screate(Srv *srv, Req *r) @@ -447,13 +467,18 @@ screate(Srv *srv, Req *r) else respond(r, Enocreate); } + static void -rcreate(Req *r, char *error) +ropen(Req *r, char *error) { if(error) return; - r->fid->omode = r->ifcall.mode; + if(chatty9p) + fprint(2, "fid mode is %x\n", (int)r->ifcall.mode); + if(r->ofcall.qid.type&QTDIR) + r->fid->diroffset = 0; r->fid->qid = r->ofcall.qid; + r->fid->omode = r->ifcall.mode; } static void @@ -465,6 +490,20 @@ sread(Srv *srv, Req *r) respond(r, Eunknownfid); return; } + o = r->fid->omode; + if(o == -1){ + respond(r, Ebotch); + return; + } + switch(o & 3){ + default: + respond(r, Ebotch); + return; + case OREAD: + case ORDWR: + case OEXEC: + break; + } if((int)r->ifcall.count < 0){ respond(r, Ebotch); return; @@ -474,18 +513,12 @@ sread(Srv *srv, Req *r) respond(r, Ebadoffset); return; } - if(r->ifcall.count > srv->msize - IOHDRSZ) r->ifcall.count = srv->msize - IOHDRSZ; r->rbuf = emalloc9p(r->ifcall.count); r->ofcall.data = r->rbuf; - o = r->fid->omode & 3; - if(o != OREAD && o != ORDWR && o != OEXEC){ - respond(r, Ebotch); - return; - } if((r->fid->qid.type&QTDIR) && r->fid->file){ - r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count); + r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count, r->ifcall.offset); respond(r, nil); return; } @@ -498,19 +531,35 @@ static void rread(Req *r, char *error) { if(error==nil && (r->fid->qid.type&QTDIR)) - r->fid->diroffset += r->ofcall.count; + r->fid->diroffset = r->ifcall.offset + r->ofcall.count; } static void swrite(Srv *srv, Req *r) { int o; - char e[ERRMAX]; if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){ respond(r, Eunknownfid); return; } + o = r->fid->omode; + if(o == -1){ + respond(r, Ebotch); + return; + } + switch(o & 3){ + default: + respond(r, Ebotch); + return; + case OWRITE: + case ORDWR: + break; + } + if(r->fid->qid.type&QTDIR){ + respond(r, Ebotch); + return; + } if((int)r->ifcall.count < 0){ respond(r, Ebotch); return; @@ -521,16 +570,10 @@ swrite(Srv *srv, Req *r) } if(r->ifcall.count > srv->msize - IOHDRSZ) r->ifcall.count = srv->msize - IOHDRSZ; - o = r->fid->omode & 3; - if(o != OWRITE && o != ORDWR){ - snprint(e, sizeof e, "write on fid with open mode 0x%ux", r->fid->omode); - respond(r, e); - return; - } if(srv->write) srv->write(r); else - respond(r, "no srv->write"); + respond(r, Enowrite); } static void rwrite(Req *r, char *error) @@ -561,8 +604,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; } @@ -655,25 +697,32 @@ swstat(Srv *srv, Req *r) respond(r, Ebaddir); return; } - if((ushort)~r->d.type){ - respond(r, "wstat -- attempt to change type"); - return; - } - if((uint)~r->d.dev){ - respond(r, "wstat -- attempt to change dev"); + if(r->d.qid.path != ~0 && r->d.qid.path != r->fid->qid.path){ + respond(r, "wstat -- attempt to change qid.path"); return; } - if((uchar)~r->d.qid.type || (ulong)~r->d.qid.vers || (uvlong)~r->d.qid.path){ - respond(r, "wstat -- attempt to change qid"); + if(r->d.qid.vers != ~0 && r->d.qid.vers != r->fid->qid.vers){ + respond(r, "wstat -- attempt to change qid.vers"); return; } - if(r->d.muid && r->d.muid[0]){ - respond(r, "wstat -- attempt to change muid"); - return; - } - if((ulong)~r->d.mode && ((r->d.mode&DMDIR)>>24) != (r->fid->qid.type&QTDIR)){ - respond(r, "wstat -- attempt to change DMDIR bit"); - return; + if(r->d.mode != ~0){ + if(r->d.mode & ~(DMDIR|DMAPPEND|DMEXCL|DMTMP|0777)){ + respond(r, "wstat -- unknown bits in mode"); + return; + } + if(r->d.qid.type != (uchar)~0 && r->d.qid.type != ((r->d.mode>>24)&0xFF)){ + respond(r, "wstat -- qid.type/mode mismatch"); + return; + } + if(((r->d.mode>>24) ^ r->fid->qid.type) & ~(QTAPPEND|QTEXCL|QTTMP)){ + respond(r, "wstat -- attempt to change qid.type"); + return; + } + } else { + if(r->d.qid.type != (uchar)~0 && r->d.qid.type != r->fid->qid.type){ + respond(r, "wstat -- attempt to change qid.type"); + return; + } } srv->wstat(r); } @@ -682,14 +731,16 @@ rwstat(Req*, char*) { } +static void srvclose(Srv *); + static void srvwork(void *v) { Srv *srv = v; Req *r; - incref(&srv->sref); while(r = getreq(srv)){ + incref(&srv->rref); if(r->error){ respond(r, r->error); continue; @@ -713,11 +764,29 @@ srvwork(void *v) case Tstat: sstat(srv, r); break; case Twstat: swstat(srv, r); break; } + if(srv->sref.ref > 8 && srv->spid != getpid()){ + decref(&srv->sref); + qunlock(&srv->slock); + return; + } qunlock(&srv->slock); } - if(decref(&srv->sref)) + + if(srv->end && srv->sref.ref == 1) + srv->end(srv); + if(decref(&srv->sref) == 0) + srvclose(srv); +} + +static void +srvclose(Srv *srv) +{ + if(srv->rref.ref || srv->sref.ref) return; + if(chatty9p) + fprint(2, "srvclose\n"); + free(srv->rbuf); srv->rbuf = nil; free(srv->wbuf); @@ -728,8 +797,8 @@ srvwork(void *v) freereqpool(srv->rpool); srv->rpool = nil; - if(srv->end) - srv->end(srv); + if(srv->free) + srv->free(srv); } void @@ -742,8 +811,10 @@ srvacquire(Srv *srv) void srvrelease(Srv *srv) { - if(decref(&srv->sref) == 0) + if(decref(&srv->sref) == 0){ + incref(&srv->sref); _forker(srvwork, srv, 0); + } qunlock(&srv->slock); } @@ -753,6 +824,10 @@ srv(Srv *srv) fmtinstall('D', dirfmt); fmtinstall('F', fcallfmt); + srv->spid = getpid(); + memset(&srv->sref, 0, sizeof(srv->sref)); + memset(&srv->rref, 0, sizeof(srv->rref)); + if(srv->fpool == nil) srv->fpool = allocfidpool(srv->destroyfid); if(srv->rpool == nil) @@ -768,6 +843,7 @@ srv(Srv *srv) if(srv->start) srv->start(srv); + incref(&srv->sref); srvwork(srv); } @@ -799,7 +875,7 @@ respond(Req *r, char *error) case Tattach: rattach(r, error); break; case Twalk: rwalk(r, error); break; case Topen: ropen(r, error); break; - case Tcreate: rcreate(r, error); break; + case Tcreate: ropen(r, error); break; case Tread: rread(r, error); break; case Twrite: rwrite(r, error); break; case Tclunk: rclunk(r, error); break; @@ -819,7 +895,7 @@ if(chatty9p) qlock(&srv->wlock); n = convS2M(&r->ofcall, srv->wbuf, srv->msize); if(n <= 0){ - fprint(2, "n = %d %F\n", n, &r->ofcall); + fprint(2, "msize = %d n = %d %F\n", srv->msize, n, &r->ofcall); abort(); } assert(n > 2); @@ -827,7 +903,7 @@ if(chatty9p) closereq(removereq(r->pool, r->ifcall.tag)); m = write(srv->outfd, srv->wbuf, n); if(m != n) - sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd); + fprint(2, "lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd); qunlock(&srv->wlock); qlock(&r->lk); /* no one will add flushes now */ @@ -844,6 +920,9 @@ if(chatty9p) closereq(r); else free(r); + + if(decref(&srv->rref) == 0) + srvclose(srv); } void @@ -854,59 +933,3 @@ responderror(Req *r) rerrstr(errbuf, sizeof errbuf); respond(r, errbuf); } - -int -postfd(char *name, int pfd) -{ - int fd; - char buf[80]; - - snprint(buf, sizeof buf, "/srv/%s", name); - if(chatty9p) - fprint(2, "postfd %s\n", buf); - fd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600); - if(fd < 0){ - if(chatty9p) - fprint(2, "create fails: %r\n"); - return -1; - } - if(fprint(fd, "%d", pfd) < 0){ - if(chatty9p) - fprint(2, "write fails: %r\n"); - close(fd); - return -1; - } - if(chatty9p) - fprint(2, "postfd successful\n"); - return 0; -} - -int -sharefd(char *name, char *desc, int pfd) -{ - int fd; - char buf[80]; - - snprint(buf, sizeof buf, "#σc/%s", name); - if((fd = create(buf, OREAD, 0700|DMDIR)) >= 0) - close(fd); - snprint(buf, sizeof buf, "#σc/%s/%s", name, desc); - if(chatty9p) - fprint(2, "sharefd %s\n", buf); - fd = create(buf, OWRITE, 0600); - if(fd < 0){ - if(chatty9p) - fprint(2, "create fails: %r\n"); - return -1; - } - if(fprint(fd, "%d\n", pfd) < 0){ - if(chatty9p) - fprint(2, "write fails: %r\n"); - close(fd); - return -1; - } - close(fd); - if(chatty9p) - fprint(2, "sharefd successful\n"); - return 0; -}