[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250709-sockmap-splice-v3-2-b23f345a67fc@datadoghq.com>
Date: Wed, 09 Jul 2025 14:47:58 +0200
From: Vincent Whitchurch via B4 Relay <devnull+vincent.whitchurch.datadoghq.com@...nel.org>
To: John Fastabend <john.fastabend@...il.com>,
Jakub Sitnicki <jakub@...udflare.com>
Cc: Kuniyuki Iwashima <kuniyu@...gle.com>, Jakub Kicinski <kuba@...nel.org>,
netdev@...r.kernel.org, bpf@...r.kernel.org,
Vincent Whitchurch <vincent.whitchurch@...adoghq.com>
Subject: [PATCH bpf-next v3 2/5] tcp_bpf: Fix reading with splice(2)
From: Vincent Whitchurch <vincent.whitchurch@...adoghq.com>
If a socket is added to a sockmap with a verdict program which returns
SK_PASS, splice(2) is not able to read from the socket.
The verdict code removes skbs from the receive queue, checks them using
the bpf program, and then re-queues them onto a separate queue
(psock->ingress_msg). The sockmap code modifies the TCP recvmsg hook to
check this second queue also so that works. But the splice_read hooks is
not modified and the default tcp_read_splice() only reads the normal
receive queue so it never sees the skbs which have been re-queued.
Fix it by using copy_splice_read() when replacing the proto for the
sockmap. This could eventually be replaced with a more efficient custom
version.
Signed-off-by: Vincent Whitchurch <vincent.whitchurch@...adoghq.com>
---
net/ipv4/tcp_bpf.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index ba581785adb4..197429b6adae 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -3,6 +3,7 @@
#include <linux/skmsg.h>
#include <linux/filter.h>
+#include <linux/fs.h>
#include <linux/bpf.h>
#include <linux/init.h>
#include <linux/wait.h>
@@ -381,6 +382,13 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
return ret;
}
+static ssize_t tcp_bpf_splice_read(struct socket *sock, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags)
+{
+ return copy_splice_read(sock->file, ppos, pipe, len, flags);
+}
+
static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock,
struct sk_msg *msg, int *copied, int flags)
{
@@ -605,6 +613,7 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS],
prot[TCP_BPF_BASE].destroy = sock_map_destroy;
prot[TCP_BPF_BASE].close = sock_map_close;
prot[TCP_BPF_BASE].recvmsg = tcp_bpf_recvmsg;
+ prot[TCP_BPF_BASE].splice_read = tcp_bpf_splice_read;
prot[TCP_BPF_BASE].sock_is_readable = sk_msg_is_readable;
prot[TCP_BPF_TX] = prot[TCP_BPF_BASE];
--
2.34.1
Powered by blists - more mailing lists