diff mbox series

[v2,6/9] random: absorb fast pool into input pool after fast load

Message ID 20220209011919.493762-7-Jason@zx2c4.com (mailing list archive)
State Not Applicable
Delegated to: Herbert Xu
Headers show
Series random: cleanups around per-cpu crng & rdrand | expand

Commit Message

Jason A. Donenfeld Feb. 9, 2022, 1:19 a.m. UTC
During crng_init == 0, we never credit entropy in add_interrupt_
randomness(), but instead dump it directly into the base_crng. That's
fine, except for the fact that we then wind up throwing away that
entropy later when we switch to extracting from the input pool and
overwriting the base_crng key. The two other early init sites --
add_hwgenerator_randomness()'s use crng_fast_load() and add_device_
randomness()'s use of crng_slow_load() -- always additionally give their
inputs to the input pool. But not add_interrupt_randomness().

This commit fixes that shortcoming by calling mix_pool_bytes() after
crng_fast_load() in add_interrupt_randomness(). That's partially
verboten on PREEMPT_RT, where it implies taking spinlock_t from an IRQ
handler. But this also only happens during early boot and then never
again after that. Should this turn into a larger problem later for some
esoteric reason, we can always use `if (IS_ENABLED(PREEMPT_RT))` or
something similar to that. But for now, this should do.

Cc: Theodore Ts'o <tytso@mit.edu>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Suggested-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
 drivers/char/random.c | 7 +++++++
 1 file changed, 7 insertions(+)

Comments

Dominik Brodowski Feb. 9, 2022, 8:29 a.m. UTC | #1
Am Wed, Feb 09, 2022 at 02:19:16AM +0100 schrieb Jason A. Donenfeld:
> During crng_init == 0, we never credit entropy in add_interrupt_
> randomness(), but instead dump it directly into the base_crng. That's
> fine, except for the fact that we then wind up throwing away that
> entropy later when we switch to extracting from the input pool and
> overwriting the base_crng key. The two other early init sites --
> add_hwgenerator_randomness()'s use crng_fast_load() and add_device_
> randomness()'s use of crng_slow_load() -- always additionally give their
> inputs to the input pool. But not add_interrupt_randomness().

Hm, up to this patch there is no base_crng key. So maybe change the ordering
of the patches?

> This commit fixes that shortcoming by calling mix_pool_bytes() after
> crng_fast_load() in add_interrupt_randomness(). That's partially
> verboten on PREEMPT_RT, where it implies taking spinlock_t from an IRQ
> handler. But this also only happens during early boot and then never
> again after that. Should this turn into a larger problem later for some
> esoteric reason, we can always use `if (IS_ENABLED(PREEMPT_RT))` or
> something similar to that. But for now, this should do.
> 
> Cc: Theodore Ts'o <tytso@mit.edu>
> Cc: Dominik Brodowski <linux@dominikbrodowski.net>
> Suggested-by: Eric Biggers <ebiggers@google.com>
> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
> ---
>  drivers/char/random.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/char/random.c b/drivers/char/random.c
> index 785a4545c9d7..20374bce9a07 100644
> --- a/drivers/char/random.c
> +++ b/drivers/char/random.c
> @@ -864,6 +864,13 @@ void add_interrupt_randomness(int irq)
>  		    crng_fast_load((u8 *)fast_pool->pool, sizeof(fast_pool->pool)) > 0) {
>  			fast_pool->count = 0;
>  			fast_pool->last = now;
> +
> +			/* Technically this call means that we're using a spinlock_t
> +			 * in the IRQ handler, which isn't terrific for PREEMPT_RT.
> +			 * However, this only happens during very early boot, and then

Whether it's only during "very early" boot depends on how fast we progress
to crng_init = 2. So maybe just "during boot"?

Otherwise, all fine, so

	Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>

Thanks,
	Dominik
Jason A. Donenfeld Feb. 9, 2022, 10:45 a.m. UTC | #2
On Wed, Feb 9, 2022 at 9:31 AM Dominik Brodowski
<linux@dominikbrodowski.net> wrote:
>
> Am Wed, Feb 09, 2022 at 02:19:16AM +0100 schrieb Jason A. Donenfeld:
> > During crng_init == 0, we never credit entropy in add_interrupt_
> > randomness(), but instead dump it directly into the base_crng. That's
> > fine, except for the fact that we then wind up throwing away that
> > entropy later when we switch to extracting from the input pool and
> > overwriting the base_crng key. The two other early init sites --
> > add_hwgenerator_randomness()'s use crng_fast_load() and add_device_
> > randomness()'s use of crng_slow_load() -- always additionally give their
> > inputs to the input pool. But not add_interrupt_randomness().
>
> Hm, up to this patch there is no base_crng key. So maybe change the ordering
> of the patches?

I'll fix the commit message, actually. Eric wrote in his review of v1
that he thinks this problem needs to be fixed before we move to
overwriting keys in the subsequent patch and I agreed. Hence, this
patch comes first.

> > +
> > +                     /* Technically this call means that we're using a spinlock_t
> > +                      * in the IRQ handler, which isn't terrific for PREEMPT_RT.
> > +                      * However, this only happens during very early boot, and then
>
> Whether it's only during "very early" boot depends on how fast we progress
> to crng_init = 2. So maybe just "during boot"?

Will do.

Jason
diff mbox series

Patch

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 785a4545c9d7..20374bce9a07 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -864,6 +864,13 @@  void add_interrupt_randomness(int irq)
 		    crng_fast_load((u8 *)fast_pool->pool, sizeof(fast_pool->pool)) > 0) {
 			fast_pool->count = 0;
 			fast_pool->last = now;
+
+			/* Technically this call means that we're using a spinlock_t
+			 * in the IRQ handler, which isn't terrific for PREEMPT_RT.
+			 * However, this only happens during very early boot, and then
+			 * never again, so we live with it.
+			 */
+			mix_pool_bytes(&fast_pool->pool, sizeof(fast_pool->pool));
 		}
 		return;
 	}