mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net] net: reuseport: avoid duplicate closed socket insertion
@ 2026-11-06 13:58 Lin Jiapeng
  2026-11-06 14:01 ` netdev-bot+sinfo
  2026-11-07  5:02 ` Jiayuan Chen
  0 siblings, 2 replies; 5+ messages in thread
From: Lin Jiapeng @ 2026-11-06 13:58 UTC (permalink / raw)
  To: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
	David S. Miller, Jakub Kicinski, Simon Horman, Martin KaFai Lau,
	Daniel Borkmann, netdev, linux-kernel
  Cc: Lin Jiapeng, TencentOS Corvus AI, stable, Lin Jiapeng

Clearing SO_REUSEPORT on a TCP listener clears sk_reuseport but leaves
sk_reuseport_cb attached to its reuseport group. A subsequent listen()
does not put the socket back into the listening section because
inet_hash() checks sk_reuseport. However, inet_unhash() checks
sk_reuseport_cb and calls reuseport_stop_listen_sock().

With request migration enabled, reuseport_stop_listen_sock() ignores
whether __reuseport_detach_sock() actually removed the socket from the
listening section and unconditionally appends it to the closed section.
Repeated connect(AF_UNSPEC)/listen() cycles therefore insert the same
socket until num_closed_socks exceeds max_socks. The next insertion
writes before socks[], overlapping prog on x86-64 and leading to type
confusion when a reuseport program is attached or detached.

Only insert the socket into the closed section when it was actually
removed from the listening section. A socket that was not rehashed as a
listener is already represented in the closed section, so leaving it
there preserves request migration semantics and prevents duplicate
entries and the resulting negative array indices.

Fixes: 333bb73f620e1 ("tcp: Keep TCP_CLOSE sockets in the reuseport group.")
Reported-by: TencentOS Corvus AI <corvus@tencent.com>
Cc: stable@vger.kernel.org
Signed-off-by: Lin Jiapeng <jiapenglin@tencent.com>
---
 net/core/sock_reuseport.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
index fccbdd0430b0..775f446516c3 100644
--- a/net/core/sock_reuseport.c
+++ b/net/core/sock_reuseport.c
@@ -480,8 +480,8 @@ void reuseport_stop_listen_sock(struct sock *sk)
 			 */
 			bpf_sk_reuseport_detach(sk);
 
-			__reuseport_detach_sock(sk, reuse);
-			__reuseport_add_closed_sock(sk, reuse);
+			if (__reuseport_detach_sock(sk, reuse))
+				__reuseport_add_closed_sock(sk, reuse);
 
 			spin_unlock_bh(&reuseport_lock);
 			return;
-- 
2.55.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net] net: reuseport: avoid duplicate closed socket insertion
  2026-11-06 13:58 [PATCH net] net: reuseport: avoid duplicate closed socket insertion Lin Jiapeng
@ 2026-11-06 14:01 ` netdev-bot+sinfo
  2026-11-06 14:55   ` Lin Jiapeng
  2026-11-07  5:02 ` Jiayuan Chen
  1 sibling, 1 reply; 5+ messages in thread
From: netdev-bot+sinfo @ 2026-11-06 14:01 UTC (permalink / raw)
  To: Lin Jiapeng
  Cc: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
	David S. Miller, Jakub Kicinski, Simon Horman, Martin KaFai Lau,
	Daniel Borkmann, netdev, linux-kernel, TencentOS Corvus AI,
	stable, Lin Jiapeng

Hi!

This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:

 - Whether the issue was actually triggered, or is only theoretical
   (e.g. found by code inspection). If it was triggered please include
   the symptoms, like the stack trace or error messages.

Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.

The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net] net: reuseport: avoid duplicate closed socket insertion
  2026-11-06 14:01 ` netdev-bot+sinfo
@ 2026-11-06 14:55   ` Lin Jiapeng
  0 siblings, 0 replies; 5+ messages in thread
From: Lin Jiapeng @ 2026-11-06 14:55 UTC (permalink / raw)
  To: netdev-bot+sinfo
  Cc: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
	David S. Miller, Jakub Kicinski, Simon Horman, Martin KaFai Lau,
	Daniel Borkmann, netdev, linux-kernel, TencentOS Corvus AI,
	stable, Lin Jiapeng



On 2026-11-06 10:01 p.m., netdev-bot+sinfo@kernel.org wrote:
> Hi!
> 
> This is an automated message. This series looks like a fix, but its
> commit messages seem to be missing some information:
> 
>   - Whether the issue was actually triggered, or is only theoretical
>     (e.g. found by code inspection). If it was triggered please include
>     the symptoms, like the stack trace or error messages.
> 
> Please do not repost the series just to address the above. Instead,
> reply to this email with the missing information, so that reviewers
> can take it into account. If the series needs another revision for
> other reasons, please include the information in the commit messages
> then.
> 
> The evaluation is done by an LLM so it may be wrong, if you think
> that is the case please reply and explain.


The issue was actually triggered, not found by code inspection.

Reproducer outline (unprivileged, uid 65534, inside a fresh user + network
namespace with net.ipv4.tcp_migrate_req = 1):

   1. Create two TCP listeners in the same SO_REUSEPORT group (one is kept
      hashed as an anchor).
   2. setsockopt(SO_REUSEPORT, 0) on one listener: sk_reuseport is cleared
      but sk_reuseport_cb stays attached.
   3. Repeat connect(AF_UNSPEC) + listen() 129 times on that socket. Each
      disconnect goes through inet_unhash() -> reuseport_stop_listen_sock(),
      which re-inserts the same socket into the closed section until
      num_closed_socks exceeds max_socks.
   4. The 129th insertion writes socks[-1], which overlaps reuse->prog on
      x86_64. Attaching a classic BPF filter with SO_ATTACH_REUSEPORT_CBPF
      on the other socket then consumes the struct sock pointer stored in
      reuse->prog as a struct bpf_prog *.

Kernel: v7.4-rc1 based tree (d68ce4e71248), x86_64, CONFIG_KASAN=y,
CONFIG_UBSAN_BOUNDS=y, QEMU.

Symptoms, first the out-of-bounds write itself:

   UBSAN: array-index-out-of-bounds in net/core/sock_reuseport.c:152:9
   index -1 is out of range for type 'struct sock *[] 
__counted_by(max_socks)'
   CPU: 0 UID: 65534 PID: 22 Comm: poc
   Call Trace:
    __ubsan_handle_out_of_bounds+0x91/0xa0
    reuseport_stop_listen_sock+0x290/0x310
    inet_unhash+0xd5/0x400
    tcp_set_state+0x125/0x260
    tcp_disconnect+0x47/0x1950
    __inet_stream_connect+0x2d0/0xab0
    __x64_sys_connect+0x71/0x80

then, after SO_ATTACH_REUSEPORT_CBPF is issued on the second listener, the
corrupted prog pointer reaches the RCU free path as a struct sock *:

   Oops: general protection fault, probably for non-canonical address
   0xdffffc000000008e: 0000 [#1] KASAN
   KASAN: null-ptr-deref in range [0x0000000000000470-0x0000000000000477]
   RIP: 0010:call_rcu+0x10d/0x260
   Call Trace:
    ? reuseport_attach_prog+0x6c/0x140
    reuseport_attach_prog+0xdd/0x140
    sk_reuseport_attach_filter+0x97/0xf0
    sk_setsockopt+0x973/0x1cc0
    __x64_sys_setsockopt+0xac/0xc0

   followed by "Kernel panic - not syncing: Fatal exception".

With the proposed fix applied, the same reproducer completes cleanly: no
UBSAN report, no oops, the SO_ATTACH_REUSEPORT_CBPF call and socket
teardown all succeed, PoC exits 0.

I can share the reproducer program if that is useful.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net] net: reuseport: avoid duplicate closed socket insertion
  2026-11-06 13:58 [PATCH net] net: reuseport: avoid duplicate closed socket insertion Lin Jiapeng
  2026-11-06 14:01 ` netdev-bot+sinfo
@ 2026-11-07  5:02 ` Jiayuan Chen
  2026-11-07  8:08   ` Lin Jiapeng
  1 sibling, 1 reply; 5+ messages in thread
From: Jiayuan Chen @ 2026-11-07  5:02 UTC (permalink / raw)
  To: Lin Jiapeng, Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni,
	Willem de Bruijn, David S. Miller, Jakub Kicinski, Simon Horman,
	Martin KaFai Lau, Daniel Borkmann, netdev, linux-kernel
  Cc: TencentOS Corvus AI, stable, Lin Jiapeng


On 11/6/26 9:58 PM, Lin Jiapeng wrote:
> Clearing SO_REUSEPORT on a TCP listener clears sk_reuseport but leaves
> sk_reuseport_cb attached to its reuseport group. A subsequent listen()
> does not put the socket back into the listening section because
> inet_hash() checks sk_reuseport. However, inet_unhash() checks
> sk_reuseport_cb and calls reuseport_stop_listen_sock().
>
> With request migration enabled, reuseport_stop_listen_sock() ignores
> whether __reuseport_detach_sock() actually removed the socket from the
> listening section and unconditionally appends it to the closed section.
> Repeated connect(AF_UNSPEC)/listen() cycles therefore insert the same
> socket until num_closed_socks exceeds max_socks. The next insertion
> writes before socks[], overlapping prog on x86-64 and leading to type
> confusion when a reuseport program is attached or detached.


Is the issue same as Eric's patch ?

https://lore.kernel.org/netdev/20261106084300.2029567-1-edumazet@kernel.org/


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net] net: reuseport: avoid duplicate closed socket insertion
  2026-11-07  5:02 ` Jiayuan Chen
@ 2026-11-07  8:08   ` Lin Jiapeng
  0 siblings, 0 replies; 5+ messages in thread
From: Lin Jiapeng @ 2026-11-07  8:08 UTC (permalink / raw)
  To: Jiayuan Chen, Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni,
	Willem de Bruijn, David S. Miller, Jakub Kicinski, Simon Horman,
	Martin KaFai Lau, Daniel Borkmann, netdev, linux-kernel
  Cc: TencentOS Corvus AI, stable, Lin Jiapeng


On 2026-11-07 1:02 p.m., Jiayuan Chen wrote:
> 
> On 11/6/26 9:58 PM, Lin Jiapeng wrote:
>> Clearing SO_REUSEPORT on a TCP listener clears sk_reuseport but leaves
>> sk_reuseport_cb attached to its reuseport group. 
>> ...
>> Repeated connect(AF_UNSPEC)/listen() cycles therefore insert the same
>> socket until num_closed_socks exceeds max_socks. The next insertion
>> writes before socks[], overlapping prog on x86-64 and leading to type
>> confusion when a reuseport program is attached or detached.
> 
> 
> Is the issue same as Eric's patch ?
> 
> https://lore.kernel.org/netdev/20261106084300.2029567-1-edumazet@kernel.org/

These reports may be related, but analysis suggests that they seem
to have different root causes.

Eric's patch seems to prevent attaching a program to the same unhashed,
shutdown listener from resurrecting it into the listening section. My
patch addresses duplicate closed-section insertion after SO_REUSEPORT
is cleared, which may eventually make socks[-1] overwrite reuse->prog.

Eric's patch does not change reuseport_stop_listen_sock(). Also, my PoC
attaches the program on a separate, still-hashed anchor socket, so his
new check may not apply to this path.

I tested Eric's v2 patch with my unmodified PoC. His positive control
returned EINVAL, so the patch seems to be active. However, my PoC still
triggered the same UBSAN/KASAN failure. Since his patch did not stop my
reproducer, and the root causes appear to be different, I think these
may not be the same issue. The two fixes may therefore be complementary.

The following is the UBSAN/KASAN output with Eric's v2 patch applied:

[trigger] cycle 129/129 (vulnerable: socks[-1] overwrites prog)
[trigger] attaching CBPF after closed-region pump
------------[ cut here ]------------
UBSAN: array-index-out-of-bounds in 
/Users/m00nb1rd/WorkSpace/vul-findings/reuseport-closed-region-negative-index-bpfprog-as-sock/repro-upstream/linux-eric-v2/net/core/sock_reuseport.c:153:9
index -1 is out of range for type 'struct sock *[] 
__counted_by(max_socks)' (aka 'struct sock *[]')
CPU: 0 UID: 65534 PID: 22 Comm: poc Not tainted 7.4.0-rc1+ #1 PREEMPTLAZY
Call Trace:
  <TASK>
  dump_stack_lvl+0x23/0x30
  ubsan_epilogue+0x5/0x30
  __ubsan_handle_out_of_bounds+0x91/0xa0
  reuseport_stop_listen_sock+0x290/0x310
  ? reuseport_stop_listen_sock+0x43/0x310
  inet_unhash+0xd5/0x400
  tcp_set_state+0x125/0x260
  tcp_disconnect+0x47/0x1950
  __inet_stream_connect+0x2d0/0xab0
  ? do_iter_readv_writev+0x25b/0x350
  ? vfs_writev+0x2e0/0x3c0
  inet_stream_connect+0x57/0x90
  __sys_connect+0x14b/0x1a0
  __x64_sys_connect+0x71/0x80
  do_syscall_64+0x6c/0x1d0
  entry_SYSCALL_64_after_hwframe+0x4b/0x53
RIP: 0033:0x205560
...
...
  </TASK>
---[ end trace ]---
Oops: general protection fault, probably for non-canonical address 
0xdffffc000000008e: 0000 [#1] KASAN
KASAN: null-ptr-deref in range [0x0000000000000470-0x0000000000000477]
CPU: 0 UID: 65534 PID: 22 Comm: poc Not tainted 7.4.0-rc1+ #1 PREEMPTLAZY
RIP: 0010:call_rcu+0x10d/0x260
...
Call Trace:
  <TASK>
  ? reuseport_attach_prog+0x6c/0x250
  reuseport_attach_prog+0xdd/0x250
  sk_reuseport_attach_filter+0x97/0xf0
  sk_setsockopt+0x973/0x1cc0
  do_sock_setsockopt+0xa9/0x120
  __sys_setsockopt+0xaa/0xe0
  __x64_sys_setsockopt+0xac/0xc0
  do_syscall_64+0x6c/0x1d0
  entry_SYSCALL_64_after_hwframe+0x4b/0x53
RIP: 0033:0x202f22
...
  </TASK>
---[ end trace 0000000000000000 ]---


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-11-07  8:08 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-06 13:58 [PATCH net] net: reuseport: avoid duplicate closed socket insertion Lin Jiapeng
2026-11-06 14:01 ` netdev-bot+sinfo
2026-11-06 14:55   ` Lin Jiapeng
2026-11-07  5:02 ` Jiayuan Chen
2026-11-07  8:08   ` Lin Jiapeng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®