• Jason A. Donenfeld's avatar
    random: do not use input pool from hard IRQs · e3e33fc2
    Jason A. Donenfeld authored
    Years ago, a separate fast pool was added for interrupts, so that the
    cost associated with taking the input pool spinlocks and mixing into it
    would be avoided in places where latency is critical. However, one
    oversight was that add_input_randomness() and add_disk_randomness()
    still sometimes are called directly from the interrupt handler, rather
    than being deferred to a thread. This means that some unlucky interrupts
    will be caught doing a blake2s_compress() call and potentially spinning
    on input_pool.lock, which can also be taken by unprivileged users by
    writing into /dev/urandom.
    
    In order to fix this, add_timer_randomness() now checks whether it is
    being called from a hard IRQ and if so, just mixes into the per-cpu IRQ
    fast pool using fast_mix(), which is much faster and can be done
    lock-free. A nice consequence of this, as well, is that it means hard
    IRQ context FPU support is likely no longer useful.
    
    The entropy estimation algorithm used by add_timer_randomness() is also
    somewhat different than the one used for add_interrupt_randomness(). The
    former looks at deltas of deltas of deltas, while the latter just waits
    for 64 interrupts for one bit or for one second since the last bit. In
    order to bridge these, and since add_interrupt_randomness() runs after
    an add_timer_randomness() that's called from hard IRQ, we add to the
    fast pool credit the related amount, and then subtract one to account
    for add_interrupt_randomness()'s contribution.
    
    A downside of this, however, is that the num argument is potentially
    attacker controlled, which puts a bit more pressure on the fast_mix()
    sponge to do more than it's really intended to do. As a mitigating
    factor, the first 96 bits of input aren't attacker controlled (a cycle
    counter followed by zeros), which means it's essentially two rounds of
    siphash rather than one, which is somewhat better. It's also not that
    much different from add_interrupt_randomness()'s use of the irq stack
    instruction pointer register.
    
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Filipe Manana <fdmanana@suse.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Borislav Petkov <bp@alien8.de>
    Cc: Theodore Ts'o <tytso@mit.edu>
    Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
    e3e33fc2
random.c 50.3 KB