Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4562ca7 authored by Dexuan Cui's avatar Dexuan Cui Committed by David S. Miller
Browse files

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: default avatarDexuan 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: default avatarDavid S. Miller <davem@davemloft.net>
parent 0a90e251
Loading
Loading
Loading
Loading
+18 −4
Original line number Diff line number Diff line
@@ -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)