• Jason A. Donenfeld's avatar
    random: split initialization into early step and later step · f6238499
    Jason A. Donenfeld authored
    The full RNG initialization relies on some timestamps, made possible
    with initialization 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 provide 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.
    
    One subtle side effect of this change is that on systems with no RDRAND,
    RDTSC is now only queried by random_init() once, committing the moment
    of the function call, instead of multiple times as before. This is
    intentional, as the multiple RDTSCs in a loop before weren't
    accomplishing very much, with jitter being better provided by
    try_to_generate_entropy(). Plus, filling blocks with RDTSC is still
    being done in extract_entropy(), which is necessarily called before
    random bytes are served anyway.
    
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Reviewed-by: default avatarKees Cook <keescook@chromium.org>
    Reviewed-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
    Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
    f6238499
main.c 39.7 KB