All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net] vsock: do not reset a socket in connect() once it has connected
@ 2026-08-12 20:13 Hyunwoo Kim
  0 siblings, 0 replies; only message in thread
From: Hyunwoo Kim @ 2026-08-12 20:13 UTC (permalink / raw)
  To: sgarzare, davem, edumazet, kuba, pabeni, horms, mhal, leonardi,
	bobbyeshleman, stefanha, mst
  Cc: virtualization, netdev, imv4bel

commit 002541ef650b ("vsock: Ignore signal/timeout on connect() if
already established") stopped connect() from resetting an established
socket. The check only looks at whether sk_state is TCP_ESTABLISHED at
that moment, and the state can change while connect() sleeps.

A peer RST moves the socket to TCP_CLOSING, and it is not removed from
vsock_connected_table on that path. connect() then wakes up, fails the
check, and resets a socket that had actually connected to TCP_CLOSE and
SS_UNCONNECTED.

The socket can now be connected again while it is still on the table.
Reconnecting to an address served by a different transport makes
vsock_assign_transport() drop the transport from a live socket and free
vsk->trans, even if skbs it already sent are still in flight.
Reconnecting to the same address inserts a node that is already on the
table, provided shutdown() has cleared SOCK_DONE in between.

sock->state cannot be used for the check either. shutdown() overwrites
SS_CONNECTED with SS_DISCONNECTING.

Record on the socket that the connection completed, and check that
instead. The sk_err path after the loop does the same reset, so guard it
as well.

Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
Cc: stable@vger.kernel.org
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
---
 include/net/af_vsock.h   |  2 ++
 net/vmw_vsock/af_vsock.c | 12 ++++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 30046a3c20f735..d7ec976ed6e272 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -63,6 +63,8 @@ struct vsock_sock {
 	struct delayed_work pending_work;
 	struct delayed_work close_work;
 	bool close_work_scheduled;
+	/* Set once the connection completed; never cleared. */
+	bool ever_connected;
 	u32 peer_shutdown;
 	bool sent_request;
 	bool ignore_connecting_rst;
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 622dbd04679944..735c91bb762242 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -351,6 +351,8 @@ void vsock_insert_connected(struct vsock_sock *vsk)
 	struct list_head *list = vsock_connected_sockets(
 		&vsk->remote_addr, &vsk->local_addr);
 
+	vsk->ever_connected = true;
+
 	spin_lock_bh(&vsock_table_lock);
 	__vsock_insert_connected(list, vsk);
 	spin_unlock_bh(&vsock_table_lock);
@@ -1814,14 +1816,14 @@ static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,
 		 * Note that allowing to "reset" an already established socket
 		 * here is racy and insecure.
 		 */
-		if (sk->sk_state == TCP_ESTABLISHED)
+		if (vsk->ever_connected)
 			break;
 
 		/* If connection was _not_ established and a signal/timeout came
 		 * to be, we want the socket's state reset. User space may want
 		 * to retry.
 		 *
-		 * sk_state != TCP_ESTABLISHED implies that socket is not on
+		 * !ever_connected implies that socket is not on
 		 * vsock_connected_table. We keep the binding and the transport
 		 * assigned.
 		 */
@@ -1849,8 +1851,10 @@ static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,
 
 	if (sk->sk_err) {
 		err = -sk->sk_err;
-		sk->sk_state = TCP_CLOSE;
-		sock->state = SS_UNCONNECTED;
+		if (!vsk->ever_connected) {
+			sk->sk_state = TCP_CLOSE;
+			sock->state = SS_UNCONNECTED;
+		}
 	} else {
 		err = 0;
 	}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-08-12 20:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-12 20:13 [PATCH net] vsock: do not reset a socket in connect() once it has connected Hyunwoo Kim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.