From cac03f355caa29a6bd5cafd7d0d6ca362149cb27 Mon Sep 17 00:00:00 2001 From: Jacob Moody Date: Wed, 29 Jun 2022 17:35:27 +0000 Subject: [PATCH 1/5] kernel: revert /srv/clone --- sys/man/3/srv | 16 +- sys/src/9/port/devsrv.c | 431 ++++++++-------------------------------- 2 files changed, 86 insertions(+), 361 deletions(-) diff --git a/sys/man/3/srv b/sys/man/3/srv index b68f00887..820c849db 100644 --- a/sys/man/3/srv +++ b/sys/man/3/srv @@ -5,8 +5,6 @@ srv \- server registry .nf .B bind #s /srv -.BI #s/ clone -.BI #s/ n .BI #s/ service1 .BI #s/ service2 ... @@ -14,7 +12,7 @@ srv \- server registry .SH DESCRIPTION The .I srv -device provides a tree of directories holding +device provides a one-level directory holding already-open channels to services. In effect, .I srv @@ -42,18 +40,6 @@ releases that reference. .PP It is an error to write more than one number into a server file, or to create a file with a name that is already being used. -.PP -Opening the -.I clone -file allocates a new service directory. Reading -.I clone -returns the id of the new directory. This new service -directory can then be accessed at -.BR /srv/id . -Directories are recursable; each new service directory -contains its own -.I clone -file. .SH EXAMPLE To drop one end of a pipe into .BR /srv , diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c index e1b7856f9..8128569a1 100644 --- a/sys/src/9/port/devsrv.c +++ b/sys/src/9/port/devsrv.c @@ -5,249 +5,80 @@ #include "fns.h" #include "../port/error.h" -#include "netif.h" - -typedef struct Link Link; -struct Link -{ - void *link; - char *name; - ulong path; -}; typedef struct Srv Srv; struct Srv { - Link; - + char *name; char *owner; ulong perm; Chan *chan; + Srv *link; + ulong path; }; -typedef struct Board Board; -struct Board +static QLock srvlk; +static Srv *srv; +static int qidpath; + +static Srv* +srvlookup(char *name, ulong qidpath) { - Link; - RWlock; - Ref; + Srv *sp; - Board *parent; - Board *child; - Srv *srv; - long id; - int qidpath; - int closed; -}; - -struct{ - QLock; - long path; -} boards; - -enum{ - Qroot, - Qclone, - Qlease, - - Qend, -}; - -Board root; - -static char Eexpired[] = "expired lease"; - -static void* -lookup(Link *l, char *name, ulong qidpath) -{ - Link *lp; - - if(qidpath != ~0UL) - qidpath = NETTYPE(qidpath); - for(lp = l; lp != nil; lp = lp->link){ - if(qidpath != ~0UL && lp->path == qidpath) - return lp; - if(name != nil && strcmp(lp->name, name) == 0) - return lp; + for(sp = srv; sp != nil; sp = sp->link) { + if(sp->path == qidpath || (name != nil && strcmp(sp->name, name) == 0)) + return sp; } return nil; } -static void* -remove(Link **l, char *name, ulong qidpath) -{ - Link *lp; - Link **last; - - if(qidpath != ~0UL) - qidpath = NETTYPE(qidpath); - last = l; - for(lp = *l; lp != nil; lp = lp->link){ - if(qidpath != ~0UL && lp->path == qidpath) - break; - if(name != nil && strcmp(lp->name, name) == 0) - break; - last = &lp->link; - } - if(lp == nil) - return nil; - - *last = lp->link; - lp->link = nil; - return lp; -} - -static void -boardclunk(Board *b, int close) -{ - Srv *sp, *prv; - Board *ch; - long ref; - - /* caller holds a wlock */ - if(b == &root){ - wunlock(b); - return; - } - - if(close){ - assert(b->closed == 0); - b->closed++; - for(sp = b->srv; sp != nil; sp = prv){ - prv = sp->link; - free(sp->owner); - free(sp->name); - if(sp->chan != nil) - cclose(sp->chan); - free(sp); - } - b->srv = nil; - } - ref = decref(b); - - /* - * All boards must be walkable from root. So a board - * is allowed to sit at zero references as long as it - * still has active children. For leaf nodes we then - * have to walk up the tree to clear now empty parents. - */ - while(b->closed && b->child == nil && ref == 0){ - //Root should never be closed - assert(b->parent != nil); - wlock(b->parent); - ch = remove((Link**)&b->parent->child, b->name, b->path); - assert(ch == b); - - b = ch->parent; - free(ch->name); - wunlock(ch); - free(ch); - } - wunlock(b); -} - static int srvgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) { Srv *sp; - Board *b, *ch; Qid q; - if(name != nil && strlen(name) >= sizeof(up->genbuf)) - return -1; - - b = c->aux; - ch = nil; - mkqid(&q, ~0L, 0, QTFILE); - rlock(b); - if(waserror()){ - runlock(b); - return -1; - } if(s == DEVDOTDOT){ - ch = b->parent; - if(ch == nil) - ch = &root; - goto Child; - + devdir(c, c->qid, "#s", 0, eve, 0555, dp); + return 1; } - if(name != nil){ - if(strcmp("clone", name) == 0) - goto Clone; - sp = lookup(b->srv, name, ~0UL); - if(sp == nil) - ch = lookup(b->child, name, ~0UL); - } else { - if(s == 0) - goto Clone; - s--; - for(sp = b->srv; sp != nil && s > 0; sp = sp->link) - s--; - for(ch = b->child; ch != nil && s > 0; ch = ch->link) + qlock(&srvlk); + if(name != nil) + sp = srvlookup(name, -1); + else { + for(sp = srv; sp != nil && s > 0; sp = sp->link) s--; } - if(sp != nil){ - kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); - q.vers = NETID(c->qid.path); - q.path = NETQID(q.vers, sp->path); - devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); - } else if(ch != nil){ -Child: - kstrcpy(up->genbuf, ch->name, sizeof up->genbuf); - q.vers = ch->id; - q.path = NETQID(q.vers, ch->path); - q.type = QTDIR; - devdir(c, q, up->genbuf, 0, eve, 0555|DMDIR, dp); - /* dirread's and stats shouldn't alter c->aux */ - if(name != nil) - c->aux = ch; - } else if(0){ -Clone: - q.vers = NETID(c->qid.path); - q.path = NETQID(q.vers, Qclone); - devdir(c, q, "clone", 0, eve, 0444, dp); - } else - error(Enonexist); - - runlock(b); - poperror(); + if(sp == nil || (name != nil && (strlen(sp->name) >= sizeof(up->genbuf)))) { + qunlock(&srvlk); + return -1; + } + mkqid(&q, sp->path, 0, QTFILE); + /* make sure name string continues to exist after we release lock */ + kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); + devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); + qunlock(&srvlk); return 1; } static void srvinit(void) { - root.qidpath = Qend; - root.name = "#s"; + qidpath = 1; } static Chan* srvattach(char *spec) { - Chan *c; - - c = devattach('s', spec); - c->aux = &root; - return c; + return devattach('s', spec); } static Walkqid* srvwalk(Chan *c, Chan *nc, char **name, int nname) { - Board *b; - Walkqid *wq; - - wq = devwalk(c, nc, name, nname, 0, 0, srvgen); - if(wq == nil || wq->clone == nil) - return wq; - - b = wq->clone->aux; - if(b == &root) - return wq; - - incref(b); - return wq; + return devwalk(c, nc, name, nname, 0, 0, srvgen); } static int @@ -259,14 +90,12 @@ srvstat(Chan *c, uchar *db, int n) char* srvname(Chan *c) { - Board *b; Srv *sp; char *s; s = nil; - b = &root; - rlock(b); - for(sp = b->srv; sp != nil; sp = sp->link) { + qlock(&srvlk); + for(sp = srv; sp != nil; sp = sp->link) { if(sp->chan == c){ s = malloc(3+strlen(sp->name)+1); if(s != nil) @@ -274,17 +103,15 @@ srvname(Chan *c) break; } } - runlock(b); + qunlock(&srvlk); return s; } static Chan* srvopen(Chan *c, int omode) { - Board *b, *ch; Srv *sp; Chan *nc; - char buf[64]; if(c->qid.type == QTDIR){ if(omode & ORCLOSE) @@ -296,53 +123,20 @@ srvopen(Chan *c, int omode) c->offset = 0; return c; } + qlock(&srvlk); + if(waserror()){ + qunlock(&srvlk); + nexterror(); + } + + sp = srvlookup(nil, c->qid.path); + if(sp == nil || sp->chan == nil) + error(Eshutdown); + if(omode&OTRUNC) error(Eexist); if(omode&ORCLOSE) error(Eperm); - - b = c->aux; - if(NETTYPE(c->qid.path) == Qclone){; - wlock(b); - if(b->closed){ - wunlock(b); - error(Eexpired); - } - ch = smalloc(sizeof *ch); - ch->qidpath = Qend; - ch->ref = 1; - do { - qlock(&boards); - ch->id = ++boards.path; - qunlock(&boards); - snprint(buf, sizeof buf, "%ld", ch->id); - } while(lookup(b->srv, buf, ~0UL) != nil); - - ch->parent = b; - ch->path = b->qidpath++; - kstrdup(&ch->name, buf); - - ch->link = b->child; - b->child = ch; - c->aux = ch; - c->qid.vers = ch->id; - c->qid.path = NETQID(ch->id, Qlease); - boardclunk(b, 0); //unlock - return c; - } - - rlock(b); - if(waserror()){ - runlock(b); - nexterror(); - } - if(b->closed) - error(Eexpired); - - sp = lookup(b->srv, nil, c->qid.path); - if(sp == nil || sp->chan == nil) - error(Eshutdown); - if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR) error(Eperm); devpermcheck(sp->owner, sp->perm, omode); @@ -350,7 +144,7 @@ srvopen(Chan *c, int omode) nc = sp->chan; incref(nc); - runlock(b); + qunlock(&srvlk); poperror(); cclose(c); @@ -360,7 +154,6 @@ srvopen(Chan *c, int omode) static Chan* srvcreate(Chan *c, char *name, int omode, ulong perm) { - Board *b; Srv *sp; if(openmode(omode) != OWRITE) @@ -373,33 +166,27 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) kstrdup(&sp->name, name); kstrdup(&sp->owner, up->user); - b = c->aux; - wlock(b); + qlock(&srvlk); if(waserror()){ - wunlock(b); + qunlock(&srvlk); free(sp->owner); free(sp->name); free(sp); nexterror(); } - if(b->closed) - error(Eexpired); - if(lookup(b->srv, name, ~0UL) != nil) - error(Eexist); - if(lookup(b->child, name, ~0UL) != nil) + if(srvlookup(name, -1) != nil) error(Eexist); sp->perm = perm&0777; - sp->path = b->qidpath++; + sp->path = qidpath++; - c->qid.path = NETQID(b->id, sp->path); - c->qid.vers = b->id; + c->qid.path = sp->path; c->qid.type = QTFILE; - sp->link = b->srv; - b->srv = sp; + sp->link = srv; + srv = sp; - wunlock(b); + qunlock(&srvlk); poperror(); c->flag |= COPEN; @@ -411,24 +198,22 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) static void srvremove(Chan *c) { - Board *b; - Srv *sp; + Srv *sp, **l; if(c->qid.type == QTDIR) error(Eperm); - switch(NETTYPE(c->qid.path)){ - case Qlease: - case Qclone: - error(Eperm); - } - b = c->aux; - wlock(b); + qlock(&srvlk); if(waserror()){ - wunlock(b); + qunlock(&srvlk); nexterror(); } - sp = lookup(b->srv, nil, c->qid.path); + l = &srv; + for(sp = *l; sp != nil; sp = *l) { + if(sp->path == c->qid.path) + break; + l = &sp->link; + } if(sp == nil) error(Enonexist); @@ -444,9 +229,10 @@ srvremove(Chan *c) if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) && !iseve()) error(Eperm); - remove((Link**)&b->srv, nil, c->qid.path); + *l = sp->link; + sp->link = nil; - boardclunk(b, 0); //unlock + qunlock(&srvlk); poperror(); if(sp->chan != nil) @@ -459,18 +245,12 @@ srvremove(Chan *c) static int srvwstat(Chan *c, uchar *dp, int n) { - Board *b; char *strs; Srv *sp; Dir d; if(c->qid.type & QTDIR) error(Eperm); - switch(NETTYPE(c->qid.path)){ - case Qlease: - case Qclone: - error(Eperm); - } strs = smalloc(n); if(waserror()){ @@ -481,16 +261,13 @@ srvwstat(Chan *c, uchar *dp, int n) if(n == 0) error(Eshortstat); - b = c->aux; - wlock(b); + qlock(&srvlk); if(waserror()){ - wunlock(b); + qunlock(&srvlk); nexterror(); } - if(b->closed) - error(Eexpired); - sp = lookup(b->srv, nil, c->qid.path); + sp = srvlookup(nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -502,10 +279,6 @@ srvwstat(Chan *c, uchar *dp, int n) error(Ebadchar); if(strlen(d.name) >= sizeof(up->genbuf)) error(Etoolong); - if(lookup(b->srv, d.name, ~0UL) != nil) - error(Eexist); - if(lookup(b->child, d.name, ~0UL) != nil) - error(Eexist); kstrdup(&sp->name, d.name); } if(d.uid != nil && *d.uid) @@ -513,7 +286,7 @@ srvwstat(Chan *c, uchar *dp, int n) if(d.mode != ~0UL) sp->perm = d.mode & 0777; - wunlock(b); + qunlock(&srvlk); poperror(); free(strs); @@ -525,47 +298,22 @@ srvwstat(Chan *c, uchar *dp, int n) static void srvclose(Chan *c) { - Board *b; - int expired; - - expired = 0; - if(NETTYPE(c->qid.path) == Qlease) - expired++; - else if(c->flag & CRCLOSE){ - /* - * in theory we need to override any changes in removability - * since open, but since all that's checked is the owner, - * which is immutable, all is well. - */ + /* + * in theory we need to override any changes in removability + * since open, but since all that's checked is the owner, + * which is immutable, all is well. + */ + if(c->flag & CRCLOSE){ if(waserror()) - goto Clunk; + return; srvremove(c); poperror(); - return; } -Clunk: - b = c->aux; - wlock(b); - boardclunk(b, expired); //unlock } static long -srvread(Chan *c, void *va, long n, vlong off) +srvread(Chan *c, void *va, long n, vlong) { - Board *b; - - if(NETTYPE(c->qid.path) == Qlease){ - b = c->aux; - rlock(b); - if(waserror()){ - runlock(b); - nexterror(); - } - n = readstr((ulong)off, va, n, b->name); - runlock(b); - poperror(); - return n; - } isdir(c); return devdirread(c, va, n, 0, 0, srvgen); } @@ -573,15 +321,11 @@ srvread(Chan *c, void *va, long n, vlong off) static long srvwrite(Chan *c, void *va, long n, vlong) { - Board *b; Srv *sp; Chan *c1; int fd; char buf[32]; - if(NETTYPE(c->qid.path) == Qlease) - error(Eperm); - if(n >= sizeof buf) error(Etoobig); memmove(buf, va, n); /* so we can NUL-terminate */ @@ -590,18 +334,15 @@ srvwrite(Chan *c, void *va, long n, vlong) c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ - b = c->aux; - wlock(b); + qlock(&srvlk); if(waserror()) { - wunlock(b); + qunlock(&srvlk); cclose(c1); nexterror(); } - if(b->closed) - error(Eexpired); if(c1->qid.type & QTAUTH) error("cannot post auth file in srv"); - sp = lookup(b->srv, nil, c->qid.path); + sp = srvlookup(nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -610,7 +351,7 @@ srvwrite(Chan *c, void *va, long n, vlong) sp->chan = c1; - wunlock(b); + qunlock(&srvlk); poperror(); return n; } @@ -639,14 +380,12 @@ Dev srvdevtab = { void srvrenameuser(char *old, char *new) { - Board *b; Srv *sp; - b = &root; - wlock(b); - for(sp = b->srv; sp != nil; sp = sp->link) { + qlock(&srvlk); + for(sp = srv; sp != nil; sp = sp->link) { if(sp->owner != nil && strcmp(old, sp->owner) == 0) kstrdup(&sp->owner, new); } - wunlock(b); + qunlock(&srvlk); } From a13aa17e4a6ca065180085da1630b7dddfcc324c Mon Sep 17 00:00:00 2001 From: Jacob Moody Date: Thu, 30 Jun 2022 00:51:59 +0000 Subject: [PATCH 2/5] aux/9pcon: add assert flag --- sys/src/cmd/aux/9pcon.c | 424 ++++++++++++++++++++++++++++++++++------ 1 file changed, 359 insertions(+), 65 deletions(-) diff --git a/sys/src/cmd/aux/9pcon.c b/sys/src/cmd/aux/9pcon.c index 3c4b92ebe..b51a8ddac 100644 --- a/sys/src/cmd/aux/9pcon.c +++ b/sys/src/cmd/aux/9pcon.c @@ -5,6 +5,8 @@ #include uint messagesize = 65536; /* just a buffer size */ +int aflag; +int srvfd; void usage(void) @@ -37,22 +39,32 @@ connectcmd(char *cmd) } } +static int rendez; + void watch(int fd) { int n; uchar *buf; - Fcall f; + Fcall f, *p; buf = malloc(messagesize); if(buf == nil) sysfatal("out of memory"); while((n = read9pmsg(fd, buf, messagesize)) > 0){ + memset(&f, 0, sizeof f); if(convM2S(buf, n, &f) != n){ print("convM2S: %r\n"); continue; } + if(aflag){ + p = malloc(sizeof *p); + if(p == nil) + sysfatal("out of memory"); + memmove(p, &f, sizeof f); + rendezvous(&rendez, p); + } print("\t<- %F\n", &f); } if(n == 0) @@ -62,7 +74,7 @@ watch(int fd) } char* -tversion(Fcall *f, int, char **argv) +version(Fcall *f, int, char **argv) { f->msize = strtol(argv[0], 0, 0); if(f->msize > messagesize) @@ -80,6 +92,58 @@ tauth(Fcall *f, int, char **argv) return nil; } +char* +strtoqid(char *s, Qid *q) +{ + char *dot; + int state; + char buf[1024]; + char *p; + + state = 0; + p = buf; + for(dot = s; *dot; dot++){ + assert(p - buf < sizeof buf); + switch(*dot){ + case '{': + continue; + default: + *p++ = *dot; + break; + case '}': + case ',': + *p = '\0'; + switch(state){ + case 0: + q->path = strtoull(buf, 0, 0); + break; + case 1: + q->vers = strtoul(buf, 0, 0); + break; + case 2: + if(buf[0] == 'f' || strcmp("QTFILE", buf) == 0) + q->type = QTFILE; + else if(buf[0] == 'd' || strcmp("QTDIR", buf) == 0) + q->type = QTDIR; + else + q->type = (uchar)strtol(buf, 0, 0); + break; + } + p = buf; + state++; + } + } + if(state != 3) + return "malformed qid"; + return nil; +} + +char* +rauth(Fcall *f, int, char **argv) +{ + return strtoqid(argv[0], &f->aqid); +} + char* tflush(Fcall *f, int, char **argv) { @@ -97,6 +161,12 @@ tattach(Fcall *f, int, char **argv) return nil; } +char* +rattach(Fcall *f, int, char **argv) +{ + return strtoqid(argv[0], &f->qid); +} + char* twalk(Fcall *f, int argc, char **argv) { @@ -114,6 +184,24 @@ twalk(Fcall *f, int argc, char **argv) return nil; } +char* +rwalk(Fcall *f, int argc, char **argv) +{ + int i; + char *e; + + if(argc >= MAXWELEM) + return "too many names"; + + f->nwqid = argc; + for(i = 0; i < argc; i++){ + e = strtoqid(argv[i], &f->wqid[i]); + if(e != nil) + return e; + } + return nil; +} + char* topen(Fcall *f, int, char **argv) { @@ -122,6 +210,13 @@ topen(Fcall *f, int, char **argv) return nil; } +char* +ropen(Fcall *f, int, char **argv) +{ + f->iounit = strtol(argv[1], 0, 0); + return strtoqid(argv[0], &f->qid); +} + char* tcreate(Fcall *f, int, char **argv) { @@ -141,6 +236,14 @@ tread(Fcall *f, int, char **argv) return nil; } +char* +rread(Fcall *f, int, char **argv) +{ + f->data = argv[0]; + f->count = strlen(argv[0]); + return nil; +} + char* twrite(Fcall *f, int, char **argv) { @@ -151,6 +254,13 @@ twrite(Fcall *f, int, char **argv) return nil; } +char* +rwrite(Fcall *f, int, char **argv) +{ + f->count = strtol(argv[0], 0, 0); + return nil; +} + char* tclunk(Fcall *f, int, char **argv) { @@ -194,16 +304,21 @@ twstat(Fcall *f, int, char **argv) static uchar buf[DIRMAX]; Dir d; + //We function as Rstat as well + if(f->type == Twstat){ + f->fid = strtol(argv[0], 0, 0); + argv++; + } + memset(&d, 0, sizeof d); nulldir(&d); - d.name = argv[1]; - d.uid = argv[2]; - d.gid = argv[3]; - d.mode = xstrtoul(argv[4]); - d.mtime = xstrtoul(argv[5]); - d.length = xstrtoull(argv[6]); + d.name = argv[0]; + d.uid = argv[1]; + d.gid = argv[2]; + d.mode = xstrtoul(argv[3]); + d.mtime = xstrtoul(argv[4]); + d.length = xstrtoull(argv[5]); - f->fid = strtol(argv[0], 0, 0); f->stat = buf; f->nstat = convD2M(&d, buf, sizeof buf); if(f->nstat < BIT16SZ) @@ -212,6 +327,21 @@ twstat(Fcall *f, int, char **argv) return nil; } +char* +nop(Fcall*, int, char**) +{ + /* Rwstat,Rremove,Rclunk,Rflush */ + return nil; +} + +enum{ + Xsource = Tmax+1, + Xdef, + Xend, + + Xnexttag, +}; + int taggen; char* @@ -224,6 +354,72 @@ settag(Fcall*, int, char **argv) return buf; } +char* shell9p(int); + +char* +source(Fcall*, int, char **argv) +{ + int fd; + char *e; + + fd = open(argv[0], OREAD); + if(fd < 0) + return smprint("^could not open %s: %r", argv[0]); + e = shell9p(fd); + close(fd); + return e; +} + +typedef struct Func Func; +struct Func { + Func *link; + char *name; + char *lines[128]; + int n; +}; + +Func *globals; +Func *local; + +char* +funcdef(Fcall*, int, char **argv) +{ + if(local != nil) + return smprint("^can not define func %s; %s not terminated", argv[0], local->name); + local = mallocz(sizeof *local, 1); + if(local == nil) + return "!out of memory"; + local->name = strdup(argv[0]); + return nil; +} + +char* +funcend(Fcall*, int, char**) +{ + Func **l; + Func *p; + int i; + + if(local == nil) + return "?no function defined"; + l = &globals; + for(p = globals; p != nil; p = p->link){ + if(strcmp(local->name, p->name) == 0) + break; + l = &p->link; + } + if(p != nil){ + for(i=0; in; i++) + free(p->lines[i]); + free(p->name); + free(p); + } + *l = local; + local = nil; + + return nil; +} + typedef struct Cmd Cmd; struct Cmd { char *name; @@ -234,87 +430,184 @@ struct Cmd { }; Cmd msg9p[] = { - "Tversion", Tversion, 2, "messagesize version", tversion, + "Tversion", Tversion, 2, "messagesize version", version, + "Rversion", Rversion, 2, "messagesize version", version, + "Tauth", Tauth, 3, "afid uname aname", tauth, + "Rauth", Rauth, 1, "aqid", rauth, + "Tflush", Tflush, 1, "oldtag", tflush, + "Rflush", Rflush, 0, "", nop, + "Tattach", Tattach, 4, "fid afid uname aname", tattach, + "Rattach", Rattach, 1, "qid", rattach, + "Twalk", Twalk, 0, "fid newfid [name...]", twalk, + "Rwalk", Rwalk, 0, "name...", rwalk, + "Topen", Topen, 2, "fid mode", topen, + "Ropen", Ropen, 2, "qid iounit", ropen, + "Tcreate", Tcreate, 4, "fid name perm mode", tcreate, + "Rcreate", Rcreate, 2, "qid iounit", ropen, + "Tread", Tread, 3, "fid offset count", tread, + "Rread", Rread, 1, "data", rread, + "Twrite", Twrite, 3, "fid offset data", twrite, + "Rwrite", Rwrite, 1, "count", rwrite, + "Tclunk", Tclunk, 1, "fid", tclunk, + "Rclunk", Rclunk, 0, "", nop, + "Tremove", Tremove, 1, "fid", tremove, + "Rremove", Rremove, 0, "", nop, + "Tstat", Tstat, 1, "fid", tstat, + "Rstat", Rstat, 6, "name uid gid mode mtime length", twstat, + "Twstat", Twstat, 7, "fid name uid gid mode mtime length", twstat, - "nexttag", 0, 0, "", settag, + "Rwstat", Rwstat, 0, "", nop, + + ".", Xsource, 1, "file", source, + "def", Xdef, 1, "name", funcdef, + "end", Xend, 0, "", funcend, + + "nexttag", Xnexttag, 0, "", settag, }; -void +char* +run(char *p) +{ + char *e, *f[10]; + int i, n, nf, n2; + Fcall t, *r; + Func *func; + char *cp; + static uchar *buf = nil; + static uchar *buf2 = nil; + + if(buf == nil) + buf = malloc(messagesize); + if(buf2 == nil) + buf2 = malloc(messagesize); + if(buf == nil || buf2 == nil) + return "!out of memory"; + + if(p[0] == '#') + return nil; + if(local != nil && strstr(p, "end") == nil){ + local->lines[local->n++] = strdup(p); + return nil; + } + if((nf = tokenize(p, f, nelem(f))) == 0) + return nil; + for(i=0; ilink){ + if(strcmp(func->name, f[0]) != 0) + continue; + for(i = 0; i < func->n; i++){ + cp = strdup(func->lines[i]); + if(e = run(cp)){ + free(cp); + return e; + } + free(cp); + } + return nil; + } + return "?unknown message"; + } + + memset(&t, 0, sizeof t); + t.type = msg9p[i].type; + if(t.type == Tversion) + t.tag = NOTAG; + else + t.tag = ++taggen; + if(nf < 1 || (msg9p[i].argc && nf != 1+msg9p[i].argc)) + return smprint("^usage: %s %s", msg9p[i].name, msg9p[i].usage); + + if((e = msg9p[i].fn(&t, nf-1, f+1)) || t.type > Tmax) + return e; + + n = convS2M(&t, buf, messagesize); + if(n <= BIT16SZ) + return "?message too large for buffer"; + + switch(msg9p[i].name[0]){ + case 'R': + if(!aflag) + break; + r = rendezvous(&rendez, nil); + r->tag = t.tag; + n2 = convS2M(r, buf2, messagesize); + if(n != n2 || memcmp(buf, buf2, n) != 0){ + fprint(2, "?mismatch %F != %F\n", r, &t); + return "!assert fail"; + } + free(r); + break; + case 'T': + if(write(srvfd, buf, n) != n) + return "!write fails"; + print("\t-> %F\n", &t); + } + return nil; +} + +char* shell9p(int fd) { - char *e, *f[10], *p; - uchar *buf; - int i, n, nf; + char *e, *p; Biobuf b; - Fcall t; - buf = malloc(messagesize); - if(buf == nil){ - fprint(2, "out of memory\n"); - return; - } - - taggen = 0; - Binit(&b, 0, OREAD); + Binit(&b, fd, OREAD); while(p = Brdline(&b, '\n')){ p[Blinelen(&b)-1] = '\0'; - if(p[0] == '#') + e = run(p); + if(e == nil) continue; - if((nf = tokenize(p, f, nelem(f))) == 0) - continue; - for(i=0; i %F\n", &t); } + Bterm(&b); + return nil; } void main(int argc, char **argv) { - int fd, pid, cmd, net; + int pid, cmd, net; + char *status; cmd = 0; net = 0; + aflag = 0; + taggen = 0; ARGBEGIN{ + case 'a': + aflag = 1; + break; case 'c': cmd = 1; break; @@ -339,29 +632,30 @@ main(int argc, char **argv) usage(); if(cmd) - fd = connectcmd(argv[0]); + srvfd = connectcmd(argv[0]); else if(net){ - fd = dial(netmkaddr(argv[0], "net", "9fs"), 0, 0, 0); - if(fd < 0) + srvfd = dial(netmkaddr(argv[0], "net", "9fs"), 0, 0, 0); + if(srvfd < 0) sysfatal("dial: %r"); }else{ - fd = open(argv[0], ORDWR); - if(fd < 0) + srvfd = open(argv[0], ORDWR); + if(srvfd < 0) sysfatal("open: %r"); } + status = nil; switch(pid = rfork(RFPROC|RFMEM)){ case -1: sysfatal("rfork: %r"); break; case 0: - watch(fd); + watch(srvfd); postnote(PNPROC, getppid(), "kill"); break; default: - shell9p(fd); + status = shell9p(0); postnote(PNPROC, pid, "kill"); break; } - exits(nil); + exits(status); } From 1f95e98dddc420321a8942d9f3195d966c7cc6c0 Mon Sep 17 00:00:00 2001 From: Jacob Moody Date: Thu, 30 Jun 2022 00:56:10 +0000 Subject: [PATCH 3/5] skelfs: dont mount if not asked to --- sys/src/cmd/skelfs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/skelfs.c b/sys/src/cmd/skelfs.c index 137e19397..f2a9e5396 100644 --- a/sys/src/cmd/skelfs.c +++ b/sys/src/cmd/skelfs.c @@ -214,6 +214,7 @@ void main(int argc, char **argv) { char *s, *mode; + char *mtpt; int stdio; s = nil; @@ -241,7 +242,13 @@ main(int argc, char **argv) usage(); if(stdio == 0){ - postmountsrv(&fs, s, argc ? argv[0] : "/mnt/skel", MREPL); + if(s != nil && argc == 0) + mtpt = nil; + else if(argc) + mtpt = argv[0]; + else + mtpt = "/mnt/skel"; + postmountsrv(&fs, s, mtpt, MREPL); exits(nil); } fs.infd = 0; From e6d31c1715cc50bd3d9a0301a41647295f739071 Mon Sep 17 00:00:00 2001 From: Ori Bernstein Date: Thu, 30 Jun 2022 01:24:27 +0000 Subject: [PATCH 4/5] spf: limit recursion depth to prevent ddos (thanks tijay, iashiq5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An attacker may use an infinite number of SPF referrals in his/her SPF setting and can send an email to your mail server which would make your SMTP server make a lot of DNS queries. By exploiting this vulnerability, an attacker can block your SMTP queue, flood the associated recursive resolver, or any DNS authoritative server. According to RFC recommendations (https://datatracker.ietf.org/doc/html/rfc7208#section-4.6), a few DNS lookup limits exist that an SMTP server needs to maintain while resolving an SPF record. That is, SPF implementations MUST limit the total number of query-causing terms to 10 and the number of void lookups to 2 to avoid unreasonable load on the DNS. from: Taejoong “Tijay” Chung (tijay@vt.edu) Ishtiaq Ashiq (iashiq5@vt.edu) --- sys/src/cmd/upas/spf/spf.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sys/src/cmd/upas/spf/spf.c b/sys/src/cmd/upas/spf/spf.c index 09d9c7bdc..6b83ef102 100644 --- a/sys/src/cmd/upas/spf/spf.c +++ b/sys/src/cmd/upas/spf/spf.c @@ -387,7 +387,7 @@ lower(char *s) } int -spfquery(Squery *x, char *d, int include) +spfquery(Squery *x, char *d, int include, int depth) { char *s, **t, *r, *p, *q, buf[10]; int i, n, c; @@ -398,6 +398,10 @@ spfquery(Squery *x, char *d, int include) fprint(2, "spf: include loop: %s (%s)\n", d, inc->s); return -1; } + if(depth >= 10){ + fprint(2, "spf: too much recursion %s\n", d); + return -1; + } s = spffetch(x, d); if(!s) return -1; @@ -457,7 +461,7 @@ spfquery(Squery *x, char *d, int include) if(rflag) fprint(2, "I> %s\n", q); addbegin(mod, r, q); - if(spfquery(x, q, 1) == -1){ + if(spfquery(x, q, 1, depth+1) == -1){ ditch(); addfail(); }else @@ -704,7 +708,7 @@ main(int argc, char **argv) goto loop; spfinit(&q, d, argc, argv); /* or s? */ addbegin('+', ".", s); - if(spfquery(&q, s, 0) != -1) + if(spfquery(&q, s, 0, 0) != -1) break; } if(eflag && nspf) From 6dbfe8c3562b8ccf630ed0e3099b47c8d2730d14 Mon Sep 17 00:00:00 2001 From: "akw@oneirism.org" Date: Thu, 30 Jun 2022 01:58:01 +0000 Subject: [PATCH 5/5] nusb/ptp: increase payload A silly little patch, but some ptp devices (like the camera I own) use USB3 endpoints and subsequently require the data size of the payload to be 1024(-12 for metadata). This is reflected in libgphoto2's current ptp driver. --- sys/src/cmd/nusb/ptp/ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/nusb/ptp/ptp.c b/sys/src/cmd/nusb/ptp/ptp.c index 2b9ef459f..6581b28cc 100644 --- a/sys/src/cmd/nusb/ptp/ptp.c +++ b/sys/src/cmd/nusb/ptp/ptp.c @@ -45,7 +45,7 @@ struct Ptprpc uchar type[2]; uchar code[2]; uchar transid[4]; - uchar d[500]; + uchar d[1012]; }; struct Node