Skip to content

Commit

Permalink
vsock: correct removal of socket from the list
Browse files Browse the repository at this point in the history
The current vsock code for removal of socket from the list is both
subject to race and inefficient. It takes the lock, checks whether
the socket is in the list, drops the lock and if the socket was on the
list, deletes it from the list. This is subject to race because as soon
as the lock is dropped once it is checked for presence, that condition
cannot be relied upon for any decision. It is also inefficient because
if the socket is present in the list, it takes the lock twice.

Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
sunilmut authored and davem330 committed Jun 15, 2019
1 parent b373326 commit d5afa82
Showing 1 changed file with 7 additions and 31 deletions.
38 changes: 7 additions & 31 deletions net/vmw_vsock/af_vsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,15 +282,17 @@ EXPORT_SYMBOL_GPL(vsock_insert_connected);
void vsock_remove_bound(struct vsock_sock *vsk)
{
spin_lock_bh(&vsock_table_lock);
__vsock_remove_bound(vsk);
if (__vsock_in_bound_table(vsk))
__vsock_remove_bound(vsk);
spin_unlock_bh(&vsock_table_lock);
}
EXPORT_SYMBOL_GPL(vsock_remove_bound);

void vsock_remove_connected(struct vsock_sock *vsk)
{
spin_lock_bh(&vsock_table_lock);
__vsock_remove_connected(vsk);
if (__vsock_in_connected_table(vsk))
__vsock_remove_connected(vsk);
spin_unlock_bh(&vsock_table_lock);
}
EXPORT_SYMBOL_GPL(vsock_remove_connected);
Expand Down Expand Up @@ -326,35 +328,10 @@ struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
}
EXPORT_SYMBOL_GPL(vsock_find_connected_socket);

static bool vsock_in_bound_table(struct vsock_sock *vsk)
{
bool ret;

spin_lock_bh(&vsock_table_lock);
ret = __vsock_in_bound_table(vsk);
spin_unlock_bh(&vsock_table_lock);

return ret;
}

static bool vsock_in_connected_table(struct vsock_sock *vsk)
{
bool ret;

spin_lock_bh(&vsock_table_lock);
ret = __vsock_in_connected_table(vsk);
spin_unlock_bh(&vsock_table_lock);

return ret;
}

void vsock_remove_sock(struct vsock_sock *vsk)
{
if (vsock_in_bound_table(vsk))
vsock_remove_bound(vsk);

if (vsock_in_connected_table(vsk))
vsock_remove_connected(vsk);
vsock_remove_bound(vsk);
vsock_remove_connected(vsk);
}
EXPORT_SYMBOL_GPL(vsock_remove_sock);

Expand Down Expand Up @@ -485,8 +462,7 @@ static void vsock_pending_work(struct work_struct *work)
* incoming packets can't find this socket, and to reduce the reference
* count.
*/
if (vsock_in_connected_table(vsk))
vsock_remove_connected(vsk);
vsock_remove_connected(vsk);

sk->sk_state = TCP_CLOSE;

Expand Down

0 comments on commit d5afa82

Please sign in to comment.