hv_sock: add locking in the open/close/release code paths
Without the patch, when hvs_open_connection() hasn't completely established a connection (e.g. it has changed sk->sk_state to SS_CONNECTED, but hasn't inserted the sock into the connected queue), vsock_stream_connect() may see the sk_state change and return the connection to the userspace, and next when the userspace closes the connection quickly, hvs_release() may not see the connection in the connected queue; finally hvs_open_connection() inserts the connection into the queue, but we won't be able to purge the connection for ever. Signed-off-by: Dexuan Cui <decui@microsoft.com> Cc: K. Y. Srinivasan <kys@microsoft.com> Cc: Haiyang Zhang <haiyangz@microsoft.com> Cc: Stephen Hemminger <sthemmin@microsoft.com> Cc: Vitaly Kuznetsov <vkuznets@redhat.com> Cc: Cathy Avery <cavery@redhat.com> Cc: Rolf Neugebauer <rolf.neugebauer@docker.com> Cc: Marcelo Cerri <marcelo.cerri@canonical.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0a90e25198
commit
b4562ca792
|
@ -310,11 +310,15 @@ static void hvs_close_connection(struct vmbus_channel *chan)
|
|||
struct sock *sk = get_per_channel_state(chan);
|
||||
struct vsock_sock *vsk = vsock_sk(sk);
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
sk->sk_state = SS_UNCONNECTED;
|
||||
sock_set_flag(sk, SOCK_DONE);
|
||||
vsk->peer_shutdown |= SEND_SHUTDOWN | RCV_SHUTDOWN;
|
||||
|
||||
sk->sk_state_change(sk);
|
||||
|
||||
release_sock(sk);
|
||||
}
|
||||
|
||||
static void hvs_open_connection(struct vmbus_channel *chan)
|
||||
|
@ -344,6 +348,8 @@ static void hvs_open_connection(struct vmbus_channel *chan)
|
|||
if (!sk)
|
||||
return;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
if ((conn_from_host && sk->sk_state != VSOCK_SS_LISTEN) ||
|
||||
(!conn_from_host && sk->sk_state != SS_CONNECTING))
|
||||
goto out;
|
||||
|
@ -395,9 +401,7 @@ static void hvs_open_connection(struct vmbus_channel *chan)
|
|||
|
||||
vsock_insert_connected(vnew);
|
||||
|
||||
lock_sock(sk);
|
||||
vsock_enqueue_accept(sk, new);
|
||||
release_sock(sk);
|
||||
} else {
|
||||
sk->sk_state = SS_CONNECTED;
|
||||
sk->sk_socket->state = SS_CONNECTED;
|
||||
|
@ -410,6 +414,8 @@ static void hvs_open_connection(struct vmbus_channel *chan)
|
|||
out:
|
||||
/* Release refcnt obtained when we called vsock_find_bound_socket() */
|
||||
sock_put(sk);
|
||||
|
||||
release_sock(sk);
|
||||
}
|
||||
|
||||
static u32 hvs_get_local_cid(void)
|
||||
|
@ -476,13 +482,21 @@ static int hvs_shutdown(struct vsock_sock *vsk, int mode)
|
|||
|
||||
static void hvs_release(struct vsock_sock *vsk)
|
||||
{
|
||||
struct sock *sk = sk_vsock(vsk);
|
||||
struct hvsock *hvs = vsk->trans;
|
||||
struct vmbus_channel *chan = hvs->chan;
|
||||
struct vmbus_channel *chan;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
sk->sk_state = SS_DISCONNECTING;
|
||||
vsock_remove_sock(vsk);
|
||||
|
||||
release_sock(sk);
|
||||
|
||||
chan = hvs->chan;
|
||||
if (chan)
|
||||
hvs_shutdown(vsk, RCV_SHUTDOWN | SEND_SHUTDOWN);
|
||||
|
||||
vsock_remove_sock(vsk);
|
||||
}
|
||||
|
||||
static void hvs_destruct(struct vsock_sock *vsk)
|
||||
|
|
Loading…
Reference in New Issue