The virtio transports send every packet from the transport's CID, so a
socket bound to another local CID sends from another socket's address.
Patch 1 refuses connect() on such a socket; patches 2 and 3 close two
other ways a socket can send from another address or have its local
CID changed.

I'm sending this as an RFC because one problem is still open.  Over
vsock_loopback, a socket bound to (VMADDR_CID_LOCAL, P) sends from the
same address as the children of a listener on (guest CID, P) -- or, on
a host, on (VMADDR_CID_HOST, P) -- and vsock_check_source()
(dee44f41f206) accepts packets from either one as coming from the
peer.  So either one can shut down or stall the other's connections,
including those of clients that never called bind().  Making
vsock_loopback send from the bound CID would fix this and make patch 1
unnecessary for loopback.  Would you prefer that, or these patches as
they are?

Changes in v2:
- New approach.  v1 made bind() treat the same port on two local CIDs
  as a conflict, but as the Sashiko review pointed out, its alias list
  missed VMADDR_CID_HOST and did not handle guest->host transports
  without a CID.  I reproduced both gaps.  v2 leaves bind() alone.
- Patches 2 and 3 are new.
- Only the virtio transports change, vsock_loopback included.  VMCI
  picks its source context by route (a nested VMware guest reaches its
  VMs from VMADDR_CID_HOST), and hv_sock has no CIDs.
- v1: https://patch.msgid.link/[email protected]

I tested on net 4dca97647a3e (net/vmw_vsock is unchanged through
5838f10563d5) under QEMU/KVM with vsock_loopback built in, in four
setups: guests with vhost_vsock, with and without the virtio-vsock
device; a guest with the device but no vhost_vsock; and a host with
vhost_vsock and no virtio transport.  The table shows where each
problem reproduces as the patches are applied one at a time ("no dev"
is the guest without the device):

                       base          +1            +1+2     +1+2+3
  connect() reset      all           fixed         fixed    fixed
  credit update stall  all           all           fixed    fixed
  rebind to CID ANY    no dev, host  no dev, host  no dev   fixed

vsock_test passes at every step, and no connect() that used to succeed
is now refused.  I have not tested VMware, Hyper-V or nested setups,
nor run with KASAN, and there is no vsock_test case yet; I can add one.

The patch 1 problem was found with afb-afl, an LLM-driven audit
pipeline, and this letter was drafted with Claude.

Yiran Qiu (3):
  vsock/virtio: refuse connect() from a CID the transport does not own
  vsock/virtio: send credit updates only while connecting or connected
  vsock/virtio: only update a socket's local CID to the transport's CID

 net/vmw_vsock/virtio_transport_common.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

-- 
2.56.0


Reply via email to