• Dexuan Cui's avatar
    hv_sock: Fix hang when a connection is closed · 91a71a61
    Dexuan Cui authored
    [ Upstream commit 685703b4 ]
    
    There is a race condition for an established connection that is being closed
    by the guest: the refcnt is 4 at the end of hvs_release() (Note: here the
    'remove_sock' is false):
    
    1 for the initial value;
    1 for the sk being in the bound list;
    1 for the sk being in the connected list;
    1 for the delayed close_work.
    
    After hvs_release() finishes, __vsock_release() -> sock_put(sk) *may*
    decrease the refcnt to 3.
    
    Concurrently, hvs_close_connection() runs in another thread:
      calls vsock_remove_sock() to decrease the refcnt by 2;
      call sock_put() to decrease the refcnt to 0, and free the sk;
      next, the "release_sock(sk)" may hang due to use-after-free.
    
    In the above, after hvs_release() finishes, if hvs_close_connection() runs
    faster than "__vsock_release() -> sock_put(sk)", then there is not any issue,
    because at the beginning of hvs_close_connection(), the refcnt is still 4.
    
    The issue can be resolved if an extra reference is taken when the
    connection is established.
    
    Fixes: a9eeb998 ("hv_sock: Add support for delayed close")
    Signed-off-by: default avatarDexuan Cui <decui@microsoft.com>
    Reviewed-by: default avatarSunil Muthuswamy <sunilmut@microsoft.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
    91a71a61
hyperv_transport.c 23.6 KB