• David Howells's avatar
    rxrpc: Fix race between conn bundle lookup and bundle removal [ZDI-CAN-15975] · 3bcd6c7e
    David Howells authored
    After rxrpc_unbundle_conn() has removed a connection from a bundle, it
    checks to see if there are any conns with available channels and, if not,
    removes and attempts to destroy the bundle.
    
    Whilst it does check after grabbing client_bundles_lock that there are no
    connections attached, this races with rxrpc_look_up_bundle() retrieving the
    bundle, but not attaching a connection for the connection to be attached
    later.
    
    There is therefore a window in which the bundle can get destroyed before we
    manage to attach a new connection to it.
    
    Fix this by adding an "active" counter to struct rxrpc_bundle:
    
     (1) rxrpc_connect_call() obtains an active count by prepping/looking up a
         bundle and ditches it before returning.
    
     (2) If, during rxrpc_connect_call(), a connection is added to the bundle,
         this obtains an active count, which is held until the connection is
         discarded.
    
     (3) rxrpc_deactivate_bundle() is created to drop an active count on a
         bundle and destroy it when the active count reaches 0.  The active
         count is checked inside client_bundles_lock() to prevent a race with
         rxrpc_look_up_bundle().
    
     (4) rxrpc_unbundle_conn() then calls rxrpc_deactivate_bundle().
    
    Fixes: 245500d8 ("rxrpc: Rewrite the client connection manager")
    Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-15975
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    Tested-by: zdi-disclosures@trendmicro.com
    cc: Marc Dionne <marc.dionne@auristor.com>
    cc: linux-afs@lists.infradead.org
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    3bcd6c7e
conn_client.c 28.9 KB