mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 01:08:13 -04:00
bpf, sockmap: Account for receive queue in FIONREAD without a verdict program
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: 929e30f931 ("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>
This commit is contained in:
committed by
Kumar Kartikeya Dwivedi
parent
71836d063d
commit
04af4efde5
@@ -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)
|
||||
{
|
||||
|
||||
@@ -334,6 +334,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user