Socket can flip to TCP_LISTEN when connect() schedules out. Respect
listen() winning the race: let connect() time out, but don't reset the
socket.
sk is CLOSE UNCONNECTED
non-blocking connect():
sk := SYN_SENT CONNECTING
enqueue vsock_connect_timeout()
blocking connect():
release_sock()
schedule_timeout()
vsock_connect_timeout():
sk := CLOSE UNCONNECTED
listen():
sk := LISTEN UNCONNECTED
lock_sock()
sk is TCP_LISTEN UNCONNECTED
Signed-off-by: Michal Luczaj <[email protected]>
---
net/vmw_vsock/af_vsock.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 5a2d7e10ecb8..56c595942456 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1663,6 +1663,13 @@ static void vsock_unconnected_reset(struct sock *sk)
sock_owned_by_me(sk);
+ /*
+ * listen() can race connect() on schedule_timeout().
+ * Don't reset TCP_LISTEN.
+ */
+ if (sk->sk_state == TCP_LISTEN)
+ return;
+
/*
* Transport events are serviced by resetting each connected socket to
* TCP_CLOSE. The reset is done under vsock_table_lock but without
--
2.55.0