/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);