Skip to content

Commit 009ba85

Browse files
ebiggerszx2c4
authored andcommitted
random: fix data race on crng init time
_extract_crng() does plain loads of crng->init_time and crng_global_init_time, which causes undefined behavior if crng_reseed() and RNDRESEEDCRNG modify these corrently. Use READ_ONCE() and WRITE_ONCE() to make the behavior defined. Don't fix the race on crng->init_time by protecting it with crng->lock, since it's not a problem for duplicate reseedings to occur. I.e., the lockless access with READ_ONCE() is fine. Fixes: d848e5f ("random: add new ioctl RNDRESEEDCRNG") Fixes: e192be9 ("random: replace non-blocking pool with a Chacha20-based CRNG") Cc: [email protected] Signed-off-by: Eric Biggers <[email protected]> Acked-by: Paul E. McKenney <[email protected]> Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent 5d73d1e commit 009ba85

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

drivers/char/random.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
991991
crng->state[i+4] ^= buf.key[i] ^ rv;
992992
}
993993
memzero_explicit(&buf, sizeof(buf));
994-
crng->init_time = jiffies;
994+
WRITE_ONCE(crng->init_time, jiffies);
995995
spin_unlock_irqrestore(&crng->lock, flags);
996996
if (crng == &primary_crng && crng_init < 2) {
997997
invalidate_batched_entropy();
@@ -1017,12 +1017,15 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
10171017
static void _extract_crng(struct crng_state *crng,
10181018
__u8 out[CHACHA_BLOCK_SIZE])
10191019
{
1020-
unsigned long v, flags;
1020+
unsigned long v, flags, init_time;
10211021

1022-
if (crng_ready() &&
1023-
(time_after(crng_global_init_time, crng->init_time) ||
1024-
time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)))
1025-
crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
1022+
if (crng_ready()) {
1023+
init_time = READ_ONCE(crng->init_time);
1024+
if (time_after(READ_ONCE(crng_global_init_time), init_time) ||
1025+
time_after(jiffies, init_time + CRNG_RESEED_INTERVAL))
1026+
crng_reseed(crng, crng == &primary_crng ?
1027+
&input_pool : NULL);
1028+
}
10261029
spin_lock_irqsave(&crng->lock, flags);
10271030
if (arch_get_random_long(&v))
10281031
crng->state[14] ^= v;
@@ -1962,7 +1965,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
19621965
if (crng_init < 2)
19631966
return -ENODATA;
19641967
crng_reseed(&primary_crng, &input_pool);
1965-
crng_global_init_time = jiffies - 1;
1968+
WRITE_ONCE(crng_global_init_time, jiffies - 1);
19661969
return 0;
19671970
default:
19681971
return -EINVAL;

0 commit comments

Comments
 (0)