• David Howells's avatar
    rxrpc: Fix incoming call setup race · 42f229c3
    David Howells authored
    An incoming call can race with rxrpc socket destruction, leading to a
    leaked call.  This may result in an oops when the call timer eventually
    expires:
    
       BUG: kernel NULL pointer dereference, address: 0000000000000874
       RIP: 0010:_raw_spin_lock_irqsave+0x2a/0x50
       Call Trace:
        <IRQ>
        try_to_wake_up+0x59/0x550
        ? __local_bh_enable_ip+0x37/0x80
        ? rxrpc_poke_call+0x52/0x110 [rxrpc]
        ? rxrpc_poke_call+0x110/0x110 [rxrpc]
        ? rxrpc_poke_call+0x110/0x110 [rxrpc]
        call_timer_fn+0x24/0x120
    
    with a warning in the kernel log looking something like:
    
       rxrpc: Call 00000000ba5e571a still in use (1,SvAwtACK,1061d,0)!
    
    incurred during rmmod of rxrpc.  The 1061d is the call flags:
    
       RECVMSG_READ_ALL, RX_HEARD, BEGAN_RX_TIMER, RX_LAST, EXPOSED,
       IS_SERVICE, RELEASED
    
    but no DISCONNECTED flag (0x800), so it's an incoming (service) call and
    it's still connected.
    
    The race appears to be that:
    
     (1) rxrpc_new_incoming_call() consults the service struct, checks sk_state
         and allocates a call - then pauses, possibly for an interrupt.
    
     (2) rxrpc_release_sock() sets RXRPC_CLOSE, nulls the service pointer,
         discards the prealloc and releases all calls attached to the socket.
    
     (3) rxrpc_new_incoming_call() resumes, launching the new call, including
         its timer and attaching it to the socket.
    
    Fix this by read-locking local->services_lock to access the AF_RXRPC socket
    providing the service rather than RCU in rxrpc_new_incoming_call().
    There's no real need to use RCU here as local->services_lock is only
    write-locked by the socket side in two places: when binding and when
    shutting down.
    
    Fixes: 5e6ef4f1 ("rxrpc: Make the I/O thread take over the call and local processor work")
    Reported-by: default avatarMarc Dionne <marc.dionne@auristor.com>
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    cc: linux-afs@lists.infradead.org
    42f229c3
call_accept.c 13.8 KB