]> git.lizzy.rs Git - plan9front.git/commitdiff
kernel: make exec clear errstr, stop side-channels and truncate on utf8 boundary
authorcinap_lenrek <cinap_lenrek@felloff.net>
Wed, 4 Sep 2019 00:40:41 +0000 (02:40 +0200)
committercinap_lenrek <cinap_lenrek@felloff.net>
Wed, 4 Sep 2019 00:40:41 +0000 (02:40 +0200)
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.

sys/src/9/port/lib.h
sys/src/9/port/sysproc.c

index f991285ce8bfdf07118d8a2213deba03ae499048..1f7bf7d1d88eb4c0825bc9248969e9fcc8ae0a32 100644 (file)
@@ -47,6 +47,7 @@ enum
  */
 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);
index 5361429c4f3f370936e4c01ec527076a0d1c7408..7625b946c1f1f4c80a3f1fdae512c6a38ec1ae41 100644 (file)
@@ -572,6 +572,9 @@ sysexec(va_list list)
        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 @@ werrstr(char *fmt, ...)
 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;
 }