On Tue, Sep 22, 2026 at 03:18:13PM +0200, Michal Luczaj wrote:
On 9/16/26 14:30, Stefano Garzarella wrote:
On Tue, Sep 15, 2026 at 03:15:14PM +0200, Michal Luczaj wrote:
A non-blocking connect() running in parallel with a blocking connect(),
combined with a racy listen() that hits right after a connect timeout:
TCP_SYN_SENT -> TCP_CLOSE -> TCP_LISTEN, while the connect() loop is still
in progress.

Enforce the invariant. Prevent a socket from becoming a listener after
acquiring a transport.

We should improve this comment; it's not entirely clear to me, TBH.

The race I was thinking about:

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

It's not really critical (blocking connect() just timeouts), but I thought
the invariant should be enforced once and for all.

I see, would it better to do this change in net-next?


@@ -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) {

Are we changing the behavior when an error occurs?

If we call `connect()` on a socket (with no others running in parallel),
it fails, and then when we call `listen()`, it now fails, whereas before
it didn't. Can this happen? Is that what we want?

Ah, true, I didn't consider that. So yeah, we'd changing the behaviour.

If so, we should mention it at least in the commit description; if not,
perhaps we should unassign the transport in the `connect` call.

Do you mean immediately un-assign on every transition from SYN_SENT to
CLOSE (failure, timeout, signal)? Then we could also drop the re-assign
logic. I think that's a nice idea.

yeah, that!


---

I've addressed all your other comments for v2 and went through Ashiko's
reports (side effects of lockless peer_shutdown write, imperfect
no-transport TCP_LISTENER enforcement). I've decided to try the
eager-unassign approach. I think/hope this way we sidestep the lockless
writes and enforce the invariant without breaking the API, while fixing the
bugs.

This should probably be RFC, but I'm posting as v3[1] so netdev's LLM can
have a go (too). Hope I'm not breaking any workflow. Let me know what you
think.

I think you can add RFC also on a v3 patch, just to make it clear you are not sure it's ready to be merged.

That said, thanks for that :-) I'll take a look today or next week because I'm off tomorrow.

I'm just worried it's becoming too big for net. Anyway, I'll comment there.

Thanks,
Stefano


Reply via email to