Messages in this thread Patch in this message | | | From | Bernd Edlinger <> | Subject | [PATCHv2] random: Make /dev/random wait for crng_ready | Date | Fri, 15 Feb 2019 13:58:20 +0000 |
| |
Reading from /dev/random may return data while the getrandom syscall is still blocking.
Those bytes are not yet cryptographically secure.
The first byte from /dev/random can have as little as 8 bits entropy estimation. Once a read blocks, it will block until /proc/sys/kernel/random/read_wakeup_threshold bits are available, which is usually 64 bits, but can be configured as low as 8 bits. A select will wake up when at least read_wakeup_threshold bits are available. Also when constantly reading bytes out of /dev/random it will prevent the crng init done event forever.
Fixed by making read and select on /dev/random wait until the crng is fully initialized.
Signed-off-by: Bernd Edlinger <bernd.edlinger@hotmail.de> --- v2: Fixed one white space in the code. Also added some more details about the problem to the commit message. --- drivers/char/random.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c index bd449ad..c8f16f0 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -721,7 +721,7 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits) } /* should we wake readers? */ - if (entropy_bits >= random_read_wakeup_bits && + if (crng_ready() && entropy_bits >= random_read_wakeup_bits && wq_has_sleeper(&random_read_wait)) { wake_up_interruptible(&random_read_wait); kill_fasync(&fasync, SIGIO, POLL_IN); @@ -1826,7 +1826,9 @@ _random_read(int nonblock, char __user *buf, size_t nbytes) nbytes = min_t(size_t, nbytes, SEC_XFER_SIZE); while (1) { - n = extract_entropy_user(&blocking_pool, buf, nbytes); + n = crng_ready() + ? extract_entropy_user(&blocking_pool, buf, nbytes) + : 0; if (n < 0) return n; trace_random_read(n*8, (nbytes-n)*8, @@ -1840,6 +1842,7 @@ _random_read(int nonblock, char __user *buf, size_t nbytes) return -EAGAIN; wait_event_interruptible(random_read_wait, + crng_ready() && ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits); if (signal_pending(current)) @@ -1884,7 +1887,8 @@ random_poll(struct file *file, poll_table * wait) poll_wait(file, &random_read_wait, wait); poll_wait(file, &random_write_wait, wait); mask = 0; - if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits) + if (crng_ready() && + ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits) mask |= EPOLLIN | EPOLLRDNORM; if (ENTROPY_BITS(&input_pool) < random_write_wakeup_bits) mask |= EPOLLOUT | EPOLLWRNORM; -- 2.7.4
| |