From: Jerome Mohm <[email protected]>
vsock_bpf_recvmsg() sends every read that the transport queue cannot
serve through sk_msg_recvmsg() and the sockmap wait, which handle
neither a zero length nor these flags:
- with len == 0 and data in the psock ingress queue the loop spins with
lock_sock() held, and the delivery worker blocks on the lock;
- MSG_ERRQUEUE with data in the psock ingress queue consumes stream
bytes, and a zero-length MSG_ERRQUEUE read, as MSG_ZEROCOPY users
do, never reaches the error queue: it gets -EAGAIN, or waits for
stream data if it blocks;
- MSG_OOB consumes ordinary stream bytes or waits for data, where the
native path returns -EOPNOTSUPP.
Handle them at the top of vsock_bpf_recvmsg(). The order matters:
MSG_ERRQUEUE goes to the native path first, as in tcp_bpf, or a
zero-length error-queue read would return 0; MSG_OOB comes before
len == 0, as in unix_bpf, so recv(fd, buf, 0, MSG_OOB) returns
-EOPNOTSUPP as on a connected native socket.
The MSG_ERRQUEUE case was found with the help of Anthropic's Claude, the
zero-length and MSG_OOB cases by the netdev Sashiko review. Each was
reproduced in a VM with a vsock-loopback socket in a sockmap, without
kernel changes or error injection. With the series applied the reads
behave as on a connected native socket, and the vsock vmtest.sh
single-VM tests and the BPF sockmap test_progs pass.
Fixes: 634f1a7110b4 ("vsock: support sockmap")
Cc: [email protected]
Signed-off-by: Jerome Mohm <[email protected]>
---
net/vmw_vsock/vsock_bpf.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/vmw_vsock/vsock_bpf.c b/net/vmw_vsock/vsock_bpf.c
index 6d96ff03f28c..58b32fbc1f4b 100644
--- a/net/vmw_vsock/vsock_bpf.c
+++ b/net/vmw_vsock/vsock_bpf.c
@@ -119,6 +119,15 @@ static int vsock_bpf_recvmsg(struct sock *sk, struct
msghdr *msg,
struct vsock_sock *vsk;
int copied;
+ if (unlikely(flags & MSG_ERRQUEUE))
+ return __vsock_recvmsg(sk, msg, len, flags);
+
+ if (flags & MSG_OOB)
+ return -EOPNOTSUPP;
+
+ if (!len)
+ return 0;
+
psock = sk_psock_get(sk);
if (unlikely(!psock))
return __vsock_recvmsg(sk, msg, len, flags);
--
2.56.0