static Chan* signopen(Chan *c, int omode) { if(c->qid.type & QTDIR) { if(omode != OREAD) error(Eisdir); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } switch((ulong)c->qid.path){ case Qctl: if(!iseve()) error(Eperm); break; case Qkey: if(omode != OREAD && !iseve()) error(Eperm); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; }
static void srvremove(Chan *c) { Proc *up = externup(); Srv *sp, **l; if(c->qid.type == QTDIR) error(Eperm); qlock(&srvlk); if(waserror()){ qunlock(&srvlk); nexterror(); } l = &srv; for(sp = *l; sp; sp = sp->link) { if(sp->path == c->qid.path) break; l = &sp->link; } if(sp == 0) error(Enonexist); /* * Only eve can remove system services. * No one can remove #s/boot. */ if(strcmp(sp->owner, eve) == 0 && !iseve()) error(Eperm); if(strcmp(sp->name, "boot") == 0) error(Eperm); /* * No removing personal services. */ if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) && !iseve()) error(Eperm); *l = sp->link; qunlock(&srvlk); poperror(); if(sp->chan) cclose(sp->chan); free(sp->owner); free(sp->name); free(sp); }
static void capremove(struct chan *c) { if (iseve() && c->qid.path == Qhash) ncapdir = ARRAY_SIZE(capdir) - 1; else error(EPERM, "Permission denied"); }
static long segmentwstat(Chan *c, uchar *dp, long n) { Globalseg *g; Dir *d; if(c->qid.type == QTDIR) error(Eperm); g = getgseg(c); if(waserror()){ putgseg(g); nexterror(); } if(strcmp(g->uid, up->user)!=0 && !iseve()) error(Eperm); d = smalloc(sizeof(Dir)+n); if(waserror()){ free(d); nexterror(); } n = convM2D(dp, n, &d[0], (char*)&d[1]); if(!emptystr(d->uid) && strcmp(d->uid, g->uid) != 0) kstrdup(&g->uid, d->uid); if(d->mode != ~0UL) g->perm = d->mode & 0777; poperror(); free(d); poperror(); putgseg(g); return n; }
static int cmdwstat(Chan *c, uchar *dp, int n) { Dir *d; Conv *cv; switch(TYPE(c->qid)){ default: error(Eperm); case Qctl: case Qdata: case Qstderr: d = malloc(sizeof(*d)+n); if(d == nil) error(Enomem); if(waserror()){ free(d); nexterror(); } n = convM2D(dp, n, d, (char*)&d[1]); if(n == 0) error(Eshortstat); cv = cmd.conv[CONV(c->qid)]; if(!iseve() && strcmp(up->env->user, cv->owner) != 0) error(Eperm); if(!emptystr(d->uid)) kstrdup(&cv->owner, d->uid); if(d->mode != ~0UL) cv->perm = d->mode & 0777; poperror(); free(d); break; } return n; }
static void capremove(Chan *c) { if(c->qid.path != Qhash || !iseve()) error(Eperm); ncapdir = nelem(capdir)-1; }
static int segmentwstat(Chan *c, uchar *dp, int n) { Globalseg *g; Dir *d; if(c->qid.type == QTDIR) error(Eperm); g = getgseg(c); if(waserror()){ putgseg(g); nexterror(); } if(strcmp(g->uid, up->user) && !iseve()) error(Eperm); d = smalloc(sizeof(Dir)+n); n = convM2D(dp, n, &d[0], (char*)&d[1]); g->perm = d->mode & 0777; putgseg(g); poperror(); free(d); return n; }
static Chan* pmcopen(Chan *c, int omode) { if (!iseve()) error(Eperm); return devopen(c, omode, nil, 0, pmcgen); }
static Chan* fsattach(char *spec) { struct stat st; Chan *c; UnixFd *ufd; int dev; if(!iseve()) error(Eperm); dev = 1; if(spec && spec[0]){ snprint(up->genbuf, sizeof up->genbuf, "no file system #%C%s", FsChar, spec); error(up->genbuf); } if(stat("/", &st) < 0) oserror(); c = devattach(FsChar, 0); ufd = mallocz(sizeof(UnixFd), 1); ufd->path = newpath("/"); ufd->fd = -1; c->aux = ufd; c->dev = dev; c->qid = fsqid(&st); if(Trace) print("fsattach /\n"); return c; }
static int sdwstat(Chan* c, uchar* dp, int n) { Dir *d; SDpart *pp; SDperm *perm; SDunit *unit; SDev *sdev; if(c->qid.type & QTDIR) error(Eperm); sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->ctl); d = nil; if(waserror()){ free(d); qunlock(&unit->ctl); decref(&sdev->r); nexterror(); } switch(TYPE(c->qid)){ default: error(Eperm); case Qctl: perm = &unit->ctlperm; break; case Qraw: perm = &unit->rawperm; break; case Qpart: pp = &unit->part[PART(c->qid)]; if(unit->vers+pp->vers != c->qid.vers) error(Enonexist); perm = &pp->SDperm; break; } if(strcmp(up->env->user, perm->user) && !iseve()) error(Eperm); d = smalloc(sizeof(Dir)+n); n = convM2D(dp, n, &d[0], (char*)&d[1]); if(n == 0) error(Eshortstat); if(!emptystr(d[0].uid)) kstrdup(&perm->user, d[0].uid); if(d[0].mode != ~0UL) perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777); free(d); qunlock(&unit->ctl); decref(&sdev->r); poperror(); return n; }
static int ipwstat(Chan *c, uchar *dp, int n) { Dir d; Conv *cv; Fs *f; Proto *p; f = ipfs[c->dev]; switch(TYPE(c->qid)) { default: error(Eperm); break; case Qctl: case Qdata: break; } n = convM2D(dp, n, &d, nil); if(n > 0){ p = f->p[PROTO(c->qid)]; cv = p->conv[CONV(c->qid)]; if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0) error(Eperm); if(d.uid[0]) kstrdup(&cv->owner, d.uid); cv->perm = d.mode & 0777; } return n; }
static Chan* acpiopen(Chan *c, int omode) { if( !iseve() ) { error( Eperm ); } return devopen( c, omode, acpidir, nelem(acpidir), devgen); }
uintptr sysr1(va_list) { if(!iseve()) error(Eperm); checkpagerefs(); return 0; }
static Chan* dsoopen(Chan *c, int omode) { if(!iseve()) error(Eperm); return devopen(c, omode, dsotab, nfichtab+2, devgen); }
static void capremove(Chan *c) { if(iseve() && c->qid.path == Qhash) ncapdir = nelem(capdir)-1; else error(Eperm); }
static Chan* consopen(Chan *c, int omode) { c->aux = 0; switch((ulong)c->qid.path){ case Qconsctl: if(!iseve()) error(Eperm); qlock(&kbd); kbd.ctl++; qunlock(&kbd); break; case Qkeyboard: if((omode & 3) != OWRITE) { qlock(&kbd); kbd.kbdr++; flushkbdline(kbdq); kbd.raw = 1; qunlock(&kbd); } break; case Qscancode: qlock(&kbd); if(kscanq || !kscanid) { qunlock(&kbd); c->flag &= ~COPEN; if(kscanq) error(Einuse); else error(Ebadarg); } kscanq = qopen(256, 0, nil, nil); qunlock(&kbd); break; case Qkprint: if((omode & 3) != OWRITE) { wlock(&kprintq); if(kprintq.q != nil){ wunlock(&kprintq); error(Einuse); } kprintq.q = qopen(32*1024, Qcoalesce, nil, nil); if(kprintq.q == nil){ wunlock(&kprintq); error(Enomem); } qnoblock(kprintq.q, 1); wunlock(&kprintq); c->iounit = qiomaxatomic; } break; } return devopen(c, omode, consdir, nelem(consdir), devgen); }
/* * set a local address and port from a string of the form * [address!]port[!r] */ char* setladdrport(Conv* c, char* str, int announcing) { char *p; char *rv; ushort lport; uchar addr[IPaddrlen]; /* * ignore restricted part if it exists. it's * meaningless on local ports. */ p = strchr(str, '!'); if(p != nil){ *p++ = 0; if(strcmp(p, "r") == 0) p = nil; } c->lport = 0; if(p == nil){ if(announcing) ipmove(c->laddr, IPnoaddr); else setladdr(c); p = str; } else { if(strcmp(str, "*") == 0) ipmove(c->laddr, IPnoaddr); else { if(parseip(addr, str) == -1) return Ebadip; if(ipforme(c->p->f, addr)) ipmove(c->laddr, addr); else return "not a local IP address"; } } /* one process can get all connections */ if(announcing && strcmp(p, "*") == 0){ if(!iseve()) error(Eperm); return setluniqueport(c, 0); } lport = atoi(p); if(lport <= 0) rv = setlport(c); else rv = setluniqueport(c, lport); return rv; }
long hostdomainwrite(char *a, int n) { char buf[DOMLEN]; if(!iseve()) error(Eperm); if(n >= DOMLEN) error(Ebadarg); memset(buf, 0, DOMLEN); strncpy(buf, a, n); if(buf[0] == 0) error(Ebadarg); memmove(hostdomain, buf, DOMLEN); return n; }
static Chan* kbinopen(Chan *c, int omode) { if(!iseve()) error(Eperm); if(c->qid.path == Qkbd){ lock(&kbinlck); if(kbinbusy){ unlock(&kbinlck); error(Einuse); } kbinbusy++; unlock(&kbinlck); } return devopen(c, omode, kbintab, nelem(kbintab), devgen); }
/* * set a local address and port from a string of the form * [address!]port[!r] */ static void setladdrport(Conv *c, char *str, int announcing) { char *p; int lport; /* * ignore restricted part if it exists. it's * meaningless on local ports. */ p = strchr(str, '!'); if(p != nil){ *p++ = 0; if(strcmp(p, "r") == 0) p = nil; } c->lport = 0; if(p == nil){ if(announcing) ipmove(c->laddr, IPnoaddr); else if(0) setladdr(c); p = str; } else { if(strcmp(str, "*") == 0) ipmove(c->laddr, IPnoaddr); else if(parseip(c->laddr, str) == 0) error("invalid IP address"); } if(announcing && strcmp(p, "*") == 0){ if(!iseve()) error(Eperm); c->lport = 0; setlport(c); return; } lport = portno(p); if(lport <= 0) c->lport = 0; else c->lport = lport; setlport(c); }
static FWImage* readfirmware(void) { uchar dirbuf[sizeof(Dir)+100], *data; char *err; FWImage *fw; int n, r; Chan *c; Dir d; if(!iseve()) error(Eperm); if(!waserror()){ c = namec("/boot/wpi-3945abg", Aopen, OREAD, 0); poperror(); }else c = namec("/lib/firmware/wpi-3945abg", Aopen, OREAD, 0); if(waserror()){ cclose(c); nexterror(); } n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf); if(n <= 0) error("can't stat firmware"); convM2D(dirbuf, n, &d, nil); fw = smalloc(sizeof(*fw) + 16 + d.length); data = (uchar*)(fw+1); if(waserror()){ free(fw); nexterror(); } r = 0; while(r < d.length){ n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r); if(n <= 0) break; r += n; } if((err = crackfw(fw, data, r)) != nil) error(err); poperror(); poperror(); cclose(c); return fw; }
static int32_t srvwstat(Chan *c, uint8_t *dp, int32_t n) { Proc *up = externup(); Dir d; Srv *sp; char *strs; if(c->qid.type & QTDIR) error(Eperm); strs = nil; qlock(&srvlk); if(waserror()){ qunlock(&srvlk); free(strs); nexterror(); } sp = srvlookup(nil, c->qid.path); if(sp == 0) error(Enonexist); if(strcmp(sp->owner, up->user) != 0 && !iseve()) error(Eperm); strs = smalloc(n); n = convM2D(dp, n, &d, strs); if(n == 0) error(Eshortstat); if(d.mode != (uint32_t)~0UL) sp->perm = d.mode & 0777; if(d.uid && *d.uid) kstrdup(&sp->owner, d.uid); if(d.name && *d.name && strcmp(sp->name, d.name) != 0) { if(strchr(d.name, '/') != nil) error(Ebadchar); kstrdup(&sp->name, d.name); } qunlock(&srvlk); free(strs); poperror(); return n; }
/* * called by devcons() for host owner/domain * * writing hostowner also sets user */ long hostownerwrite(char *a, int n) { char buf[128]; if(!iseve()) error(Eperm); if(n <= 0 || n >= sizeof buf) error(Ebadarg); memmove(buf, a, n); buf[n] = 0; renameuser(eve, buf); kstrdup(&eve, buf); kstrdup(&up->user, buf); up->basepri = PriNormal; return n; }
static int eiawstat(Chan *c, uchar *dp, int n) { Dir d; int i; if(!iseve()) error(Eperm); if(c->qid.type & QTDIR) error(Eperm); if(NETTYPE(c->qid.path) == Nstatqid) error(Eperm); n = convM2D(dp, n, &d, nil); i = Nqid*NETID(c->qid.path)+NETTYPE(c->qid.path)-Ndataqid; if(d.mode != ~0UL) eiadir[i+1].perm = d.mode&0666; return n; }
static Chan* capopen(Chan *c, int omode) { if(c->qid.type & QTDIR) { if(omode != OREAD) error(Eisdir); c->mode = omode; c->flag |= COPEN; c->offset = 0; return c; } if(c->qid.path == Qhash && !iseve()) error(Eperm); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; }
static int uartwstat(Chan *c, uchar *dp, int n) { Dir d; Dirtab *dt; if(!iseve()) error(Eperm); if(QTDIR & c->qid.type) error(Eperm); if(NETTYPE(c->qid.path) == Nstatqid) error(Eperm); dt = &uartdir[1 + 3 * NETID(c->qid.path)]; n = convM2D(dp, n, &d, nil); if(n == 0) error(Eshortstat); if(d.mode != ~0UL) dt[0].perm = dt[1].perm = d.mode; return n; }
static int32_t uartwstat(Chan *c, uint8_t *dp, int32_t n) { Dir d; Dirtab *dt; if(!iseve()) error(Eperm); if(QTDIR & c->qid.type) error(Eperm); if(UARTTYPE(c->qid.path) == Qstat) error(Eperm); dt = &uartdir[1 + 3 * UARTID(c->qid.path)]; n = convM2D(dp, n, &d, nil); if(n == 0) error(Eshortstat); if(d.mode != (uint32_t)~0UL) dt[0].perm = dt[1].perm = d.mode; return n; }
static int uartwstat(Chan *c, uchar *dp, int n) { error(Eperm); return 0; #ifdef xxx Dir d; Dirtab *dt; if(!iseve()) error(Eperm); if(c->qid.type & QTDIR) error(Eperm); if(NETTYPE(c->qid.path) == Nstatqid) error(Eperm); dt = &uartdir[3 * NETID(c->qid.path)]; convM2D(dp, &d); d.mode &= 0666; dt[0].perm = dt[1].perm = d.mode; #endif }
static int ipwstat(Chan *c, uchar *dp, int n) { Dir *d; Conv *cv; Proto *p; Fs *f; f = ipfs[c->dev]; switch(TYPE(c->qid)) { default: error(Eperm); break; case Qctl: case Qdata: break; } d = smalloc(sizeof(*d)+n); if(waserror()){ free(d); nexterror(); } n = convM2D(dp, n, d, (char*)&d[1]); if(n == 0) error(Eshortstat); p = f->p[PROTO(c->qid)]; cv = p->conv[CONV(c->qid)]; if(!iseve() && strcmp(up->env->user, cv->owner) != 0) error(Eperm); if(!emptystr(d->uid)) kstrdup(&cv->owner, d->uid); if(d->mode != ~0UL) cv->perm = d->mode & 0777; poperror(); free(d); return n; }
/* * if the stream doesn't exist, create it */ static struct chan *capopen(struct chan *c, int omode) { if (c->qid.type & QTDIR) { if (omode != O_RDONLY) error(EISDIR, "Is a directory"); c->mode = omode; c->flag |= COPEN; c->offset = 0; return c; } switch ((uint32_t)c->qid.path) { case Qhash: if (!iseve()) error(EPERM, "Permission denied: only eve() can open Qhash"); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; }