/n/sources/plan9/sys/src/9/port/./sysproc.c:92,98 - ./sysproc.c:92,97 p->dot = up->dot; incref(p->dot); - memmove(p->note, up->note, sizeof(p->note)); p->privatemem = up->privatemem; p->noswap = up->noswap; p->nnote = up->nnote; /n/sources/plan9/sys/src/9/port/./segment.c:465,470 - ./segment.c:465,479 newtop = PGROUND(addr); newsize = (newtop-s->base)/BY2PG; if(newtop < s->top) { + /* + * do not shrink when shared with other procs, as the freed + * address space may have been passed to the kernel already + * by another proc and is past the validaddr stage. + */ + if(s->ref > 1){ + qunlock(&s->lk); + error(Einuse); + } mfreeseg(s, newtop, (s->top-newtop)/BY2PG); s->top = newtop; s->size = newsize; /n/sources/plan9/sys/src/9/port/./segment.c:642,653 - ./segment.c:651,662 Segment *s, *os; Physseg *ps; - if(va != 0 && va >= USTKTOP) - error(Ebadarg); + name = validnamedup(name, 1); + if(waserror()){ + free(name); + nexterror(); + } - validaddr((ulong)name, 1, 0); - vmemchr(name, 0, ~0); - for(sno = 0; sno < NSEG; sno++) if(p->seg[sno] == nil && sno != ESEG) break; /n/sources/plan9/sys/src/9/port/./segment.c:662,709 - ./segment.c:671,727 if(_globalsegattach != nil){ s = (*_globalsegattach)(p, name); if(s != nil){ + poperror(); + free(name); + p->seg[sno] = s; return s->base; } } + for(ps = physseg; ps->name; ps++) + if(strcmp(name, ps->name) == 0){ + poperror(); + free(name); + + goto found; + } + + error(Ebadarg); + + found: len = PGROUND(len); if(len == 0) error(Ebadarg); + if(len > ps->size) + error(Enovmem); + /* * Find a hole in the address space. * Starting at the lowest possible stack address - len, * check for an overlapping segment, and repeat at the * base of that segment - len until either a hole is found - * or the address space is exhausted. + * or the address space is exhausted. make sure we dont + * map the zero page. */ if(va == 0) { - va = p->seg[SSEG]->base - len; - for(;;) { - os = isoverlap(p, va, len); - if(os == nil) - break; + os = p->seg[SSEG]; + do { va = os->base; - if(len > va) + if(len >= va) error(Enovmem); va -= len; - } + os = isoverlap(p, va, len); + } while(os != nil); + } else { + va = va&~(BY2PG-1); + if(va == 0 || va >= USTKTOP) + error(Ebadarg); + if(isoverlap(p, va, len) != nil) + error(Esoverlap); } - va = va&~(BY2PG-1); - if(isoverlap(p, va, len) != nil) - error(Esoverlap); - - for(ps = physseg; ps->name; ps++) - if(strcmp(name, ps->name) == 0) - goto found; - - error(Ebadarg); - found: - if(len > ps->size) - error(Enovmem); - attr &= ~SG_TYPE; /* Turn off what is not allowed */ attr |= ps->attr; /* Copy in defaults */ /n/sources/plan9/sys/src/9/port/./segment.c:710,716 - ./segment.c:728,733 s = newseg(attr, va, len/BY2PG); s->pseg = ps; p->seg[sno] = s; - return va; } /n/sources/plan9/sys/src/9/port/./chan.c:1281,1288 - ./chan.c:1281,1289 /* * Turn a name into a channel. - * &name[0] is known to be a valid address. It may be a kernel address. * + * aname is validated and can be from user or kernel memory. + * * Opening with amode Aopen, Acreate, Aremove, or Aaccess guarantees * that the result will be the only reference to that particular fid. * This is necessary since we might pass the result to /n/sources/plan9/sys/src/9/port/./chan.c:1307,1319 - ./chan.c:1308,1320 char *createerr, tmperrbuf[ERRMAX]; char *name; - if(aname[0] == '\0') - error("empty file name"); aname = validnamedup(aname, 1); if(waserror()){ free(aname); nexterror(); } + if(aname[0] == '\0') + error("empty file name"); DBG("namec %s %d %d\n", aname, amode, omode); name = aname; /n/sources/plan9/sys/src/9/port/./chan.c:1667,1674 - ./chan.c:1668,1673 * a) is in valid memory. * b) is shorter than 2^16 bytes, so it can fit in a 9P string field. * c) contains no frogs. - * The first byte is known to be addressible by the requester, so the - * routine works for kernel and user memory both. * The parameter slashok flags whether a slash character is an error * or a valid character. * /n/sources/plan9/sys/src/9/port/./chan.c:1690,1696 - ./chan.c:1689,1695 if(!dup) print("warning: validname called from %lux with user pointer", pc); ename = vmemchr(name, 0, (1<<16)); - }else + } else ename = memchr(name, 0, (1<<16)); if(ename==nil || ename-name>=(1<<16)) /n/sources/plan9/sys/src/9/port/./chan.c:1713,1723 - ./chan.c:1712,1721 if(c >= Runeself) name += chartorune(&r, name); else{ - if(isfrog[c]) - if(!slashok || c!='/'){ - snprint(up->genbuf, sizeof(up->genbuf), "%s: %q", Ebadchar, aname); - free(s); - error(up->genbuf); + if(isfrog[c] && (!slashok || c!='/')) { + snprint(up->genbuf, sizeof(up->genbuf), "%s: %q", Ebadchar, aname); + free(s); + error(up->genbuf); } name++; } /n/sources/plan9/sys/src/9/port/./fault.c:330,336 - ./fault.c:330,335 return 1; } } - pprint("suicide: invalid address %#lux/%lud in sys call pc=%#lux\n", addr, len, userpc()); return 0; } /n/sources/plan9/sys/src/9/port/./fault.c:337,344 - ./fault.c:336,345 void validaddr(ulong addr, ulong len, int write) { - if(!okaddr(addr, len, write)) - pexit("Suicide", 0); + if(!okaddr(addr, len, write)){ + postnote(up, 1, "sys: bad address in syscall", NDebug); + error(Ebadarg); + } } /* /n/sources/plan9/sys/src/9/port/./sysfile.c:266,281 - ./sysfile.c:266,279 sysopen(ulong *arg) { int fd; - Chan *c = 0; + Chan *c; openmode(arg[1]); /* error check only */ + c = namec((char*)arg[0], Aopen, arg[1], 0); if(waserror()){ - if(c) - cclose(c); + cclose(c); nexterror(); } - validaddr(arg[0], 1, 0); - c = namec((char*)arg[0], Aopen, arg[1], 0); fd = newfd(c); if(fd < 0) error(Enofd); /n/sources/plan9/sys/src/9/port/./sysfile.c:956,962 - ./sysfile.c:954,959 l = arg[2]; validaddr(arg[1], l, 1); - validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Aaccess, 0, 0); if(waserror()){ cclose(c); /n/sources/plan9/sys/src/9/port/./sysfile.c:977,984 - ./sysfile.c:974,979 { Chan *c; - validaddr(arg[0], 1, 0); - c = namec((char*)arg[0], Atodir, 0, 0); cclose(up->dot); up->dot = c; /n/sources/plan9/sys/src/9/port/./sysfile.c:1000,1008 - ./sysfile.c:995,1007 if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER)) error(Ebadarg); - bogus.flags = flag & MCACHE; - if(ismount){ + spec = validnamedup(spec, 1); + if(waserror()){ + free(spec); + nexterror(); + } + if(up->pgrp->noattach) error(Enoattach); /n/sources/plan9/sys/src/9/port/./sysfile.c:1014,1074 - ./sysfile.c:1013,1058 cclose(bc); nexterror(); } - if(afd >= 0) ac = fdtochan(afd, ORDWR, 0, 1); - + bogus.flags = flag & MCACHE; bogus.chan = bc; bogus.authchan = ac; - - validaddr((ulong)spec, 1, 0); bogus.spec = spec; - if(waserror()) - error(Ebadspec); - spec = validnamedup(spec, 1); - poperror(); - - if(waserror()){ - free(spec); - nexterror(); - } - ret = devno('M', 0); c0 = devtab[ret]->attach((char*)&bogus); - - poperror(); /* spec */ - free(spec); poperror(); /* ac bc */ if(ac) cclose(ac); cclose(bc); }else{ - bogus.spec = 0; - validaddr((ulong)arg0, 1, 0); + spec = 0; c0 = namec(arg0, Abind, 0, 0); } - if(waserror()){ cclose(c0); nexterror(); } - validaddr((ulong)arg1, 1, 0); c1 = namec(arg1, Amount, 0, 0); if(waserror()){ cclose(c1); nexterror(); } - - ret = cmount(&c0, c1, flag, bogus.spec); - + ret = cmount(&c0, c1, flag, spec); poperror(); cclose(c1); + poperror(); cclose(c0); - if(ismount) + + if(ismount){ fdclose(fd, 0); + poperror(); + free(spec); + } + return ret; } /n/sources/plan9/sys/src/9/port/./sysfile.c:1097,1111 - ./sysfile.c:1081,1094 cmounted = 0; - validaddr(arg[1], 1, 0); cmount = namec((char *)arg[1], Amount, 0, 0); - + if(waserror()) { + cclose(cmount); + if(cmounted) + cclose(cmounted); + nexterror(); + } if(arg[0]) { - if(waserror()) { - cclose(cmount); - nexterror(); - } - validaddr(arg[0], 1, 0); /* * This has to be namec(..., Aopen, ...) because * if arg[0] is something like /srv/cs or /fd/0, /n/sources/plan9/sys/src/9/port/./sysfile.c:1113,1133 - ./sysfile.c:1096,1107 * Chan underneath. */ cmounted = namec((char*)arg[0], Aopen, OREAD, 0); - poperror(); } - - if(waserror()) { - cclose(cmount); - if(cmounted) - cclose(cmounted); - nexterror(); - } - cunmount(cmount, cmounted); + poperror(); cclose(cmount); if(cmounted) cclose(cmounted); - poperror(); return 0; } /n/sources/plan9/sys/src/9/port/./sysfile.c:1135,1150 - ./sysfile.c:1109,1122 syscreate(ulong *arg) { int fd; - Chan *c = 0; + Chan *c; openmode(arg[1]&~OEXCL); /* error check only; OEXCL okay here */ + c = namec((char*)arg[0], Acreate, arg[1], arg[2]); if(waserror()) { - if(c) - cclose(c); + cclose(c); nexterror(); } - validaddr(arg[0], 1, 0); - c = namec((char*)arg[0], Acreate, arg[1], arg[2]); fd = newfd(c); if(fd < 0) error(Enofd); /n/sources/plan9/sys/src/9/port/./sysfile.c:1157,1164 - ./sysfile.c:1129,1136 { Chan *c; - validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Aremove, 0, 0); + /* * Removing mount points is disallowed to avoid surprises * (which should be removed: the mount point or the mounted Chan?). /n/sources/plan9/sys/src/9/port/./sysfile.c:1167,1172 - ./sysfile.c:1139,1145 cclose(c); error(Eismtpt); } + if(waserror()){ c->type = 0; /* see below */ cclose(c); /n/sources/plan9/sys/src/9/port/./sysfile.c:1217,1223 - ./sysfile.c:1190,1195 l = arg[2]; validaddr(arg[1], l, 0); validstat((uchar*)arg[1], l); - validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Aaccess, 0, 0); return wstat(c, (uchar*)arg[1], l); } /n/sources/plan9/sys/src/9/port/./sysfile.c:1280,1286 - ./sysfile.c:1252,1257 char old[] = "old stat system call - recompile"; validaddr(arg[1], 116, 1); - validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Aaccess, 0, 0); if(waserror()){ cclose(c); /n/sources/plan9/sys/src/9/port/./sysfile.c:1297,1303 - ./sysfile.c:1268,1273 if(l == 0) error(old); packoldstat((uchar*)arg[1], &d); - poperror(); cclose(c); return 0; /n/sources/plan9/sys/src/9/port/./auth.c:65,71 - ./auth.c:65,70 char *aname; int fd; - validaddr(arg[1], 1, 0); aname = validnamedup((char*)arg[1], 1); if(waserror()){ free(aname); /n/sources/plan9/sys/src/9/port/./auth.c:79,94 - ./auth.c:78,92 ac = mntauth(c, aname); /* at this point ac is responsible for keeping c alive */ - cclose(c); poperror(); /* c */ - free(aname); + cclose(c); poperror(); /* aname */ + free(aname); if(waserror()){ cclose(ac); nexterror(); } - fd = newfd(ac); if(fd < 0) error(Enofd);