All of lore.kernel.org
 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: 10+ 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 23:58       ` Emil Tsalapatis
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.