mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: mhal@rbox.co
Cc: stefanha@redhat.com, sgarzare@redhat.com, mst@redhat.com,
	jasowangio@gmail.com, eperezma@redhat.com, davem@davemloft.net,
	xuanzhuo@linux.alibaba.com, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, asias@redhat.com,
	kvm@vger.kernel.org, virtualization@lists.linux.dev,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net v2 3/5] vsock: Enforce no-transport invariant for TCP_LISTEN sockets
Date: Wed, 16 Sep 2026 23:39:15 +0000	[thread overview]
Message-ID: <178960195580.22033.2015490803994413730@kernel.org> (raw)
In-Reply-To: <20260915-vsock-connect-reset-closing-v2-3-a1d9abb472f7@rbox.co>

Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:

Critical: 0 · High: 1 · Medium: 0 · Low: 0

- [High] Incomplete race fix: `vsk->transport != NULL` is not a reliable
  sentinel for "a connect() waiter is still in flight", so the exact bug…

--

vsock: Enforce no-transport invariant for TCP_LISTEN sockets

The patch makes vsock_listen() reject sockets that already have a transport
assigned, so that a socket cannot become a listener while a connect() wait
loop is still running on it.

> diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
> index f840498b58afb..499e902becfad 100644
> --- a/net/vmw_vsock/af_vsock.c
> +++ b/net/vmw_vsock/af_vsock.c
> @@ -1973,13 +1973,13 @@ static int vsock_listen(struct socket *sock, int backlog)
>  		goto out;
>  	}
>  
> -	if (sock->state != SS_UNCONNECTED) {
> +	vsk = vsock_sk(sk);
> +
> +	if (sock->state != SS_UNCONNECTED || vsk->transport) {
>  		err = -EINVAL;
>  		goto out;
>  	}

[Severity: High]
Is vsk->transport a reliable indicator that no connect() waiter is in
flight?

vsock_assign_transport() drops the old transport before the new one is
validated and initialized:

net/vmw_vsock/af_vsock.c:vsock_assign_transport() {
	...
	if (vsk->transport) {
		vsk->transport->release(vsk);
		vsock_deassign_transport(vsk);	/* vsk->transport = NULL */
		...
		sk->sk_state = TCP_CLOSE;
		...
	}

	if (sk->sk_type == SOCK_SEQPACKET) {
		if (!new_transport->seqpacket_allow ||
		    !new_transport->seqpacket_allow(vsk, remote_cid)) {
			module_put(new_transport->module);
			return -ESOCKTNOSUPPORT;
		}
	}

	ret = new_transport->init(vsk, psk);
	if (ret) {
		module_put(new_transport->module);
		return ret;
	}

	vsk->transport = new_transport;
	...
}

Both of those failure returns happen after vsock_deassign_transport(), so
the socket is left with vsk->transport == NULL while it is still alive and
still bound (vsock_remove_sock() keeps the binding unless SOCK_DEAD is set).

The seqpacket path looks reachable without any allocation failure: only
virtio_transport.c and vsock_loopback.c define .seqpacket_allow, so a
SOCK_SEQPACKET reassignment that resolves to vmci returns -ESOCKTNOSUPPORT.
The init path is reachable via the kzalloc in
virtio_transport_do_socket_init().

Can the following interleaving still put a listener into TCP_CLOSE?

Thread A: blocking connect(), transport T1 assigned, TCP_SYN_SENT,
	  sock->state = SS_CONNECTING, enters the wait loop
Thread B: connect() on the same fd hits case SS_CONNECTING (-EALREADY)
	  and joins the same wait loop
Thread A: timeout fires and runs the signal/timeout branch of
	  vsock_connect(), leaving TCP_CLOSE / SS_UNCONNECTED and keeping
	  T1 ("We keep the binding and the transport assigned"), while
	  thread B still sleeps with the sock lock released
Thread C: connect() to a peer that resolves to a different transport, so
	  vsock_assign_transport() deassigns T1 and then fails at the
	  seqpacket_allow check or in init(); vsk->transport is now NULL
Thread D: listen() sees sock->state == SS_UNCONNECTED and
	  vsk->transport == NULL, passes the new gate and sets TCP_LISTEN
Thread B: wakes up; TCP_LISTEN is neither TCP_ESTABLISHED nor TCP_CLOSING
	  and sk_err == 0, so it keeps looping, and on the next
	  signal/timeout it runs:

net/vmw_vsock/af_vsock.c:vsock_connect() {
	...
		if (signal_pending(current) || timeout == 0) {
			err = timeout == 0 ? -ETIMEDOUT : sock_intr_errno(timeout);
			...
			sk->sk_state = TCP_CLOSE;
			sock->state = SS_UNCONNECTED;

			vsock_transport_cancel_pkt(vsk);

			goto out_wait;
		}
	...
}

That stale waiter rewrites sk_state and sock->state without re-checking
whether the socket became a listener in the meantime, so accept() on it
would then return -EINVAL and incoming requests would no longer be queued,
while entries from the listener phase remain on pending_links/accept_queue.

The window is also user-controllable through SO_VM_SOCKETS_CONNECT_TIMEOUT,
which sets vsk->connect_timeout read at loop entry.

Reading the rest of the series, up to b93debf817d4 ("vsock: Handle sudden
TCP_CLOSE during connect"), vsock_assign_transport() is unchanged,
vsock_listen() still gates only on sock->state != SS_UNCONNECTED ||
vsk->transport, and the waiter still rewrites sk_state/sock->state, so the
gap does not appear to be closed later either.

Would it make more sense to express the invariant as "no connect() waiter
outstanding", or to make the reassignment failure paths not leave a live
socket transport-less?

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260915-vsock-connect-reset-closing-v2-0-a1d9abb472f7%40rbox.co

  parent reply	other threads:[~2026-09-16 23:39 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-15 13:15 [PATCH net v2 0/5] vsock: Fix connect() races Michal Luczaj
2026-09-15 13:15 ` [PATCH net v2 1/5] vhost/vsock: Fix socket state constant Michal Luczaj
2026-09-16 12:28   ` Stefano Garzarella
2026-09-15 13:15 ` [PATCH net v2 2/5] vsock/virtio: Streamline socket reset on transport/PM event Michal Luczaj
2026-09-16 12:30   ` Stefano Garzarella
2026-09-16 23:39   ` netdev-bot+sashiko
2026-09-15 13:15 ` [PATCH net v2 3/5] vsock: Enforce no-transport invariant for TCP_LISTEN sockets Michal Luczaj
2026-09-16 12:30   ` Stefano Garzarella
2026-09-16 23:39   ` netdev-bot+sashiko [this message]
2026-09-15 13:15 ` [PATCH net v2 4/5] vsock: Do not reset a TCP_CLOSING socket Michal Luczaj
2026-09-16 12:30   ` Stefano Garzarella
2026-09-16 23:39   ` netdev-bot+sashiko
2026-09-15 13:15 ` [PATCH net v2 5/5] vsock: Handle sudden TCP_CLOSE during connect Michal Luczaj
2026-09-16 12:31   ` Stefano Garzarella
2026-09-16 23:39   ` netdev-bot+sashiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178960195580.22033.2015490803994413730@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=asias@redhat.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=eperezma@redhat.com \
    --cc=horms@kernel.org \
    --cc=jasowangio@gmail.com \
    --cc=kuba@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mhal@rbox.co \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sgarzare@redhat.com \
    --cc=stefanha@redhat.com \
    --cc=virtualization@lists.linux.dev \
    --cc=xuanzhuo@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®