BPF List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jiayuan Chen" <jiayuan.chen@linux.dev>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v3 5/7] sockmap: Fix use-after-free in udp_bpf_recvmsg()
Date: Fri, 12 Jun 2026 13:24:54 +0000	[thread overview]
Message-ID: <20260612132454.F14321F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260612130919.299124-6-jiayuan.chen@linux.dev>

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

New issues:
- [Critical] Infinite loop holding the socket lock when data is pending in `ingress_skb` but not yet in `ingress_msg`.

Pre-existing issues:
- [High] Blocking recvmsg() incorrectly returns -EAGAIN instead of -EINTR (-ERESTARTSYS) when interrupted by a signal.
- [High] Delegating to `sk_udp_recvmsg` ignores data subsequently arriving via BPF redirect, causing a permanent hang.
- [High] udp_bpf_recvmsg() resets the receive timeout on every loop iteration, allowing indefinite blocking despite SO_RCVTIMEO.
- [High] udp_msg_wait_data() does not check sk_shutdown after waking up, causing recvmsg to return -EAGAIN instead of 0 on a closed socket.
--

commit d3eae210a4563564468c062b23ec1d89b4e36196
Author: Kuniyuki Iwashima <kuniyu@google.com>

sockmap: Fix use-after-free in udp_bpf_recvmsg()

This commit fixes a use-after-free of struct sk_msg in sk_msg_recvmsg()
reported by syzbot. It serialises sk_msg_recvmsg() by adding lock_sock()
inside udp_bpf_recvmsg(), ensuring that multiple threads do not concurrently
process the same sk_msg.

Link: https://lore.kernel.org/netdev/69922ac9.a70a0220.2c38d7.00e0.GAE@google.com/

> diff --git a/net/ipv4/udp_bpf.c b/net/ipv4/udp_bpf.c
> index 9f33b07b14813..ad57c4c9eaab6 100644
> --- a/net/ipv4/udp_bpf.c
> +++ b/net/ipv4/udp_bpf.c
> @@ -50,7 +50,9 @@ static int udp_msg_wait_data(struct sock *sk, struct sk_psock *psock,
>  	sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
>  	ret = udp_msg_has_data(sk, psock);
>  	if (!ret) {
> +		release_sock(sk);
>  		wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
> +		lock_sock(sk);
>  		ret = udp_msg_has_data(sk, psock);

[Severity: High]
This is a pre-existing issue, but does this miss checking for socket shutdown
after waking up?

If the socket is shut down (RCV_SHUTDOWN) while the thread is sleeping in
wait_woken(), the thread wakes up and evaluates udp_msg_has_data(). If it
finds no data, it returns 0.

The caller udp_bpf_recvmsg() then sets copied = -EAGAIN and returns it to
userspace. Does this violate POSIX semantics, which require a blocking
recvmsg() to return 0 (EOF) immediately on a gracefully closed socket?

[Severity: High]
This is also a pre-existing issue, but is there a missing check for
signal_pending(current) here?

If wait_woken() is interrupted by a signal, it returns early. Since
udp_msg_wait_data() fails to check for signals after the wait, it will
return 0 if no data has arrived.

In udp_bpf_recvmsg(), this 0 is unconditionally translated to -EAGAIN.
Should this instead return -EINTR / -ERESTARTSYS when interrupted by a
signal? Returning -EAGAIN on a blocking socket can cause applications
to fail or spin indefinitely.

>  	}
>  	sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);

[ ... ]

>  	if (!psock_has_data(psock)) {
>  		ret = sk_udp_recvmsg(sk, msg, len, flags);
>  		goto out;
>  	}

[Severity: High]
This is a pre-existing issue, but does delegating to sk_udp_recvmsg() here
ignore data that might arrive via BPF redirect?

If the socket currently has no data (!psock_has_data(psock)), the fast path
drops into sk_udp_recvmsg(). If the socket is blocking, sk_udp_recvmsg()
will block waiting for data in sk->sk_receive_queue.

If a BPF program subsequently redirects a packet to this socket's psock, the
wait queue is woken up, but sk_udp_recvmsg() only checks
sk->sk_receive_queue. Finding it empty, it will go back to sleep
indefinitely. Can this result in a permanent hang?

>  
> +	lock_sock(sk);
>  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);

[Severity: High]
This is a pre-existing issue, but does this reset the receive timeout on
every loop iteration?

Inside the loop, sock_rcvtimeo() is called to fetch the timeout value.
udp_msg_wait_data() uses this timeout, but drops the remaining time when it
returns.

On the next iteration (for example, due to a spurious wakeup),
sock_rcvtimeo() is called again, reloading the full original timeout from
the socket. Doesn't this break SO_RCVTIMEO semantics by allowing the socket
to block indefinitely if wakeups keep occurring?

>  		data = udp_msg_wait_data(sk, psock, timeo);
>  		if (data) {
>  			if (psock_has_data(psock))
>  				goto msg_bytes_ready;

[Severity: Critical]
Does this loop introduce a hard lockup if data is pending in the
ingress_skb queue but not yet in ingress_msg?

If data is queued in psock->ingress_skb but not yet processed into
psock->ingress_msg, psock_has_data() returns true, but sk_msg_recvmsg()
returns 0.

The code then calls udp_msg_wait_data():

static int udp_msg_wait_data(...)
{
    ...
    ret = udp_msg_has_data(sk, psock);
    if (!ret) {
        release_sock(sk);
        wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
        lock_sock(sk);
        ...
    }
    return ret;
}

Because udp_msg_has_data() evaluates to true, udp_msg_wait_data() returns 1
immediately WITHOUT releasing lock_sock(sk).

Back in udp_bpf_recvmsg(), the code sees data is non-zero and
psock_has_data() is true, so it jumps to msg_bytes_ready. Because we still
hold lock_sock(sk), no other thread can process the ingress_skb, and
sk_msg_recvmsg() will again return 0.

Can this result in a 100% CPU tight spin loop while holding the socket
lock?

> +
> +			release_sock(sk);
> +
>  			ret = sk_udp_recvmsg(sk, msg, len, flags);
>  			goto out;
>  		}
>  		copied = -EAGAIN;
>  	}
> +
> +	release_sock(sk);
> +
>  	ret = copied;
>  out:
>  	sk_psock_put(sk, psock);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260612130919.299124-1-jiayuan.chen@linux.dev?part=5

  reply	other threads:[~2026-06-12 13:24 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-12 13:07 [PATCH bpf-next v3 0/7] bpf, skmsg: some fixes for skmsg Jiayuan Chen
2026-06-12 13:07 ` [PATCH bpf-next v3 1/7] bpf, sockmap: reject overflowing copy + len in bpf_msg_push_data() Jiayuan Chen
2026-06-12 13:28   ` sashiko-bot
2026-06-13  0:09   ` Kuniyuki Iwashima
2026-06-12 13:07 ` [PATCH bpf-next v3 2/7] bpf, sockmap: Fix wrong rsge offset " Jiayuan Chen
2026-06-12 13:27   ` sashiko-bot
2026-06-13  0:17   ` Kuniyuki Iwashima
2026-06-12 13:07 ` [PATCH bpf-next v3 3/7] bpf, sockmap: zero-initialize pages allocated in bpf_msg_push_data Jiayuan Chen
2026-06-12 13:34   ` sashiko-bot
2026-06-13  0:28   ` Kuniyuki Iwashima
2026-06-13  1:36     ` Alexei Starovoitov
2026-06-12 13:07 ` [PATCH bpf-next v3 4/7] bpf, sockmap: keep sk_msg copy state in sync Jiayuan Chen
2026-06-12 13:57   ` bot+bpf-ci
2026-06-13  0:40   ` Kuniyuki Iwashima
2026-06-12 13:07 ` [PATCH bpf-next v3 5/7] sockmap: Fix use-after-free in udp_bpf_recvmsg() Jiayuan Chen
2026-06-12 13:24   ` sashiko-bot [this message]
2026-06-12 13:07 ` [PATCH bpf-next v3 6/7] bpf, sockmap: fix integer overflow in bpf_msg_pop_data() bounds check Jiayuan Chen
2026-06-13  0:44   ` Kuniyuki Iwashima
2026-06-12 13:07 ` [PATCH bpf-next v3 7/7] selftests/bpf: add test for bpf_msg_pop_data() overflow Jiayuan Chen
2026-06-12 17:09 ` [PATCH bpf-next v3 0/7] bpf, skmsg: some fixes for skmsg Alexei Starovoitov
2026-06-12 18:43   ` Kuniyuki Iwashima

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=20260612132454.F14321F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=jiayuan.chen@linux.dev \
    --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