diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-09-11 02:09:07 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-09-11 02:09:07 +0200 |
commit | 7713145638f45c07c47b9ef8c859d518d88f6127 (patch) | |
tree | 00380a228d0790111d29d82d745461fd053359c4 /sys/src/9/port | |
parent | a12180612649d5aebb2ca7e6c7727c41becb4549 (diff) |
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.
Diffstat (limited to 'sys/src/9/port')
-rw-r--r-- | sys/src/9/port/random.c | 31 |
1 files changed, 23 insertions, 8 deletions
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); +} |