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 65b422d9b6 ("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>
This commit is contained in:
Alexander Graf
2026-03-04 23:00:27 +00:00
committed by Paolo Abeni
parent 17edc4e820
commit 0de607dc4f
6 changed files with 89 additions and 5 deletions

View File

@@ -602,3 +602,31 @@ it does not modify the current namespace or any existing children.
A namespace with ``ns_mode`` set to ``local`` cannot change
``child_ns_mode`` to ``global`` (returns ``-EPERM``).
g2h_fallback
------------
Controls whether connections to CIDs not owned by the host-to-guest (H2G)
transport automatically fall back to the guest-to-host (G2H) transport.
When enabled, if a connect targets a CID that the H2G transport (e.g.
vhost-vsock) does not serve, or if no H2G transport is loaded at all, the
connection is routed via the G2H transport (e.g. virtio-vsock) instead. This
allows a host running both nested VMs (via vhost-vsock) and sibling VMs
reachable through the hypervisor (e.g. Nitro Enclaves) to address both using
a single CID space, without requiring applications to set
``VMADDR_FLAG_TO_HOST``.
When the fallback is taken, ``VMADDR_FLAG_TO_HOST`` is automatically set on
the remote address so that userspace can determine the path via
``getpeername()``.
Note: With this sysctl enabled, user space that attempts to talk to a guest
CID which is not implemented by the H2G transport will create host vsock
traffic. Environments that rely on H2G-only isolation should set it to 0.
Values:
- 0 - Connections to CIDs <= 2 or with VMADDR_FLAG_TO_HOST use G2H;
all others use H2G (or fail with ENODEV if H2G is not loaded).
- 1 - Connections to CIDs not owned by H2G fall back to G2H. (default)