• David Howells's avatar
    rxrpc: Fix locking issue · ad25f5cb
    David Howells authored
    There's a locking issue with the per-netns list of calls in rxrpc.  The
    pieces of code that add and remove a call from the list use write_lock()
    and the calls procfile uses read_lock() to access it.  However, the timer
    callback function may trigger a removal by trying to queue a call for
    processing and finding that it's already queued - at which point it has a
    spare refcount that it has to do something with.  Unfortunately, if it puts
    the call and this reduces the refcount to 0, the call will be removed from
    the list.  Unfortunately, since the _bh variants of the locking functions
    aren't used, this can deadlock.
    
    ================================
    WARNING: inconsistent lock state
    5.18.0-rc3-build4+ #10 Not tainted
    --------------------------------
    inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
    ksoftirqd/2/25 [HC0[0]:SC1[1]:HE1:SE0] takes:
    ffff888107ac4038 (&rxnet->call_lock){+.?.}-{2:2}, at: rxrpc_put_call+0x103/0x14b
    {SOFTIRQ-ON-W} state was registered at:
    ...
     Possible unsafe locking scenario:
    
           CPU0
           ----
      lock(&rxnet->call_lock);
      <Interrupt>
        lock(&rxnet->call_lock);
    
     *** DEADLOCK ***
    
    1 lock held by ksoftirqd/2/25:
     #0: ffff8881008ffdb0 ((&call->timer)){+.-.}-{0:0}, at: call_timer_fn+0x5/0x23d
    
    Changes
    =======
    ver #2)
     - Changed to using list_next_rcu() rather than rcu_dereference() directly.
    
    Fixes: 17926a79 ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    cc: Marc Dionne <marc.dionne@auristor.com>
    cc: linux-afs@lists.infradead.org
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    ad25f5cb
list.h 31.4 KB