• David Howells's avatar
    rxrpc: Fix potential deadlock · 60034d3d
    David Howells authored
    There is a potential deadlock in rxrpc_peer_keepalive_dispatch() whereby
    rxrpc_put_peer() is called with the peer_hash_lock held, but if it reduces
    the peer's refcount to 0, rxrpc_put_peer() calls __rxrpc_put_peer() - which
    the tries to take the already held lock.
    
    Fix this by providing a version of rxrpc_put_peer() that can be called in
    situations where the lock is already held.
    
    The bug may produce the following lockdep report:
    
    ============================================
    WARNING: possible recursive locking detected
    5.2.0-next-20190718 #41 Not tainted
    --------------------------------------------
    kworker/0:3/21678 is trying to acquire lock:
    00000000aa5eecdf (&(&rxnet->peer_hash_lock)->rlock){+.-.}, at: spin_lock_bh
    /./include/linux/spinlock.h:343 [inline]
    00000000aa5eecdf (&(&rxnet->peer_hash_lock)->rlock){+.-.}, at:
    __rxrpc_put_peer /net/rxrpc/peer_object.c:415 [inline]
    00000000aa5eecdf (&(&rxnet->peer_hash_lock)->rlock){+.-.}, at:
    rxrpc_put_peer+0x2d3/0x6a0 /net/rxrpc/peer_object.c:435
    
    but task is already holding lock:
    00000000aa5eecdf (&(&rxnet->peer_hash_lock)->rlock){+.-.}, at: spin_lock_bh
    /./include/linux/spinlock.h:343 [inline]
    00000000aa5eecdf (&(&rxnet->peer_hash_lock)->rlock){+.-.}, at:
    rxrpc_peer_keepalive_dispatch /net/rxrpc/peer_event.c:378 [inline]
    00000000aa5eecdf (&(&rxnet->peer_hash_lock)->rlock){+.-.}, at:
    rxrpc_peer_keepalive_worker+0x6b3/0xd02 /net/rxrpc/peer_event.c:430
    
    Fixes: 330bdcfa ("rxrpc: Fix the keepalive generator [ver #2]")
    Reported-by: syzbot+72af434e4b3417318f84@syzkaller.appspotmail.com
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    Reviewed-by: default avatarMarc Dionne <marc.dionne@auristor.com>
    Reviewed-by: default avatarJeffrey Altman <jaltman@auristor.com>
    60034d3d
peer_object.c 12 KB