changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: kernel: make exec clear errstr, stop side-channels and truncate on utf8 boundary

changeset 7359: 4042bfad48ba
parent 7358: 329c64d814e4
child 7360: c47796355917
author: cinap_lenrek@felloff.net
date: Wed, 04 Sep 2019 02:40:41 +0200
files: sys/src/9/port/lib.h sys/src/9/port/sysproc.c
description: 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.
     1.1--- a/sys/src/9/port/lib.h
     1.2+++ b/sys/src/9/port/lib.h
     1.3@@ -47,6 +47,7 @@ enum
     1.4  */
     1.5 extern	int	runetochar(char*, Rune*);
     1.6 extern	int	chartorune(Rune*, char*);
     1.7+extern	char*	utfecpy(char *s1, char *es1, char *s2);
     1.8 extern	char*	utfrune(char*, long);
     1.9 extern	int	utflen(char*);
    1.10 extern	int	utfnlen(char*, long);
     2.1--- a/sys/src/9/port/sysproc.c
     2.2+++ b/sys/src/9/port/sysproc.c
     2.3@@ -572,6 +572,9 @@ sysexec(va_list list)
     2.4 	procsetup(up);
     2.5 	qunlock(&up->debug);
     2.6 
     2.7+	up->errbuf0[0] = '\0';
     2.8+	up->errbuf1[0] = '\0';
     2.9+
    2.10 	/*
    2.11 	 *  At this point, the mmu contains info about the old address
    2.12 	 *  space and needs to be flushed
    2.13@@ -698,20 +701,21 @@ werrstr(char *fmt, ...)
    2.14 static int
    2.15 generrstr(char *buf, uint nbuf)
    2.16 {
    2.17-	char tmp[ERRMAX];
    2.18+	char *err;
    2.19 
    2.20 	if(nbuf == 0)
    2.21 		error(Ebadarg);
    2.22+	if(nbuf > ERRMAX)
    2.23+		nbuf = ERRMAX;
    2.24 	validaddr((uintptr)buf, nbuf, 1);
    2.25-	if(nbuf > sizeof tmp)
    2.26-		nbuf = sizeof tmp;
    2.27-	memmove(tmp, buf, nbuf);
    2.28 
    2.29-	/* make sure it's NUL-terminated */
    2.30-	tmp[nbuf-1] = '\0';
    2.31-	memmove(buf, up->syserrstr, nbuf);
    2.32-	buf[nbuf-1] = '\0';
    2.33-	memmove(up->syserrstr, tmp, nbuf);
    2.34+	err = up->errstr;
    2.35+	utfecpy(err, err+nbuf, buf);
    2.36+	utfecpy(buf, buf+nbuf, up->syserrstr);
    2.37+
    2.38+	up->errstr = up->syserrstr;
    2.39+	up->syserrstr = err;
    2.40+	
    2.41 	return 0;
    2.42 }
    2.43