Once a socket has a transport, changing its buffer size
(SO_VM_SOCKETS_BUFFER_*) sends a credit update in any state, from the
transport's CID to whatever remote address the last connect() left
behind.  So a socket bound to (guest CID, P) whose loopback connect()
failed or was refused still sends as (VMADDR_CID_LOCAL, P).  If another
process has a connection open from (VMADDR_CID_LOCAL, P) to the
listener that connect() targeted, the socket the listener accepted for
it takes the update's buf_alloc and fwd_cnt as its peer's, and can
stall.

On a host without a guest->host transport, a socket whose loopback
connect() failed can then connect() to VMADDR_CID_ANY with
VMADDR_FLAG_TO_HOST.  That fails with ENODEV but leaves VMADDR_CID_ANY
as the remote address, so the update reaches any loopback socket on
that port.

Only send the update while connecting or connected.  Now that connect()
refuses a CID the transport does not own and leaves a failed socket in
TCP_CLOSE, a socket in either state sends from its own address.

Found by an LLM review of an unposted draft of this series.  On
unmodified kernels, where the first connect() times out instead of
being refused, a non-blocking send() on the accepted socket returns
EAGAIN after the update; with this patch it succeeds, and vsock_test
passes.  Drafted with Claude.

Fixes: c0cfa2d8a788 ("vsock: add multi-transports support")
Signed-off-by: Yiran Qiu <[email protected]>
---
 net/vmw_vsock/virtio_transport_common.c |  4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/vmw_vsock/virtio_transport_common.c 
b/net/vmw_vsock/virtio_transport_common.c
index 8f524d073ae1..4d0511629044 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -1098,7 +1098,9 @@ void virtio_transport_notify_buffer_size(struct 
vsock_sock *vsk, u64 *val)
 
        vvs->buf_alloc = *val;
 
-       virtio_transport_send_credit_update(vsk);
+       if (sk_vsock(vsk)->sk_state == TCP_ESTABLISHED ||
+           sk_vsock(vsk)->sk_state == TCP_SYN_SENT)
+               virtio_transport_send_credit_update(vsk);
 }
 EXPORT_SYMBOL_GPL(virtio_transport_notify_buffer_size);
 
-- 
2.56.0


Reply via email to