Am Mon, Sep 26, 2022 at 11:31:29PM +0200 schrieb Jason A. Donenfeld:
The full RNG initialization relies on some timestamps, made possible with general functions like time_init() and timekeeping_init(). However, these are only available rather late in initialization. Meanwhile, other things, such as memory allocator functions, make use of the RNG much earlier.
So split RNG initialization into two phases. We can give arch randomness very early on, and then later, after timekeeping and such are available, initialize the rest.
This ensures that, for example, slabs are properly randomized if RDRAND is available. Without this, CONFIG_SLAB_FREELIST_RANDOM=y loses a degree of its security, because its random seed is potentially deterministic, since it hasn't yet incorporated RDRAND. It also makes it possible to use a better seed in kfence, which currently relies on only the cycle counter.
Another positive consequence is that on systems with RDRAND, running with CONFIG_WARN_ALL_UNSEEDED_RANDOM=y results in no warnings at all.
Nice improvement. One question, though:
#if defined(LATENT_ENTROPY_PLUGIN) static const u8 compiletime_seed[BLAKE2S_BLOCK_SIZE] __initconst __latent_entropy; @@ -803,34 +798,46 @@ int __init random_init(const char *command_line) i += longs; continue; }
entropy[0] = random_get_entropy();
arch_bits -= sizeof(*entropy) * 8; ++i; }_mix_pool_bytes(entropy, sizeof(*entropy));
Previously, random_get_entropy() was mixed into the pool ARRAY_SIZE(entropy) times.
+/*
- This is called a little bit after the prior function, and now there is
- access to timestamps counters. Interrupts are not yet enabled.
- */
+void __init random_init(void) +{
- unsigned long entropy = random_get_entropy();
- ktime_t now = ktime_get_real();
- _mix_pool_bytes(utsname(), sizeof(*(utsname())));
But now, it's only mixed into the pool once. Is this change on purpose?
Thanks, Dominik