ref: 8749b9e891e171477eb5b4923ca666e417e504dc
parent: bfb4b9cc038157da5b5f2b58a8bd581b902f1a77
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Sep 3 22:40:41 EDT 2019
kernel: make exec clear errstr, stop side-channels and truncate on utf8 boundary make exec() clear the per process error string to avoid spurious errors and confusion. the errstr() syscall used to always swap the maximum buffer size with memmove(), which is problematic as this gives access to the garbage beyond the NUL byte. worse, newproc(), werrstr() and rerrstr() only clear the first byte of the input buffer. so random stack rubble could be leaked across processes. we change the errstr() syscall to not copy beyond the NUL byte. the manpage also documents that errstr() should truncate on a utf8 boundary so we use utfecpy() to ensure proper NUL termination.
--- a/sys/src/9/port/lib.h
+++ b/sys/src/9/port/lib.h
@@ -47,6 +47,7 @@
*/
extern int runetochar(char*, Rune*);
extern int chartorune(Rune*, char*);
+extern char* utfecpy(char *s1, char *es1, char *s2);
extern char* utfrune(char*, long);
extern int utflen(char*);
extern int utfnlen(char*, long);
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -572,6 +572,9 @@
procsetup(up);
qunlock(&up->debug);
+ up->errbuf0[0] = '\0';
+ up->errbuf1[0] = '\0';
+
/*
* At this point, the mmu contains info about the old address
* space and needs to be flushed
@@ -698,20 +701,21 @@
static int
generrstr(char *buf, uint nbuf)
{- char tmp[ERRMAX];
+ char *err;
if(nbuf == 0)
error(Ebadarg);
+ if(nbuf > ERRMAX)
+ nbuf = ERRMAX;
validaddr((uintptr)buf, nbuf, 1);
- if(nbuf > sizeof tmp)
- nbuf = sizeof tmp;
- memmove(tmp, buf, nbuf);
- /* make sure it's NUL-terminated */
- tmp[nbuf-1] = '\0';
- memmove(buf, up->syserrstr, nbuf);
- buf[nbuf-1] = '\0';
- memmove(up->syserrstr, tmp, nbuf);
+ err = up->errstr;
+ utfecpy(err, err+nbuf, buf);
+ utfecpy(buf, buf+nbuf, up->syserrstr);
+
+ up->errstr = up->syserrstr;
+ up->syserrstr = err;
+
return 0;
}
--
⑨