diff options
author | Theodore Ts'o <tytso@mit.edu> | 2019-05-22 12:02:16 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-06-25 11:48:58 +0200 |
commit | 6db0daa5450f53c91ad7eb8d34ce68f532b6b186 (patch) | |
tree | bc11572c651a47ea66cf3708ab902dd5639d1386 | |
parent | 00a0b39aee6aa9220dd90d0cf93c949bacb7f593 (diff) | |
download | linux-stable-6db0daa5450f53c91ad7eb8d34ce68f532b6b186.tar.gz linux-stable-6db0daa5450f53c91ad7eb8d34ce68f532b6b186.tar.bz2 linux-stable-6db0daa5450f53c91ad7eb8d34ce68f532b6b186.zip |
random: fix soft lockup when trying to read from an uninitialized blocking pool
commit 58be0106c5306b939b07b4b8bf00669a20593f4b upstream.
Fixes: eb9d1bf079bb: "random: only read from /dev/random after its pool has received 128 bits"
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/char/random.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index 986429d9e07c..e62df1693511 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -773,8 +773,11 @@ retry: if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) goto retry; - if (has_initialized) + if (has_initialized) { r->initialized = 1; + wake_up_interruptible(&random_read_wait); + kill_fasync(&fasync, SIGIO, POLL_IN); + } trace_credit_entropy_bits(r->name, nbits, entropy_count >> ENTROPY_SHIFT, _RET_IP_); @@ -790,6 +793,13 @@ retry: entropy_bits = r->entropy_count >> ENTROPY_SHIFT; } + /* initialize the blocking pool if necessary */ + if (entropy_bits >= random_read_wakeup_bits && + !other->initialized) { + schedule_work(&other->push_work); + return; + } + /* should we wake readers? */ if (entropy_bits >= random_read_wakeup_bits && wq_has_sleeper(&random_read_wait)) { @@ -2002,8 +2012,8 @@ _random_read(int nonblock, char __user *buf, size_t nbytes) return -EAGAIN; wait_event_interruptible(random_read_wait, - ENTROPY_BITS(&input_pool) >= - random_read_wakeup_bits); + blocking_pool.initialized && + (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits)); if (signal_pending(current)) return -ERESTARTSYS; } |