git: 9front

Download patch

ref: 1d563ec8e9a5a485597a9f9c24d1f5a698f2c8a3
parent: 90dd4f7fcc307ac5f538978ff720926d0ce678e1
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Sep 10 22:09:07 EDT 2016

kernel: make randomread() fault reentrant

we now access the user buffer in randomread() outside of the lock,
only copying and advancing the chacha state under the lock. this
means we can use randomread() within the fault handling path now
without fearing deadlock. this also allows multiple readers to
generate random numbers in parallel.

--- a/sys/src/9/port/random.c
+++ b/sys/src/9/port/random.c
@@ -86,22 +86,37 @@
 }
 
 ulong
-randomread(void *xp, ulong n)
+randomread(void *p, ulong n)
 {
+	Chachastate c;
+	ulong b;
+
 	if(n == 0)
 		return 0;
 
 	if(hwrandbuf != nil)
-		(*hwrandbuf)(xp, n);
+		(*hwrandbuf)(p, n);
 
-	if(waserror()){
-		qunlock(rs);
-		nexterror();
-	}
+	/* copy chacha state and advance block counter */
 	qlock(rs);
-	chacha_encrypt((uchar*)xp, n, rs);
+	c = *rs;
+	b = rs->input[12];
+	rs->input[12] += (n + ChachaBsize-1)/ChachaBsize;
+	if(rs->input[12] < b) rs->input[13]++;
 	qunlock(rs);
-	poperror();
 
+	/* encrypt the buffer, can fault */
+	chacha_encrypt((uchar*)p, n, &c);
+
+	/* prevent state leakage */
+	memset(&c, 0, sizeof(c));
+
 	return n;
+}
+
+/* used by fastrand() */
+void
+genrandom(uchar *p, int n)
+{
+	randomread(p, n);
 }
--