From: Jiayuan Chen <jiayuan.chen@linux.dev>
To: Eric Dumazet <edumazet@kernel.org>,
"David S . Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Kuniyuki Iwashima <kuniyu@google.com>,
Willem de Bruijn <willemb@google.com>
Cc: Simon Horman <horms@kernel.org>,
netdev@vger.kernel.org, Kyle Zeng <kylebot@openai.com>
Subject: Re: [PATCH v2 net] tcp: do not resurrect a former listener with SO_ATTACH_REUSEPORT_[CE]BPF
Date: Fri, 6 Nov 2026 18:57:42 +0800 [thread overview]
Message-ID: <24287f78-a962-470f-99eb-2624d8ac3bad@linux.dev> (raw)
In-Reply-To: <20261106084300.2029567-1-edumazet@kernel.org>
On 11/6/26 4:42 PM, Eric Dumazet wrote:
> After listen() + shutdown(), a TCP socket is moved to the closed
> section of its reuseport group, while TCP_NEW_SYN_RECV requests
> can still reference it as rsk_listener.
>
> If SO_ATTACH_REUSEPORT_[CE]BPF is then used on this socket,
> reuseport_attach_prog() calls reuseport_alloc(), which resurrects
> it into the listening section of a new group, even though the
> socket is still in TCP_CLOSE.
>
> After close(), the socket stays in that group and the pending
> requests keep it allocated. When the final ACK arrives,
> reuseport_migrate_sock() can select this dead socket and
> inet_csk_clone_lock() clones it. With a ULP like espintcp installed
> while in TCP_CLOSE, the child inherits icsk_ulp_data and sk_destruct
> after tcp_cleanup_ulp() cleared icsk_ulp_ops, leading to a
> use-after-free in espintcp_destruct().
>
> As done in commit 8cc3aef0cb19 ("tcp: Do not allow buggy transitions
> between ehash and lhash2."), deny this transition instead of adding
> checks to the fast path.
>
> Only an unhashed former listener is affected. Applications can still
> attach a reuseport prog to a socket that never listened, or to a
> listener (including one that called listen() again after shutdown()).
>
> Fixes: 333bb73f620e ("tcp: Keep TCP_CLOSE sockets in the reuseport group.")
> Reported-by: Kyle Zeng <kylebot@openai.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
> Signed-off-by: Eric Dumazet <edumazet@kernel.org>
> Cc: Jiayuan Chen <jiayuan.chen@linux.dev>
> ---
> v2: use sk_is_tcp() instead of checking sk_protocol, as raw sockets
> can have sk_protocol == IPPROTO_TCP (Jiayuan Chen, Sashiko)
> Add discovery, validation and testing info to the changelog (netdev-bot)
> v1: https://lore.kernel.org/netdev/20261105164830.1682714-1-edumazet@kernel.org/
>
> This was reported by OpenAI Security Research. The report does not
> state the discovery method, it was likely found by an AI-assisted scan.
>
> Validated with the reporter's PoC on a KASAN kernel: run as an
> unprivileged user in its own user and network namespaces, it triggers
> a slab-use-after-free in espintcp_destruct(). No kernel modification
> or error injection is needed. With this patch, SO_ATTACH_REUSEPORT_CBPF
> fails with -EINVAL and no splat is seen.
>
> The following selftests pass: net/reuseport_bpf, reuseport_bpf_cpu,
> reuseport_bpf_numa, reuseport_dualstack, reuseport_addr_any.sh,
> stress_reuseport_listen.sh, and bpf test_progs migrate_reuseport and
> select_reuseport.
>
> net/core/sock_reuseport.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
> index fccbdd0430b05984e82c19b17b6b723b0a3a03a1..b9e5648fa4c515a578fffd375c5214b3d5de6645 100644
> --- a/net/core/sock_reuseport.c
> +++ b/net/core/sock_reuseport.c
> @@ -6,6 +6,7 @@
> * selecting the socket index from the array of available sockets.
> */
>
> +#include <net/inet_connection_sock.h>
> #include <net/ip.h>
> #include <net/sock_reuseport.h>
> #include <linux/bpf.h>
> @@ -692,6 +693,14 @@ int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog)
> if (!sk->sk_reuseport)
> return -EINVAL;
>
> + /* Do not put a shutdown()ed TCP listener back into the
> + * listening section of a reuseport group while it is in
> + * TCP_CLOSE: requests can still migrate to it.
> + */
> + if (sk_is_tcp(sk) &&
> + inet_csk(sk)->unhashed_state == TCP_LISTEN)
> + return -EINVAL;
> +
> err = reuseport_alloc(sk, false);
> if (err)
> return err;
next prev parent reply other threads:[~2026-11-06 10:57 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-06 8:42 [PATCH v2 net] tcp: do not resurrect a former listener with SO_ATTACH_REUSEPORT_[CE]BPF Eric Dumazet
2026-11-06 10:57 ` Jiayuan Chen [this message]
2026-11-10 6:24 ` Kuniyuki Iwashima
2026-11-11 0:50 ` patchwork-bot+netdevbpf
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=24287f78-a962-470f-99eb-2624d8ac3bad@linux.dev \
--to=jiayuan.chen@linux.dev \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=kylebot@openai.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=willemb@google.com \
/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.