From 7713145638f45c07c47b9ef8c859d518d88f6127 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 11 Sep 2016 02:09:07 +0200 Subject: 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. --- sys/src/9/port/random.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'sys/src') diff --git a/sys/src/9/port/random.c b/sys/src/9/port/random.c index 012424aa6..d401e7e01 100644 --- a/sys/src/9/port/random.c +++ b/sys/src/9/port/random.c @@ -86,22 +86,37 @@ randominit(void) } 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); +} -- cgit v1.2.3