• Jason A. Donenfeld's avatar
    random: handle creditable entropy from atomic process context · e871abcd
    Jason A. Donenfeld authored
    The entropy accounting changes a static key when the RNG has
    initialized, since it only ever initializes once. Static key changes,
    however, cannot be made from atomic context, so depending on where the
    last creditable entropy comes from, the static key change might need to
    be deferred to a worker.
    
    Previously the code used the execute_in_process_context() helper
    function, which accounts for whether or not the caller is
    in_interrupt(). However, that doesn't account for the case where the
    caller is actually in process context but is holding a spinlock.
    
    This turned out to be the case with input_handle_event() in
    drivers/input/input.c contributing entropy:
    
      [<ffffffd613025ba0>] die+0xa8/0x2fc
      [<ffffffd613027428>] bug_handler+0x44/0xec
      [<ffffffd613016964>] brk_handler+0x90/0x144
      [<ffffffd613041e58>] do_debug_exception+0xa0/0x148
      [<ffffffd61400c208>] el1_dbg+0x60/0x7c
      [<ffffffd61400c000>] el1h_64_sync_handler+0x38/0x90
      [<ffffffd613011294>] el1h_64_sync+0x64/0x6c
      [<ffffffd613102d88>] __might_resched+0x1fc/0x2e8
      [<ffffffd613102b54>] __might_sleep+0x44/0x7c
      [<ffffffd6130b6eac>] cpus_read_lock+0x1c/0xec
      [<ffffffd6132c2820>] static_key_enable+0x14/0x38
      [<ffffffd61400ac08>] crng_set_ready+0x14/0x28
      [<ffffffd6130df4dc>] execute_in_process_context+0xb8/0xf8
      [<ffffffd61400ab30>] _credit_init_bits+0x118/0x1dc
      [<ffffffd6138580c8>] add_timer_randomness+0x264/0x270
      [<ffffffd613857e54>] add_input_randomness+0x38/0x48
      [<ffffffd613a80f94>] input_handle_event+0x2b8/0x490
      [<ffffffd613a81310>] input_event+0x6c/0x98
    
    According to Guoyong, it's not really possible to refactor the various
    drivers to never hold a spinlock there. And in_atomic() isn't reliable.
    
    So, rather than trying to be too fancy, just punt the change in the
    static key to a workqueue always. There's basically no drawback of doing
    this, as the code already needed to account for the static key not
    changing immediately, and given that it's just an optimization, there's
    not exactly a hurry to change the static key right away, so deferal is
    fine.
    Reported-by: default avatarGuoyong Wang <guoyong.wang@mediatek.com>
    Cc: stable@vger.kernel.org
    Fixes: f5bda35f ("random: use static branch for crng_ready()")
    Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
    e871abcd
random.c 51.6 KB