[PATCH net v6 1/2] vsock/bpf: fix zero-length, MSG_OOB and MSG_ERRQUEUE reads

From: Jerome Mohm via B4 Relay

Date: Sat Nov 14 2026 - 06:59:43 EST


From: Jerome Mohm <jrmmhm.kernel@xxxxxxxxx>

On a vsock socket in a sockmap, vsock_bpf_recvmsg() sends zero-length,
MSG_OOB and MSG_ERRQUEUE reads down the sockmap path whenever the psock
queue has data or nothing is queued at all. That path copies from the
psock queue and waits for data, and it handles none of these reads:

- a zero-length read with data in the psock queue spins with the
socket lock held, and the delivery worker blocks on that lock;
- MSG_ERRQUEUE consumes stream bytes from the psock queue, and the
zero-length MSG_ERRQUEUE read that MSG_ZEROCOPY users make to collect
completions gets -EAGAIN or blocks instead of reading the error
queue;
- MSG_OOB consumes ordinary stream bytes or waits for data, where a
connected native socket returns -EOPNOTSUPP.

Hand these reads to __vsock_recvmsg(), the path of a socket outside a
sockmap, which does not wait for any of them. They now take one path,
so the order of the checks no longer matters.

The MSG_ERRQUEUE case was found with the help of Anthropic's Claude,
its stream-byte and MSG_ZEROCOPY parts by Stefano, and the zero-length
and MSG_OOB cases by the netdev Sashiko reviews. Each was reproduced in
a VM with a vsock-loopback socket in a sockmap, without kernel changes
or error injection. With this patch alone they behave as on a native
socket. The vsock vmtest.sh single-VM tests and the BPF sockmap
selftests pass with the series; I did not run them on this patch alone.

Fixes: 634f1a7110b4 ("vsock: support sockmap")
Suggested-by: Alexei Starovoitov <alexei.starovoitov@xxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Jerome Mohm <jrmmhm.kernel@xxxxxxxxx>
---
net/vmw_vsock/vsock_bpf.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/net/vmw_vsock/vsock_bpf.c b/net/vmw_vsock/vsock_bpf.c
index 9049d2648646..c9b399f37720 100644
--- a/net/vmw_vsock/vsock_bpf.c
+++ b/net/vmw_vsock/vsock_bpf.c
@@ -80,6 +80,9 @@ static int vsock_bpf_recvmsg(struct sock *sk, struct msghdr *msg,
struct vsock_sock *vsk;
int copied;

+ if (unlikely(!len || (flags & (MSG_OOB | MSG_ERRQUEUE))))
+ return __vsock_recvmsg(sk, msg, len, flags);
+
psock = sk_psock_get(sk);
if (unlikely(!psock))
return __vsock_recvmsg(sk, msg, len, flags);

--
2.56.0