]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bpf, sockmap: Account for receive queue in FIONREAD without a verdict program
authorMattia Meleleo <mattia.meleleo@coralogix.com>
Wed, 8 Jul 2026 16:55:00 +0000 (18:55 +0200)
committerKumar Kartikeya Dwivedi <memxor@gmail.com>
Wed, 15 Jul 2026 09:10:14 +0000 (11:10 +0200)
tcp_bpf_ioctl() answers SIOCINQ from psock->msg_tot_len, which only
counts bytes in ingress_msg. Without a stream/skb verdict program
nothing is diverted there: data stays in sk_receive_queue, so FIONREAD
returns 0 even though read() returns data.

Add tcp_inq() to the reported value when the psock has no verdict
program. The two queues are disjoint, so bytes redirected into
ingress_msg from other sockets stay correctly accounted through
msg_tot_len.

Remove unused sk_psock_msg_inq().

Fixes: 929e30f93125 ("bpf, sockmap: Fix FIONREAD for sockmap")
Signed-off-by: Mattia Meleleo <mattia.meleleo@coralogix.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Reviewed-by: John Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/20260708-fionread-no-verdict-v3-1-b4ee31b3af53@coralogix.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
include/linux/skmsg.h
net/ipv4/tcp_bpf.c

index a8553401b1c93fd5685c798a41d1df856af3cfc7..d5e35f24738d5cb9cf4b365417f05e1c495f5f0f 100644 (file)
@@ -551,20 +551,6 @@ static inline void psock_progs_drop(struct sk_psock_progs *progs)
        psock_set_prog(&progs->skb_verdict, NULL);
 }
 
-/* for tcp only, sk is locked */
-static inline ssize_t sk_psock_msg_inq(struct sock *sk)
-{
-       struct sk_psock *psock;
-       ssize_t inq = 0;
-
-       psock = sk_psock_get(sk);
-       if (likely(psock)) {
-               inq = sk_psock_get_msg_len_nolock(psock);
-               sk_psock_put(sk, psock);
-       }
-       return inq;
-}
-
 /* for udp only, sk is not locked */
 static inline ssize_t sk_msg_first_len(struct sock *sk)
 {
index cc0bd73f36b6d63d253d122be9bb2ac33f34d602..8e905b50deadbe7e529985c5c1d2b44aff952d76 100644 (file)
@@ -334,6 +334,7 @@ unlock:
 
 static int tcp_bpf_ioctl(struct sock *sk, int cmd, int *karg)
 {
+       struct sk_psock *psock;
        bool slow;
 
        if (cmd != SIOCINQ)
@@ -344,7 +345,21 @@ static int tcp_bpf_ioctl(struct sock *sk, int cmd, int *karg)
                return -EINVAL;
 
        slow = lock_sock_fast(sk);
-       *karg = sk_psock_msg_inq(sk);
+       psock = sk_psock_get(sk);
+       if (unlikely(!psock)) {
+               unlock_sock_fast(sk, slow);
+               return tcp_ioctl(sk, cmd, karg);
+       }
+       *karg = sk_psock_get_msg_len_nolock(psock);
+       /* Without a verdict program, ingress data is never diverted to
+        * ingress_msg: it stays in sk_receive_queue and is read through
+        * the fallback to tcp_recvmsg(), so account for it like
+        * tcp_ioctl() does.
+        */
+       if (!READ_ONCE(psock->progs.stream_verdict) &&
+           !READ_ONCE(psock->progs.skb_verdict))
+               *karg += tcp_inq(sk);
+       sk_psock_put(sk, psock);
        unlock_sock_fast(sk, slow);
 
        return 0;