summaryrefslogtreecommitdiff
path: root/drivers/vhost
diff options
context:
space:
mode:
authorAlexander Graf <graf@amazon.com>2026-03-04 23:00:27 +0000
committerPaolo Abeni <pabeni@redhat.com>2026-03-12 10:59:36 +0100
commit0de607dc4fd80ede3b2a35e8a72f99c7a0bbc321 (patch)
tree72878c52d5623288bd4e0ff528e6d6f9c73d146f /drivers/vhost
parent17edc4e820bf8b4c7737c1de86c267e6974d543a (diff)
downloadlwn-0de607dc4fd80ede3b2a35e8a72f99c7a0bbc321.tar.gz
lwn-0de607dc4fd80ede3b2a35e8a72f99c7a0bbc321.zip
vsock: add G2H fallback for CIDs not owned by H2G transport
When no H2G transport is loaded, vsock currently routes all CIDs to the G2H transport (commit 65b422d9b61b ("vsock: forward all packets to the host when no H2G is registered"). Extend that existing behavior: when an H2G transport is loaded but does not claim a given CID, the connection falls back to G2H in the same way. This matters in environments like Nitro Enclaves, where an instance may run nested VMs via vhost-vsock (H2G) while also needing to reach sibling enclaves at higher CIDs through virtio-vsock-pci (G2H). With the old code, any CID > 2 was unconditionally routed to H2G when vhost was loaded, making those enclaves unreachable without setting VMADDR_FLAG_TO_HOST explicitly on every connect. Requiring every application to set VMADDR_FLAG_TO_HOST creates friction: tools like socat, iperf, and others would all need to learn about it. The flag was introduced 6 years ago and I am still not aware of any tool that supports it. Even if there was support, it would be cumbersome to use. The most natural experience is a single CID address space where H2G only wins for CIDs it actually owns, and everything else falls through to G2H, extending the behavior that already exists when H2G is absent. To give user space at least a hint that the kernel applied this logic, automatically set the VMADDR_FLAG_TO_HOST on the remote address so it can determine the path taken via getpeername(). Add a per-network namespace sysctl net.vsock.g2h_fallback (default 1). At 0 it forces strict routing: H2G always wins for CID > VMADDR_CID_HOST, or ENODEV if H2G is not loaded. Signed-off-by: Alexander Graf <graf@amazon.com> Tested-by: syzbot@syzkaller.appspotmail.com Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Link: https://patch.msgid.link/20260304230027.59857-1-graf@amazon.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'drivers/vhost')
-rw-r--r--drivers/vhost/vsock.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 054f7a718f50..1d8ec6bed53e 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -91,6 +91,18 @@ static struct vhost_vsock *vhost_vsock_get(u32 guest_cid, struct net *net)
return NULL;
}
+static bool vhost_transport_has_remote_cid(struct vsock_sock *vsk, u32 cid)
+{
+ struct sock *sk = sk_vsock(vsk);
+ struct net *net = sock_net(sk);
+ bool found;
+
+ rcu_read_lock();
+ found = !!vhost_vsock_get(cid, net);
+ rcu_read_unlock();
+ return found;
+}
+
static void
vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
struct vhost_virtqueue *vq)
@@ -424,6 +436,7 @@ static struct virtio_transport vhost_transport = {
.module = THIS_MODULE,
.get_local_cid = vhost_transport_get_local_cid,
+ .has_remote_cid = vhost_transport_has_remote_cid,
.init = virtio_transport_do_socket_init,
.destruct = virtio_transport_destruct,