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 --- 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