BPF List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Nnamdi Onyeyiri" <nnamdio@gmail.com>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH v6 1/2] bpf, sockmap: handle spurious tcp_msg_wait_data() wakeup
Date: Mon, 20 Jul 2026 17:32:24 +0000	[thread overview]
Message-ID: <20260720173224.9796B1F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260720171535.67867-2-nnamdio@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] Non-blocking reads and signal interrupts bypass the fallback to tcp_recvmsg(), breaking read semantics.
- [High] Early return on SOCK_DONE causes data loss and premature EOF.

Pre-existing issues:
- [High] Calling recvmsg() with a length of 0 causes a kernel hang (infinite loop) if data is present.
--

--- Patch [1]: [PATCH v6 1/2] bpf, sockmap: handle spurious tcp_msg_wait_data() wakeup ---
commit 82673cd18298f61fda976da0ad0dad3a80e2c280
Author: Nnamdi Onyeyiri <nnamdio@gmail.com>

bpf, sockmap: handle spurious tcp_msg_wait_data() wakeup

recvfrom()/recv() are documented as only returning EAGAIN for blocking
sockets when they have a receive timeout configured. However, adding a
blocking ipv4 tcp socket without a receive timeout to a sockmap will
cause EAGAIN errors sporadically.

> diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
> index 8e905b50deadb..e1c0f8b0930e1 100644
> --- a/net/ipv4/tcp_bpf.c
> +++ b/net/ipv4/tcp_bpf.c
[ ... ]
> @@ -262,6 +263,8 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
>  		}
>  	}
>  
> +	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
> +
>  msg_bytes_ready:
>  	copied = __sk_msg_recvmsg(sk, psock, msg, len, flags, &copied_from_self);
>  	/* The typical case for EFAULT is the socket was gracefully

[Severity: High]
This is a pre-existing issue, but can this loop spin infinitely if a user
calls recv() with a length of 0?

If len is 0, __sk_msg_recvmsg() bypasses its internal loop and returns 0.
The code then enters the if (!copied) branch and calls tcp_msg_wait_data(). 
If there is data in the psock queue, the wait queue condition is met
immediately and it returns 1.

The loop then hits the check:

    if (data && !sk_psock_queue_empty(psock))
        goto msg_bytes_ready;

This unconditionally jumps back to the top of the loop, creating a
CPU-spinning infinite loop that could be triggered by an unprivileged
local user. Does this need an explicit check for len == 0? (This same
pattern exists in tcp_bpf_recvmsg as well).

[ ... ]
> @@ -386,14 +390,59 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
>  		return tcp_recvmsg(sk, msg, len, flags);
>  	}
>  	lock_sock(sk);
> +
> +	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
> +
>  msg_bytes_ready:
>  	copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
>  	if (!copied) {
> -		long timeo;
>  		int data;
>  
> -		timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
> -		data = tcp_msg_wait_data(sk, psock, timeo);
> +		if (sock_flag(sk, SOCK_DONE)) {
> +			ret = 0;
> +			goto unlock;
> +		}

[Severity: High]
Does this early return cause data loss if unread data remains in the receive
queue after a FIN is received?

When a TCP FIN is received, SOCK_DONE is set on the socket. However, this
does not imply the receive queue is empty; valid data received before the
FIN may still reside in sk->sk_receive_queue.

By returning 0 immediately here, we skip the fallback to tcp_recvmsg() which
would correctly drain the receive queue before returning EOF. Can this strand
and lose unread data?

[ ... ]
> +		if (!timeo) {
> +			ret = -EAGAIN;
> +			goto unlock;
> +		}
> +
> +		if (signal_pending(current)) {
> +			ret = sock_intr_errno(timeo);
> +			goto unlock;
> +		}

[Severity: High]
Do these early returns break non-blocking reads and signal handling for
sockets that have buffered data?

When MSG_DONTWAIT is set, timeo is 0 and this code returns -EAGAIN
immediately. This completely skips the fallback check later in the function:

    if (!skb_queue_empty(&sk->sk_receive_queue)) {
        release_sock(sk);
        ...
        return tcp_recvmsg(sk, ...);
    }

For a socket added to a sockmap without a verdict program, incoming data
buffers in the standard TCP receive queue. Returning -EAGAIN or returning
due to a signal here bypasses reading that buffered data, which seems to
break read semantics for non-blocking sockets.

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260720171535.67867-1-nnamdio@gmail.com?part=1

  reply	other threads:[~2026-07-20 17:32 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20 17:15 [PATCH v6 0/2] bpf, sockmap: handle spurious tcp_msg_wait_data() wakeup Nnamdi Onyeyiri
2026-07-20 17:15 ` [PATCH v6 1/2] " Nnamdi Onyeyiri
2026-07-20 17:32   ` sashiko-bot [this message]
2026-07-20 21:16   ` Emil Tsalapatis
2026-07-20 22:53     ` Nnamdi Onyeyiri
2026-07-20 17:15 ` [PATCH v6 2/2] selftests/bpf: add sockmap recvfrom EAGAIN selftest Nnamdi Onyeyiri
2026-07-20 21:47   ` Emil Tsalapatis
2026-07-20 22:07     ` Nnamdi Onyeyiri
2026-07-20 22:17       ` Emil Tsalapatis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260720173224.9796B1F00A3A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=nnamdio@gmail.com \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox