let validaddr send a note and raise an error so resources can be freed on waserror() instead of calling pexit. the validaddr call in validname0 was removed, as the first byte should be already validated by the caller (from syscalls). vmemchr will validate all following pages of the name if it spans pages. let sysexec validnamedup() a save copy of the file argument. the rest of the changes are simplifications of the error handling mostly. this patch replaces: kernel-sysexec-validnamedup, kernel-sysfile-validaddr, kernel-segattach-validnamedup and kernel-namec-validaddr. removing the validaddr calls for the string arguments doesnt work as the user can pass kernel addresses! Reference: /n/sources/patch/applied/kernel-validname-error Date: Sun May 9 19:55:13 CES 2010 Signed-off-by: cinap_lenrek@gmx.de --- /sys/src/9/port/fault.c Sun May 9 19:33:05 2010 +++ /sys/src/9/port/fault.c Sun May 9 19:33:03 2010 @@ -337,8 +337,10 @@ 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); + } } /* --- /sys/src/9/port/chan.c Sun May 9 19:33:13 2010 +++ /sys/src/9/port/chan.c Sun May 9 19:33:08 2010 @@ -1686,7 +1686,6 @@ name = aname; if((ulong)name < KZERO){ - validaddr((ulong)name, 1, 0); if(!dup) print("warning: validname called from %lux with user pointer", pc); ename = vmemchr(name, 0, (1<<16)); --- /sys/src/9/port/auth.c Sun May 9 19:33:18 2010 +++ /sys/src/9/port/auth.c Sun May 9 19:33:15 2010 @@ -79,10 +79,10 @@ 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); --- /sys/src/9/port/sysproc.c Sun May 9 19:33:24 2010 +++ /sys/src/9/port/sysproc.c Sun May 9 19:33:20 2010 @@ -222,7 +222,7 @@ int i; Chan *tc; char **argv, **argp; - char *a, *charp, *args, *file; + char *a, *charp, *args, *file, *file0; char *progarg[sizeof(Exec)/2+1], *elem, progelem[64]; ulong ssize, spage, nargs, nbytes, n, bssend; int indir; @@ -233,14 +233,16 @@ ulong magic, text, entry, data, bss; Tos *tos; - validaddr(arg[0], 1, 0); - file = (char*)arg[0]; indir = 0; elem = nil; + validaddr(arg[0], 1, 0); + file0 = validnamedup((char*)arg[0], 1); if(waserror()){ + free(file0); free(elem); nexterror(); } + file = file0; for(;;){ tc = namec(file, Aopen, OEXEC, 0); if(waserror()){ @@ -373,6 +375,7 @@ memmove(charp, *argp++, n); charp += n; } + free(file0); free(up->text); up->text = elem; --- /sys/src/9/port/sysfile.c Sun May 9 19:33:31 2010 +++ /sys/src/9/port/sysfile.c Sun May 9 19:33:27 2010 @@ -266,16 +266,15 @@ sysopen(ulong *arg) { int fd; - Chan *c = 0; + Chan *c; openmode(arg[1]); /* error check only */ + validaddr(arg[0], 1, 0); + 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); @@ -999,9 +998,14 @@ if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER)) error(Ebadarg); - bogus.flags = flag & MCACHE; - if(ismount){ + validaddr((ulong)spec, 1, 0); + spec = validnamedup(spec, 1); + if(waserror()){ + free(spec); + nexterror(); + } + if(up->pgrp->noattach) error(Enoattach); @@ -1017,32 +1021,18 @@ 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; + spec = 0; validaddr((ulong)arg0, 1, 0); c0 = namec(arg0, Abind, 0, 0); } @@ -1059,15 +1049,17 @@ 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; } @@ -1098,35 +1090,28 @@ 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, * opening it is the only way to get at the real * Chan underneath. */ + validaddr(arg[0], 1, 0); 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; } @@ -1134,16 +1119,15 @@ syscreate(ulong *arg) { int fd; - Chan *c = 0; + Chan *c; openmode(arg[1]&~OEXCL); /* error check only; OEXCL okay here */ + validaddr(arg[0], 1, 0); + 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);