• Desmond Cheong Zhi Xi's avatar
    fcntl: fix potential deadlock for &fasync_struct.fa_lock · 2f488f69
    Desmond Cheong Zhi Xi authored
    There is an existing lock hierarchy of
    &dev->event_lock --> &fasync_struct.fa_lock --> &f->f_owner.lock
    from the following call chain:
    
      input_inject_event():
        spin_lock_irqsave(&dev->event_lock,...);
        input_handle_event():
          input_pass_values():
            input_to_handler():
              evdev_events():
                evdev_pass_values():
                  spin_lock(&client->buffer_lock);
                  __pass_event():
                    kill_fasync():
                      kill_fasync_rcu():
                        read_lock(&fa->fa_lock);
                        send_sigio():
                          read_lock_irqsave(&fown->lock,...);
    
    &dev->event_lock is HARDIRQ-safe, so interrupts have to be disabled
    while grabbing &fasync_struct.fa_lock, otherwise we invert the lock
    hierarchy. However, since kill_fasync which calls kill_fasync_rcu is
    an exported symbol, it may not necessarily be called with interrupts
    disabled.
    
    As kill_fasync_rcu may be called with interrupts disabled (for
    example, in the call chain above), we replace calls to
    read_lock/read_unlock on &fasync_struct.fa_lock in kill_fasync_rcu
    with read_lock_irqsave/read_unlock_irqrestore.
    Signed-off-by: default avatarDesmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
    Signed-off-by: default avatarJeff Layton <jlayton@kernel.org>
    2f488f69
fcntl.c 23.8 KB