• Samuel Thibault's avatar
    speakup: Fix clearing selection in safe context · 640969a6
    Samuel Thibault authored
    speakup_cut() calls speakup_clear_selection() which calls console_lock.
    Problem is: speakup_cut() is called from a keyboard interrupt
    context. This would hang if speakup_cut is pressed while the console
    lock is unfortunately already held.
    
    We can however as well just defer calling clear_selection() until the
    already-deferred set_selection_kernel() call.
    
    This was spotted by the lock hardener:
    
     Possible unsafe locking scenario:\x0a
           CPU0
           ----
      lock(console_lock);
      <Interrupt>
        lock(console_lock);
    \x0a *** DEADLOCK ***\x0a
    [...]
    Call Trace:
     <IRQ>
     dump_stack+0xc2/0x11a
     print_usage_bug.cold+0x3e0/0x4b1
     mark_lock+0xd95/0x1390
     ? print_irq_inversion_bug+0xa0/0xa0
     __lock_acquire+0x21eb/0x5730
     ? __kasan_check_read+0x11/0x20
     ? check_chain_key+0x215/0x5e0
     ? register_lock_class+0x1580/0x1580
     ? lock_downgrade+0x7a0/0x7a0
     ? __rwlock_init+0x140/0x140
     lock_acquire+0x13f/0x370
     ? speakup_clear_selection+0xe/0x20 [speakup]
     console_lock+0x33/0x50
     ? speakup_clear_selection+0xe/0x20 [speakup]
     speakup_clear_selection+0xe/0x20 [speakup]
     speakup_cut+0x19e/0x4b0 [speakup]
     keyboard_notifier_call+0x1f04/0x4a40 [speakup]
     ? read_all_doc+0x240/0x240 [speakup]
     notifier_call_chain+0xbf/0x130
     __atomic_notifier_call_chain+0x80/0x130
     atomic_notifier_call_chain+0x16/0x20
     kbd_event+0x7d7/0x3b20
     ? k_pad+0x850/0x850
     ? sysrq_filter+0x450/0xd40
     input_to_handler+0x362/0x4b0
     ? rcu_read_lock_sched_held+0xe0/0xe0
     input_pass_values+0x408/0x5a0
     ? __rwlock_init+0x140/0x140
     ? lock_acquire+0x13f/0x370
     input_handle_event+0x70e/0x1380
     input_event+0x67/0x90
     atkbd_interrupt+0xe62/0x1d4e [atkbd]
     ? __kasan_check_write+0x14/0x20
     ? atkbd_event_work+0x130/0x130 [atkbd]
     ? _raw_spin_lock_irqsave+0x26/0x70
     serio_interrupt+0x93/0x120 [serio]
     i8042_interrupt+0x232/0x510 [i8042]
     ? rcu_read_lock_bh_held+0xd0/0xd0
     ? handle_irq_event+0xa5/0x13a
     ? i8042_remove+0x1f0/0x1f0 [i8042]
     __handle_irq_event_percpu+0xe6/0x6c0
     handle_irq_event_percpu+0x71/0x150
     ? __handle_irq_event_percpu+0x6c0/0x6c0
     ? __kasan_check_read+0x11/0x20
     ? do_raw_spin_unlock+0x5c/0x240
     handle_irq_event+0xad/0x13a
     handle_edge_irq+0x233/0xa90
     do_IRQ+0x10b/0x310
     common_interrupt+0xf/0xf
     </IRQ>
    
    Cc: stable@vger.kernel.org
    Reported-by: default avatarJookia <contact@jookia.org>
    Signed-off-by: default avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
    Link: https://lore.kernel.org/r/20201107233310.7iisvaozpiqj3yvy@functionSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    640969a6
selection.c 3.5 KB