AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/08/24 04:37 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": [
    "IPV6"
  ],
  "FocusSymbols": [
    "tcp_rcv_listen_state_process",
    "do_ipv6_setsockopt"
  ],
  "KMSANReasoning": "The patch implements lockless TCP listener processing and fixes several issues related to socket cloning and state inheritance (e.g., resetting `sk_tsq_flags`, `packets_out`, and `pinet6` in cloned sockets). \n\n1. The fields being explicitly zeroed or set to NULL in `sk_clone` and `tcp_create_openreq_child` do not represent uninitialized memory. They are already fully initialized via `sock_copy` (which copies the parent socket's state). The changes merely prevent the child socket from inheriting stale or incorrect values from the listener.\n2. The lockless listener processing (`tcp_v4_rcv_listen`) introduces concurrency changes. Any resulting bugs would be data races (caught by KCSAN) or use-after-free/memory corruption (caught by KASAN).\n3. The `IPV6_ADDRFORM` and `do_ipv6_setsockopt` changes address logic bugs and potential use-after-free scenarios, which are well within the domain of KASAN.\n\nThere are no new structures sent to user space, no new allocations left uninitialized, and no changes to bounds checking that would expose uninitialized memory. Thus, a dedicated KMSAN fuzzing session is not required.",
  "NeedsKMSAN": false,
  "Reasoning": "The patch modifies TCP listening socket packet processing by introducing `tcp_rcv_listen_state_process` and lockless listen receive paths (`tcp_v4_rcv_listen`, `tcp_v6_rcv_listen`). It also adds checks in `do_ipv6_setsockopt` for `IPV6_ADDRFORM` on TCP sockets with pending connection requests. These are functional changes to the core TCP stack and IPv6 socket options, reachable from user space and network traffic, and should be fuzzed.",
  "WorthFuzzing": true
}

1/1 2026/08/24 04:37 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 8ce5d56c06f9686e398cea7789e515fbf31b5ad8\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Mon Aug 24 04:37:11 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/include/net/tcp.h b/include/net/tcp.h\nindex 2c5b889530b55..add438d6561be 100644\n--- a/include/net/tcp.h\n+++ b/include/net/tcp.h\n@@ -392,6 +392,8 @@ void tcp_write_timer_handler(struct sock *sk);\n void tcp_delack_timer_handler(struct sock *sk);\n int tcp_ioctl(struct sock *sk, int cmd, int *karg);\n enum skb_drop_reason tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb);\n+enum skb_drop_reason tcp_rcv_listen_state_process(struct sock *sk,\n+\t\t\t\t\t\t  struct sk_buff *skb);\n void tcp_rcv_established(struct sock *sk, struct sk_buff *skb);\n void tcp_rcvbuf_grow(struct sock *sk, u32 newval);\n void tcp_rcv_space_adjust(struct sock *sk);\ndiff --git a/net/core/sock.c b/net/core/sock.c\nindex 1ad41904db25b..06fbb19824e26 100644\n--- a/net/core/sock.c\n+++ b/net/core/sock.c\n@@ -2479,7 +2479,7 @@ static void sk_init_common(struct sock *sk)\n struct sock *sk_clone(const struct sock *sk, const gfp_t priority,\n \t\t      bool lock)\n {\n-\tstruct proto *prot = READ_ONCE(sk-\u003esk_prot);\n+\tstruct proto *prot = sk-\u003esk_prot_creator;\n \tstruct sk_filter *filter;\n \tbool is_charged = true;\n \tstruct sock *newsk;\n@@ -2533,6 +2533,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority,\n \tnewsk-\u003esk_reserved_mem  = 0;\n \tDEBUG_NET_WARN_ON_ONCE(newsk-\u003esk_drop_counters);\n \tsk_drops_reset(newsk);\n+\tnewsk-\u003esk_tsq_flags\t= 0;\n \tnewsk-\u003esk_send_head\t= NULL;\n \tnewsk-\u003esk_userlocks\t= sk-\u003esk_userlocks \u0026 ~SOCK_BINDPORT_LOCK;\n \tatomic_set(\u0026newsk-\u003esk_zckey, 0);\ndiff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c\nindex 0f60a1dbf9274..77af18fba66b4 100644\n--- a/net/ipv4/tcp_input.c\n+++ b/net/ipv4/tcp_input.c\n@@ -7141,6 +7141,42 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk)\n \ttcp_rearm_rto(sk);\n }\n \n+enum skb_drop_reason tcp_rcv_listen_state_process(struct sock *sk,\n+\t\t\t\t\t\t  struct sk_buff *skb)\n+{\n+\tconst struct tcphdr *th = tcp_hdr(skb);\n+\tSKB_DR(reason);\n+\n+\tif (th-\u003eack)\n+\t\treturn SKB_DROP_REASON_TCP_FLAGS;\n+\n+\tif (th-\u003erst) {\n+\t\tSKB_DR_SET(reason, TCP_RESET);\n+\t\tgoto discard;\n+\t}\n+\tif (th-\u003esyn) {\n+\t\tif (th-\u003efin) {\n+\t\t\tSKB_DR_SET(reason, TCP_FLAGS);\n+\t\t\tgoto discard;\n+\t\t}\n+\t\t/* It is possible that we process SYN packets from backlog,\n+\t\t * so we need to make sure to disable BH and RCU right there.\n+\t\t */\n+\t\trcu_read_lock();\n+\t\tlocal_bh_disable();\n+\t\tinet_csk(sk)-\u003eicsk_af_ops-\u003econn_request(sk, skb);\n+\t\tlocal_bh_enable();\n+\t\trcu_read_unlock();\n+\n+\t\tconsume_skb(skb);\n+\t\treturn 0;\n+\t}\n+\tSKB_DR_SET(reason, TCP_FLAGS);\n+discard:\n+\ttcp_drop_reason(sk, skb, reason);\n+\treturn 0;\n+}\n+\n /*\n  *\tThis function implements the receiving procedure of RFC 793 for\n  *\tall states except ESTABLISHED and TIME_WAIT.\n@@ -7152,7 +7188,6 @@ enum skb_drop_reason\n tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)\n {\n \tstruct tcp_sock *tp = tcp_sk(sk);\n-\tstruct inet_connection_sock *icsk = inet_csk(sk);\n \tconst struct tcphdr *th = tcp_hdr(skb);\n \tstruct request_sock *req;\n \tint queued = 0;\n@@ -7164,32 +7199,7 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)\n \t\tgoto discard;\n \n \tcase TCP_LISTEN:\n-\t\tif (th-\u003eack)\n-\t\t\treturn SKB_DROP_REASON_TCP_FLAGS;\n-\n-\t\tif (th-\u003erst) {\n-\t\t\tSKB_DR_SET(reason, TCP_RESET);\n-\t\t\tgoto discard;\n-\t\t}\n-\t\tif (th-\u003esyn) {\n-\t\t\tif (th-\u003efin) {\n-\t\t\t\tSKB_DR_SET(reason, TCP_FLAGS);\n-\t\t\t\tgoto discard;\n-\t\t\t}\n-\t\t\t/* It is possible that we process SYN packets from backlog,\n-\t\t\t * so we need to make sure to disable BH and RCU right there.\n-\t\t\t */\n-\t\t\trcu_read_lock();\n-\t\t\tlocal_bh_disable();\n-\t\t\ticsk-\u003eicsk_af_ops-\u003econn_request(sk, skb);\n-\t\t\tlocal_bh_enable();\n-\t\t\trcu_read_unlock();\n-\n-\t\t\tconsume_skb(skb);\n-\t\t\treturn 0;\n-\t\t}\n-\t\tSKB_DR_SET(reason, TCP_FLAGS);\n-\t\tgoto discard;\n+\t\treturn tcp_rcv_listen_state_process(sk, skb);\n \n \tcase TCP_SYN_SENT:\n \t\ttp-\u003erx_opt.saw_tstamp = 0;\ndiff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c\nindex 190c7af4cf923..2fa8958380a5b 100644\n--- a/net/ipv4/tcp_ipv4.c\n+++ b/net/ipv4/tcp_ipv4.c\n@@ -1714,6 +1714,14 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,\n \t\tinet_csk(newsk)-\u003eicsk_ext_hdr_len = inet_opt-\u003eopt.optlen;\n \tatomic_set(\u0026newinet-\u003einet_id, get_random_u16());\n \n+#if IS_ENABLED(CONFIG_IPV6)\n+\t/* Never inherit the listener's ipv6_pinfo; IPV6_ADDRFORM leaves it set\n+\t * on an AF_INET socket.  tcp_v6_mapped_child_init() installs our own.\n+\t */\n+\tnewinet-\u003epinet6 = NULL;\n+\tnewinet-\u003eipv6_fl_list = NULL;\n+#endif\n+\n \t/* Set ToS of the new socket based upon the value of incoming SYN.\n \t * ECT bits are set later in tcp_init_transfer().\n \t */\n@@ -1820,7 +1828,7 @@ u16 tcp_v4_get_syncookie(struct sock *sk, struct iphdr *iph,\n INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,\n \t\t\t\t\t\t\t   u32));\n /* The socket must have it's spinlock held when we get\n- * here, unless it is a TCP_LISTEN socket.\n+ * here.\n  *\n  * We have a potential double-lock case here, so even when\n  * doing backlog processing we use the BH locking scheme.\n@@ -1898,6 +1906,46 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)\n \tgoto discard;\n }\n \n+/* @sk is not locked here and can leave TCP_LISTEN; do not test sk_state. */\n+static noinline int tcp_v4_rcv_listen(struct sock *sk, struct sk_buff *skb)\n+{\n+\tenum skb_drop_reason reason;\n+\tstruct sock *nsk;\n+\n+\treason = psp_sk_rx_policy_check(sk, skb);\n+\tif (reason)\n+\t\tgoto err_discard;\n+\n+\tif (tcp_checksum_complete(skb))\n+\t\tgoto csum_err;\n+\n+\tnsk = tcp_v4_cookie_check(sk, skb);\n+\tif (!nsk)\n+\t\treturn 0;\n+\n+\tif (nsk != sk) {\n+\t\treason = tcp_child_process(sk, nsk, skb);\n+\t\tsock_put(nsk);\n+\t} else {\n+\t\treason = tcp_rcv_listen_state_process(sk, skb);\n+\t}\n+\tif (!reason)\n+\t\treturn 0;\n+\n+\ttcp_v4_send_reset(sk, skb, sk_rst_convert_drop_reason(reason));\n+discard:\n+\tsk_skb_reason_drop(sk, skb, reason);\n+\treturn 0;\n+\n+csum_err:\n+\treason = SKB_DROP_REASON_TCP_CSUM;\n+\ttrace_tcp_bad_csum(skb);\n+\tTCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);\n+err_discard:\n+\tTCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);\n+\tgoto discard;\n+}\n+\n enum skb_drop_reason tcp_add_backlog(struct sock *sk, struct sk_buff *skb)\n {\n \tu32 tail_gso_size, tail_gso_segs;\n@@ -2235,7 +2283,7 @@ int tcp_v4_rcv(struct sk_buff *skb)\n \tskb-\u003edev = NULL;\n \n \tif (sk-\u003esk_state == TCP_LISTEN) {\n-\t\tret = tcp_v4_do_rcv(sk, skb);\n+\t\tret = tcp_v4_rcv_listen(sk, skb);\n \t\tgoto put_and_return;\n \t}\n \ndiff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c\nindex 12254e6eb2f34..2fde196dd302f 100644\n--- a/net/ipv4/tcp_minisocks.c\n+++ b/net/ipv4/tcp_minisocks.c\n@@ -591,6 +591,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,\n \tnewtp-\u003etotal_retrans = req-\u003enum_retrans;\n \n \ttcp_init_xmit_timers(newsk);\n+\tnewtp-\u003eout_of_order_queue = RB_ROOT;\n \tWRITE_ONCE(newtp-\u003ewrite_seq, newtp-\u003epushed_seq = treq-\u003esnt_isn + 1);\n \n \tif (sock_flag(newsk, SOCK_KEEPOPEN))\n@@ -659,6 +660,12 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,\n \ttcp_ecn_openreq_child(newsk, req, skb);\n \tnewtp-\u003efastopen_req = NULL;\n \tRCU_INIT_POINTER(newtp-\u003efastopen_rsk, NULL);\n+\tnewtp-\u003epackets_out = 0;\n+\tnewtp-\u003eretrans_out = 0;\n+\tnewtp-\u003esacked_out = 0;\n+\tnewtp-\u003elost_out = 0;\n+\tnewtp-\u003eretransmit_skb_hint = NULL;\n+\tnewtp-\u003ehighest_sack = NULL;\n \n \tnewtp-\u003ebpf_chg_cc_inprogress = 0;\n \ttcp_bpf_clone(sk, newsk);\n@@ -974,7 +981,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,\n \t\ttcp_reset(sk, skb);\n \t}\n \tif (!fastopen) {\n-\t\tbool unlinked = inet_csk_reqsk_queue_drop(sk, req);\n+\t\tbool unlinked = inet_csk_reqsk_queue_drop(req-\u003ersk_listener, req);\n \n \t\tif (unlinked)\n \t\t\t__NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);\ndiff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c\nindex 282912a119999..68b330f6941d0 100644\n--- a/net/ipv6/af_inet6.c\n+++ b/net/ipv6/af_inet6.c\n@@ -479,6 +479,10 @@ void inet6_cleanup_sock(struct sock *sk)\n \tstruct sk_buff *skb;\n \tstruct ipv6_txoptions *opt;\n \n+\t/* AF_INET child of an IPV6_ADDRFORM'ed listener: nothing of its own. */\n+\tif (!np)\n+\t\treturn;\n+\n \t/* Release rx options */\n \n \tskb = xchg(\u0026np-\u003epktoptions, NULL);\ndiff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c\nindex b4c977434c2e0..6d2dd9ae46a96 100644\n--- a/net/ipv6/ipv6_sockglue.c\n+++ b/net/ipv6/ipv6_sockglue.c\n@@ -587,6 +587,21 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,\n \t\t\t\tbreak;\n \t\t\t}\n \n+\t\t\tif (sk-\u003esk_protocol == IPPROTO_TCP) {\n+\t\t\t\tif (inet_csk_reqsk_queue_len(sk)) {\n+\t\t\t\t\tretv = -EBUSY;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t\t/* A SYN that found this socket while it was\n+\t\t\t\t * still listening may not be counted yet.\n+\t\t\t\t */\n+\t\t\t\tsynchronize_rcu();\n+\t\t\t\tif (inet_csk_reqsk_queue_len(sk)) {\n+\t\t\t\t\tretv = -EBUSY;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\n \t\t\t__ipv6_sock_mc_close(sk);\n \t\t\t__ipv6_sock_ac_close(sk);\n \ndiff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c\nindex 9e9155b1b3aa7..a2deda9a4258b 100644\n--- a/net/ipv6/tcp_ipv6.c\n+++ b/net/ipv6/tcp_ipv6.c\n@@ -1556,7 +1556,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *\n INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,\n \t\t\t\t\t\t\t   u32));\n /* The socket must have it's spinlock held when we get\n- * here, unless it is a TCP_LISTEN socket.\n+ * here.\n  *\n  * We have a potential double-lock case here, so even when\n  * doing backlog processing we use the BH locking scheme.\n@@ -1704,6 +1704,46 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)\n \treturn 0;\n }\n \n+/* @sk is not locked here and can leave TCP_LISTEN; do not test sk_state. */\n+static noinline int tcp_v6_rcv_listen(struct sock *sk, struct sk_buff *skb)\n+{\n+\tenum skb_drop_reason reason;\n+\tstruct sock *nsk;\n+\n+\treason = psp_sk_rx_policy_check(sk, skb);\n+\tif (reason)\n+\t\tgoto err_discard;\n+\n+\tif (tcp_checksum_complete(skb))\n+\t\tgoto csum_err;\n+\n+\tnsk = tcp_v6_cookie_check(sk, skb);\n+\tif (!nsk)\n+\t\treturn 0;\n+\n+\tif (nsk != sk) {\n+\t\treason = tcp_child_process(sk, nsk, skb);\n+\t\tsock_put(nsk);\n+\t} else {\n+\t\treason = tcp_rcv_listen_state_process(sk, skb);\n+\t}\n+\tif (!reason)\n+\t\treturn 0;\n+\n+\ttcp_v6_send_reset(sk, skb, sk_rst_convert_drop_reason(reason));\n+discard:\n+\tsk_skb_reason_drop(sk, skb, reason);\n+\treturn 0;\n+\n+csum_err:\n+\treason = SKB_DROP_REASON_TCP_CSUM;\n+\ttrace_tcp_bad_csum(skb);\n+\tTCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);\n+err_discard:\n+\tTCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);\n+\tgoto discard;\n+}\n+\n static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr,\n \t\t\t   const struct tcphdr *th)\n {\n@@ -1891,7 +1931,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)\n \tskb-\u003edev = NULL;\n \n \tif (sk-\u003esk_state == TCP_LISTEN) {\n-\t\tret = tcp_v6_do_rcv(sk, skb);\n+\t\tret = tcp_v6_rcv_listen(sk, skb);\n \t\tgoto put_and_return;\n \t}\n \n"
}

2/1 2026/08/24 04:37 agent patch-evaluator
0m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": [
    "IPV6"
  ],
  "FocusSymbols": [
    "tcp_rcv_listen_state_process",
    "do_ipv6_setsockopt"
  ],
  "Reasoning": "The patch modifies TCP listening socket packet processing by introducing `tcp_rcv_listen_state_process` and lockless listen receive paths (`tcp_v4_rcv_listen`, `tcp_v6_rcv_listen`). It also adds checks in `do_ipv6_setsockopt` for `IPV6_ADDRFORM` on TCP sockets with pending connection requests. These are functional changes to the core TCP stack and IPv6 socket options, reachable from user space and network traffic, and should be fuzzed.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
  even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).
- Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed,
  ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU.
- Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove)
  that are executed only during PCI hot-unplug or sysfs driver unbind operations.

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
   Prefer non-static, non-inlined API entrypoint functions over internal static helper functions
   (which are inlined by the compiler and do not have distinct symbol addresses).
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs
   needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs
   output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 8ce5d56c06f9686e398cea7789e515fbf31b5ad8
Author: syz-cluster <triage@syzkaller.com>
Date:   Mon Aug 24 04:37:11 2026 +0000

    syz-cluster: applied patch under review

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 2c5b889530b55..add438d6561be 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -392,6 +392,8 @@ void tcp_write_timer_handler(struct sock *sk);
 void tcp_delack_timer_handler(struct sock *sk);
 int tcp_ioctl(struct sock *sk, int cmd, int *karg);
 enum skb_drop_reason tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb);
+enum skb_drop_reason tcp_rcv_listen_state_process(struct sock *sk,
+						  struct sk_buff *skb);
 void tcp_rcv_established(struct sock *sk, struct sk_buff *skb);
 void tcp_rcvbuf_grow(struct sock *sk, u32 newval);
 void tcp_rcv_space_adjust(struct sock *sk);
diff --git a/net/core/sock.c b/net/core/sock.c
index 1ad41904db25b..06fbb19824e26 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2479,7 +2479,7 @@ static void sk_init_common(struct sock *sk)
 struct sock *sk_clone(const struct sock *sk, const gfp_t priority,
 		      bool lock)
 {
-	struct proto *prot = READ_ONCE(sk->sk_prot);
+	struct proto *prot = sk->sk_prot_creator;
 	struct sk_filter *filter;
 	bool is_charged = true;
 	struct sock *newsk;
@@ -2533,6 +2533,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority,
 	newsk->sk_reserved_mem  = 0;
 	DEBUG_NET_WARN_ON_ONCE(newsk->sk_drop_counters);
 	sk_drops_reset(newsk);
+	newsk->sk_tsq_flags	= 0;
 	newsk->sk_send_head	= NULL;
 	newsk->sk_userlocks	= sk->sk_userlocks & ~SOCK_BINDPORT_LOCK;
 	atomic_set(&newsk->sk_zckey, 0);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 0f60a1dbf9274..77af18fba66b4 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -7141,6 +7141,42 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk)
 	tcp_rearm_rto(sk);
 }
 
+enum skb_drop_reason tcp_rcv_listen_state_process(struct sock *sk,
+						  struct sk_buff *skb)
+{
+	const struct tcphdr *th = tcp_hdr(skb);
+	SKB_DR(reason);
+
+	if (th->ack)
+		return SKB_DROP_REASON_TCP_FLAGS;
+
+	if (th->rst) {
+		SKB_DR_SET(reason, TCP_RESET);
+		goto discard;
+	}
+	if (th->syn) {
+		if (th->fin) {
+			SKB_DR_SET(reason, TCP_FLAGS);
+			goto discard;
+		}
+		/* It is possible that we process SYN packets from backlog,
+		 * so we need to make sure to disable BH and RCU right there.
+		 */
+		rcu_read_lock();
+		local_bh_disable();
+		inet_csk(sk)->icsk_af_ops->conn_request(sk, skb);
+		local_bh_enable();
+		rcu_read_unlock();
+
+		consume_skb(skb);
+		return 0;
+	}
+	SKB_DR_SET(reason, TCP_FLAGS);
+discard:
+	tcp_drop_reason(sk, skb, reason);
+	return 0;
+}
+
 /*
  *	This function implements the receiving procedure of RFC 793 for
  *	all states except ESTABLISHED and TIME_WAIT.
@@ -7152,7 +7188,6 @@ enum skb_drop_reason
 tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct inet_connection_sock *icsk = inet_csk(sk);
 	const struct tcphdr *th = tcp_hdr(skb);
 	struct request_sock *req;
 	int queued = 0;
@@ -7164,32 +7199,7 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
 		goto discard;
 
 	case TCP_LISTEN:
-		if (th->ack)
-			return SKB_DROP_REASON_TCP_FLAGS;
-
-		if (th->rst) {
-			SKB_DR_SET(reason, TCP_RESET);
-			goto discard;
-		}
-		if (th->syn) {
-			if (th->fin) {
-				SKB_DR_SET(reason, TCP_FLAGS);
-				goto discard;
-			}
-			/* It is possible that we process SYN packets from backlog,
-			 * so we need to make sure to disable BH and RCU right there.
-			 */
-			rcu_read_lock();
-			local_bh_disable();
-			icsk->icsk_af_ops->conn_request(sk, skb);
-			local_bh_enable();
-			rcu_read_unlock();
-
-			consume_skb(skb);
-			return 0;
-		}
-		SKB_DR_SET(reason, TCP_FLAGS);
-		goto discard;
+		return tcp_rcv_listen_state_process(sk, skb);
 
 	case TCP_SYN_SENT:
 		tp->rx_opt.saw_tstamp = 0;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 190c7af4cf923..2fa8958380a5b 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1714,6 +1714,14 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
 		inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
 	atomic_set(&newinet->inet_id, get_random_u16());
 
+#if IS_ENABLED(CONFIG_IPV6)
+	/* Never inherit the listener's ipv6_pinfo; IPV6_ADDRFORM leaves it set
+	 * on an AF_INET socket.  tcp_v6_mapped_child_init() installs our own.
+	 */
+	newinet->pinet6 = NULL;
+	newinet->ipv6_fl_list = NULL;
+#endif
+
 	/* Set ToS of the new socket based upon the value of incoming SYN.
 	 * ECT bits are set later in tcp_init_transfer().
 	 */
@@ -1820,7 +1828,7 @@ u16 tcp_v4_get_syncookie(struct sock *sk, struct iphdr *iph,
 INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
 							   u32));
 /* The socket must have it's spinlock held when we get
- * here, unless it is a TCP_LISTEN socket.
+ * here.
  *
  * We have a potential double-lock case here, so even when
  * doing backlog processing we use the BH locking scheme.
@@ -1898,6 +1906,46 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 	goto discard;
 }
 
+/* @sk is not locked here and can leave TCP_LISTEN; do not test sk_state. */
+static noinline int tcp_v4_rcv_listen(struct sock *sk, struct sk_buff *skb)
+{
+	enum skb_drop_reason reason;
+	struct sock *nsk;
+
+	reason = psp_sk_rx_policy_check(sk, skb);
+	if (reason)
+		goto err_discard;
+
+	if (tcp_checksum_complete(skb))
+		goto csum_err;
+
+	nsk = tcp_v4_cookie_check(sk, skb);
+	if (!nsk)
+		return 0;
+
+	if (nsk != sk) {
+		reason = tcp_child_process(sk, nsk, skb);
+		sock_put(nsk);
+	} else {
+		reason = tcp_rcv_listen_state_process(sk, skb);
+	}
+	if (!reason)
+		return 0;
+
+	tcp_v4_send_reset(sk, skb, sk_rst_convert_drop_reason(reason));
+discard:
+	sk_skb_reason_drop(sk, skb, reason);
+	return 0;
+
+csum_err:
+	reason = SKB_DROP_REASON_TCP_CSUM;
+	trace_tcp_bad_csum(skb);
+	TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
+err_discard:
+	TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
+	goto discard;
+}
+
 enum skb_drop_reason tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
 	u32 tail_gso_size, tail_gso_segs;
@@ -2235,7 +2283,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
 	skb->dev = NULL;
 
 	if (sk->sk_state == TCP_LISTEN) {
-		ret = tcp_v4_do_rcv(sk, skb);
+		ret = tcp_v4_rcv_listen(sk, skb);
 		goto put_and_return;
 	}
 
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 12254e6eb2f34..2fde196dd302f 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -591,6 +591,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
 	newtp->total_retrans = req->num_retrans;
 
 	tcp_init_xmit_timers(newsk);
+	newtp->out_of_order_queue = RB_ROOT;
 	WRITE_ONCE(newtp->write_seq, newtp->pushed_seq = treq->snt_isn + 1);
 
 	if (sock_flag(newsk, SOCK_KEEPOPEN))
@@ -659,6 +660,12 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
 	tcp_ecn_openreq_child(newsk, req, skb);
 	newtp->fastopen_req = NULL;
 	RCU_INIT_POINTER(newtp->fastopen_rsk, NULL);
+	newtp->packets_out = 0;
+	newtp->retrans_out = 0;
+	newtp->sacked_out = 0;
+	newtp->lost_out = 0;
+	newtp->retransmit_skb_hint = NULL;
+	newtp->highest_sack = NULL;
 
 	newtp->bpf_chg_cc_inprogress = 0;
 	tcp_bpf_clone(sk, newsk);
@@ -974,7 +981,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 		tcp_reset(sk, skb);
 	}
 	if (!fastopen) {
-		bool unlinked = inet_csk_reqsk_queue_drop(sk, req);
+		bool unlinked = inet_csk_reqsk_queue_drop(req->rsk_listener, req);
 
 		if (unlinked)
 			__NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 282912a119999..68b330f6941d0 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -479,6 +479,10 @@ void inet6_cleanup_sock(struct sock *sk)
 	struct sk_buff *skb;
 	struct ipv6_txoptions *opt;
 
+	/* AF_INET child of an IPV6_ADDRFORM'ed listener: nothing of its own. */
+	if (!np)
+		return;
+
 	/* Release rx options */
 
 	skb = xchg(&np->pktoptions, NULL);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index b4c977434c2e0..6d2dd9ae46a96 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -587,6 +587,21 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
 				break;
 			}
 
+			if (sk->sk_protocol == IPPROTO_TCP) {
+				if (inet_csk_reqsk_queue_len(sk)) {
+					retv = -EBUSY;
+					break;
+				}
+				/* A SYN that found this socket while it was
+				 * still listening may not be counted yet.
+				 */
+				synchronize_rcu();
+				if (inet_csk_reqsk_queue_len(sk)) {
+					retv = -EBUSY;
+					break;
+				}
+			}
+
 			__ipv6_sock_mc_close(sk);
 			__ipv6_sock_ac_close(sk);
 
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 9e9155b1b3aa7..a2deda9a4258b 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1556,7 +1556,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
 INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
 							   u32));
 /* The socket must have it's spinlock held when we get
- * here, unless it is a TCP_LISTEN socket.
+ * here.
  *
  * We have a potential double-lock case here, so even when
  * doing backlog processing we use the BH locking scheme.
@@ -1704,6 +1704,46 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
 	return 0;
 }
 
+/* @sk is not locked here and can leave TCP_LISTEN; do not test sk_state. */
+static noinline int tcp_v6_rcv_listen(struct sock *sk, struct sk_buff *skb)
+{
+	enum skb_drop_reason reason;
+	struct sock *nsk;
+
+	reason = psp_sk_rx_policy_check(sk, skb);
+	if (reason)
+		goto err_discard;
+
+	if (tcp_checksum_complete(skb))
+		goto csum_err;
+
+	nsk = tcp_v6_cookie_check(sk, skb);
+	if (!nsk)
+		return 0;
+
+	if (nsk != sk) {
+		reason = tcp_child_process(sk, nsk, skb);
+		sock_put(nsk);
+	} else {
+		reason = tcp_rcv_listen_state_process(sk, skb);
+	}
+	if (!reason)
+		return 0;
+
+	tcp_v6_send_reset(sk, skb, sk_rst_convert_drop_reason(reason));
+discard:
+	sk_skb_reason_drop(sk, skb, reason);
+	return 0;
+
+csum_err:
+	reason = SKB_DROP_REASON_TCP_CSUM;
+	trace_tcp_bad_csum(skb);
+	TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
+err_discard:
+	TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
+	goto discard;
+}
+
 static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr,
 			   const struct tcphdr *th)
 {
@@ -1891,7 +1931,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
 	skb->dev = NULL;
 
 	if (sk->sk_state == TCP_LISTEN) {
-		ret = tcp_v6_do_rcv(sk, skb);
+		ret = tcp_v6_rcv_listen(sk, skb);
 		goto put_and_return;
 	}
 

3/2 2026/08/24 04:37 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 6554
							output: 41
							thoughts: 825
						

Thoughts:
**My Analysis of This TCP Networking Patch**

Okay, so I've got a patch here that's making changes to the TCP networking code. My initial impression is that this is a significant functional change, and given that it's in the core networking stack and reachable via TCP sockets, fuzzing is definitely warranted. I'm going to start by identifying the key functions that are modified.

Specifically, I see a few key additions: `tcp_rcv_listen_state_process`, `tcp_v4_rcv_listen`, and `tcp_v6_rcv_listen`.  These are clearly introduced to handle the `TCP_LISTEN` state, which is worth investigating. The `sk_clone` function also gets a tweak to how it accesses the protocol creator.  We've got some new initialization in `tcp_create_openreq_child`. And then there's a modification to `do_ipv6_setsockopt`.

Now, let me zoom in on those functions to narrow down my focus.  I want to prioritize the best entry points. I know I should focus on non-static, non-inlined API entrypoints over internal static helper functions. I can see that `tcp_rcv_listen_state_process` is not static and is defined, which makes it a good candidate. However, `tcp_v4_rcv_listen` and `tcp_v6_rcv_listen` are static but *noinline*, so even though they are static, they will still have distinct symbol addresses which means that they are also candidates. Of course, `tcp_v4_rcv` and `tcp_v6_rcv` are the actual entry points, but those are in the kernel already so they are not new.  And finally, there's `do_ipv6_setsockopt` which is also modified.

Let's drill down into `do_ipv6_setsockopt`.  The diff shows that it's now checking for `IPPROTO_TCP` and the length of the request queue (`inet_csk_reqsk_queue_len(sk)`).  It looks like it's trying to prevent modification of options on a listening socket that has pending requests. Specifically it's trying to ensure that a SYN packet that arrived before the socket was fully listening is not missed.
I'll keep `do_ipv6_setsockopt` in mind, and I need to figure out what option is being affected.



4/2 2026/08/24 04:37 tool grepper
0m Args:
{
  "Expression": "__ipv6_sock_mc_close",
  "PathPrefix": "net/ipv6/ipv6_sockglue.c"
}

Results:
{
  "Output": "net/ipv6/ipv6_sockglue.c=376=int do_ipv6_setsockopt(struct sock *sk, int level, int optname,\n--\nnet/ipv6/ipv6_sockglue.c-604-\nnet/ipv6/ipv6_sockglue.c:605:\t\t\t__ipv6_sock_mc_close(sk);\nnet/ipv6/ipv6_sockglue.c-606-\t\t\t__ipv6_sock_ac_close(sk);\n"
}

5/2 2026/08/24 04:37 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8085
							output: 40
							thoughts: 27
						

Thoughts:
Here's a summary of my thought process, as if I were analyzing that specific code:

**Diving into ipv6_sockglue.c - Line 587**

Okay, I'm zeroing in on line 587 within `net/ipv6/ipv6_sockglue.c`. My initial thought is to recall what functions typically surround this area in the file. I immediately start mentally parsing the code flow. Since this file deals with the glue code between IPv6 and the socket layer, I'm expecting to find aspects related to the connection of IPv6 sockets and any supporting functions. I know this file is critical for managing IPv6 sockets and interfacing them with the generic socket layer. I need to understand the function call or code block on line 587 to determine what the specific context is. Is it dealing with address family handling? Socket option processing? Possibly related to multicast joins or leaves? Maybe it handles the actual socket creation or teardown. Knowing this file and area, I expect to deal with a `struct sock` or `struct inet6_sock` at some point. I’m preparing myself for that, mentally looking for hints. Let's see...



6/2 2026/08/24 04:37 tool read-file
0m Args:
{
  "File": "net/ipv6/ipv6_sockglue.c",
  "FirstLine": 570,
  "LineCount": 40
}

Results:
{
  "Contents": " 570:\t\t\t\t} else if (sk-\u003esk_protocol == IPPROTO_TCP) {\n 571:\t\t\t\t\tif (sk-\u003esk_prot != \u0026tcpv6_prot) {\n 572:\t\t\t\t\t\tretv = -EBUSY;\n 573:\t\t\t\t\t\tbreak;\n 574:\t\t\t\t\t}\n 575:\t\t\t\t} else {\n 576:\t\t\t\t\tbreak;\n 577:\t\t\t\t}\n 578:\t\n 579:\t\t\t\tif (sk-\u003esk_state != TCP_ESTABLISHED) {\n 580:\t\t\t\t\tretv = -ENOTCONN;\n 581:\t\t\t\t\tbreak;\n 582:\t\t\t\t}\n 583:\t\n 584:\t\t\t\tif (ipv6_only_sock(sk) ||\n 585:\t\t\t\t    !ipv6_addr_v4mapped(\u0026sk-\u003esk_v6_daddr)) {\n 586:\t\t\t\t\tretv = -EADDRNOTAVAIL;\n 587:\t\t\t\t\tbreak;\n 588:\t\t\t\t}\n 589:\t\n 590:\t\t\t\tif (sk-\u003esk_protocol == IPPROTO_TCP) {\n 591:\t\t\t\t\tif (inet_csk_reqsk_queue_len(sk)) {\n 592:\t\t\t\t\t\tretv = -EBUSY;\n 593:\t\t\t\t\t\tbreak;\n 594:\t\t\t\t\t}\n 595:\t\t\t\t\t/* A SYN that found this socket while it was\n 596:\t\t\t\t\t * still listening may not be counted yet.\n 597:\t\t\t\t\t */\n 598:\t\t\t\t\tsynchronize_rcu();\n 599:\t\t\t\t\tif (inet_csk_reqsk_queue_len(sk)) {\n 600:\t\t\t\t\t\tretv = -EBUSY;\n 601:\t\t\t\t\t\tbreak;\n 602:\t\t\t\t\t}\n 603:\t\t\t\t}\n 604:\t\n 605:\t\t\t\t__ipv6_sock_mc_close(sk);\n 606:\t\t\t\t__ipv6_sock_ac_close(sk);\n 607:\t\n 608:\t\t\t\tif (sk-\u003esk_protocol == IPPROTO_TCP) {\n 609:\t\t\t\t\tstruct inet_connection_sock *icsk = inet_csk(sk);\n"
}

7/2 2026/08/24 04:37 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8969
							output: 40
							thoughts: 9
						

Thoughts:
Okay, I'm ready to summarize the provided text in the first person, assuming a high level of expertise in the field. Here's how I'll approach it:

**My Initial Assessment**

Alright, let's take a look at the input. My immediate thought is, I need to understand what this "option" refers to, because the rest of the thought process hinges on clarifying that variable. I'll need to parse the context to understand the scope and relevance of the "option". It could be a hypothesis, a variable parameter within an equation, a decision point in an experiment, or even a prospective solution to a problem. The degree of the complexity varies by the context. I will work with the context to determine the best approach.



8/2 2026/08/24 04:37 tool read-file
0m Args:
{
  "File": "net/ipv6/ipv6_sockglue.c",
  "FirstLine": 540,
  "LineCount": 40
}

Results:
{
  "Contents": " 540:\t\t\tif (READ_ONCE(sk-\u003esk_bound_dev_if))\n 541:\t\t\t\treturn -EINVAL;\n 542:\t\n 543:\t\t\tWRITE_ONCE(np-\u003eucast_oif, ifindex);\n 544:\t\t\treturn 0;\n 545:\t\t}\n 546:\t\t}\n 547:\t\n 548:\t\tsockopt_lock_sock(sk);\n 549:\t\n 550:\t\t/* Another thread has converted the socket into IPv4 with\n 551:\t\t * IPV6_ADDRFORM concurrently.\n 552:\t\t */\n 553:\t\tif (unlikely(sk-\u003esk_family != AF_INET6))\n 554:\t\t\tgoto unlock;\n 555:\t\n 556:\t\tswitch (optname) {\n 557:\t\n 558:\t\tcase IPV6_ADDRFORM:\n 559:\t\t\tif (optlen \u003c sizeof(int))\n 560:\t\t\t\tgoto e_inval;\n 561:\t\t\tif (val == PF_INET) {\n 562:\t\t\t\tif (sk-\u003esk_type == SOCK_RAW)\n 563:\t\t\t\t\tbreak;\n 564:\t\n 565:\t\t\t\tif (sk-\u003esk_protocol == IPPROTO_UDP) {\n 566:\t\t\t\t\tif (udp_sk(sk)-\u003epending == AF_INET6) {\n 567:\t\t\t\t\t\tretv = -EBUSY;\n 568:\t\t\t\t\t\tbreak;\n 569:\t\t\t\t\t}\n 570:\t\t\t\t} else if (sk-\u003esk_protocol == IPPROTO_TCP) {\n 571:\t\t\t\t\tif (sk-\u003esk_prot != \u0026tcpv6_prot) {\n 572:\t\t\t\t\t\tretv = -EBUSY;\n 573:\t\t\t\t\t\tbreak;\n 574:\t\t\t\t\t}\n 575:\t\t\t\t} else {\n 576:\t\t\t\t\tbreak;\n 577:\t\t\t\t}\n 578:\t\n 579:\t\t\t\tif (sk-\u003esk_state != TCP_ESTABLISHED) {\n"
}

9/2 2026/08/24 04:37 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 9716
							output: 31
							thoughts: 158
						

Thoughts:
**Analyzing the TCP Listen Socket Handling Patch**

Okay, so this patch is definitely dealing with `IPV6_ADDRFORM`. I see it right there. It looks like the main area of focus is how the kernel handles incoming packets on listening TCP sockets. We're talking specifically about the functions `tcp_rcv_listen_state_process`, `tcp_v4_rcv_listen`, and `tcp_v6_rcv_listen`. That makes sense; incoming connections have to be properly routed to a specific socket.

Beyond the packet processing functions, this also touches on `IPV6_ADDRFORM` setsockopt handling for TCP sockets. This probably affects how we deal with the family of connections being accepted, which is critical.

I need to focus on a few key symbols here: `tcp_rcv_listen_state_process` because that's the heart of state transitions for incoming connections, and `do_ipv6_setsockopt` which likely deals with configurations.

Of course, the `IPV6` config option is involved, particularly in the `do_ipv6_setsockopt` and `tcp_v6_rcv_listen` functions. I'll need to double-check that `IPV6` is the *right* config option, but I'm betting that's the right one.



10/2 2026/08/24 04:37 tool grepper
0m Args:
{
  "Expression": "config IPV6",
  "PathPrefix": "net/ipv6/Kconfig"
}

Results:
{
  "Output": "net/ipv6/Kconfig-5-\nnet/ipv6/Kconfig:6:menuconfig IPV6\nnet/ipv6/Kconfig-7-\tbool \"The IPv6 protocol\"\n--\nnet/ipv6/Kconfig=19=if IPV6\nnet/ipv6/Kconfig-20-\nnet/ipv6/Kconfig:21:config IPV6_ROUTER_PREF\nnet/ipv6/Kconfig-22-\tbool \"IPv6: Router Preference (RFC 4191) support\"\n--\nnet/ipv6/Kconfig-30-\nnet/ipv6/Kconfig:31:config IPV6_ROUTE_INFO\nnet/ipv6/Kconfig-32-\tbool \"IPv6: Route Information (RFC 4191) support\"\n--\nnet/ipv6/Kconfig-38-\nnet/ipv6/Kconfig:39:config IPV6_OPTIMISTIC_DAD\nnet/ipv6/Kconfig-40-\tbool \"IPv6: Enable RFC 4429 Optimistic DAD\"\n--\nnet/ipv6/Kconfig=102=config INET6_IPCOMP\n--\nnet/ipv6/Kconfig-111-\nnet/ipv6/Kconfig:112:config IPV6_MIP6\nnet/ipv6/Kconfig-113-\ttristate \"IPv6: Mobility\"\n--\nnet/ipv6/Kconfig-119-\nnet/ipv6/Kconfig:120:config IPV6_ILA\nnet/ipv6/Kconfig-121-\ttristate \"IPv6: Identifier Locator Addressing (ILA)\"\n--\nnet/ipv6/Kconfig=146=config INET6_TUNNEL\n--\nnet/ipv6/Kconfig-149-\nnet/ipv6/Kconfig:150:config IPV6_VTI\nnet/ipv6/Kconfig-151-\ttristate \"Virtual (secure) IPv6: tunneling\"\n--\nnet/ipv6/Kconfig-161-\nnet/ipv6/Kconfig:162:config IPV6_SIT\nnet/ipv6/Kconfig-163-\ttristate \"IPv6: IPv6-in-IPv4 tunnel (SIT driver)\"\n--\nnet/ipv6/Kconfig-176-\nnet/ipv6/Kconfig:177:config IPV6_SIT_6RD\nnet/ipv6/Kconfig-178-\tbool \"IPv6: IPv6 Rapid Deployment (6RD)\"\n--\nnet/ipv6/Kconfig-195-\nnet/ipv6/Kconfig:196:config IPV6_NDISC_NODETYPE\nnet/ipv6/Kconfig-197-\tbool\nnet/ipv6/Kconfig-198-\nnet/ipv6/Kconfig:199:config IPV6_TUNNEL\nnet/ipv6/Kconfig-200-\ttristate \"IPv6: IP-in-IPv6 tunnel (RFC2473)\"\n--\nnet/ipv6/Kconfig-209-\nnet/ipv6/Kconfig:210:config IPV6_GRE\nnet/ipv6/Kconfig-211-\ttristate \"IPv6: GRE tunnel\"\n--\nnet/ipv6/Kconfig-227-\nnet/ipv6/Kconfig:228:config IPV6_FOU\nnet/ipv6/Kconfig-229-\ttristate\n--\nnet/ipv6/Kconfig-231-\nnet/ipv6/Kconfig:232:config IPV6_FOU_TUNNEL\nnet/ipv6/Kconfig-233-\ttristate\n--\nnet/ipv6/Kconfig-236-\nnet/ipv6/Kconfig:237:config IPV6_MULTIPLE_TABLES\nnet/ipv6/Kconfig-238-\tbool \"IPv6: Multiple Routing Tables\"\n--\nnet/ipv6/Kconfig-242-\nnet/ipv6/Kconfig:243:config IPV6_SUBTREES\nnet/ipv6/Kconfig-244-\tbool \"IPv6: source address based routing\"\n--\nnet/ipv6/Kconfig-256-\nnet/ipv6/Kconfig:257:config IPV6_MROUTE\nnet/ipv6/Kconfig-258-\tbool \"IPv6: multicast routing\"\n--\nnet/ipv6/Kconfig-264-\nnet/ipv6/Kconfig:265:config IPV6_MROUTE_MULTIPLE_TABLES\nnet/ipv6/Kconfig-266-\tbool \"IPv6: multicast policy routing\"\n--\nnet/ipv6/Kconfig-278-\nnet/ipv6/Kconfig:279:config IPV6_PIMSM_V2\nnet/ipv6/Kconfig-280-\tbool \"IPv6: PIM-SM version 2 support\"\n--\nnet/ipv6/Kconfig-285-\nnet/ipv6/Kconfig:286:config IPV6_SEG6_LWTUNNEL\nnet/ipv6/Kconfig-287-\tbool \"IPv6: Segment Routing Header encapsulation support\"\n--\nnet/ipv6/Kconfig-299-\nnet/ipv6/Kconfig:300:config IPV6_SEG6_HMAC\nnet/ipv6/Kconfig-301-\tbool \"IPv6: Segment Routing HMAC support\"\n--\nnet/ipv6/Kconfig-311-\nnet/ipv6/Kconfig:312:config IPV6_SEG6_BPF\nnet/ipv6/Kconfig-313-\tdef_bool y\n--\nnet/ipv6/Kconfig-316-\nnet/ipv6/Kconfig:317:config IPV6_RPL_LWTUNNEL\nnet/ipv6/Kconfig-318-\tbool \"IPv6: RPL Source Routing Header support\"\n--\nnet/ipv6/Kconfig-327-\nnet/ipv6/Kconfig:328:config IPV6_IOAM6_LWTUNNEL\nnet/ipv6/Kconfig-329-\tbool \"IPv6: IOAM Pre-allocated Trace insertion support\"\n"
}

11/2 2026/08/24 04:37 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 11731
							output: 169
							thoughts: 382
						

Thoughts:
**My Fuzzing Strategy: Targeting TCP Listening Sockets with IPv6 Configuration**

Okay, so the `IPV6` config is definitely relevant here. My initial review of the code has highlighted several key functions to focus my fuzzing efforts on. I've pinpointed `tcp_rcv_listen_state_process`, `do_ipv6_setsockopt`, `tcp_v4_rcv`, and `tcp_v6_rcv` as the areas of interest.

Immediately, I'm dismissing `tcp_v4_rcv` and `tcp_v6_rcv` – those are hot-path functions. Fuzzing those directly is likely to be noisy and generate a lot of false positives, which is not ideal. But that doesn't mean I won't indirectly test them.

`tcp_rcv_listen_state_process` looks promising, though. The same is true for `do_ipv6_setsockopt`. It looks like `sk_clone` is modified too, but I'm setting it aside because that's more of a general function. It's less likely to expose vulnerabilities specific to this patch.

The next question: are `tcp_rcv_listen_state_process` and `do_ipv6_setsockopt` reachable from user space? Yes, in both cases. I can trigger `tcp_rcv_listen_state_process` by sending TCP packets to a listening socket, and I can trigger `do_ipv6_setsockopt` by calling `setsockopt` with `IPV6_ADDRFORM` on an IPv6 socket. These are ideal targets.

Essentially, this patch modifies how TCP listening sockets handle packets and introduces lockless receive paths. It also adds new checks in `do_ipv6_setsockopt` when you deal with IPv6 socket options and sockets which have pending connection requests. This is a functional change to the core TCP stack and IPv6 socket options. These changes are reachable from user space via network traffic and are my key targets for fuzzing.



12/2 2026/08/24 04:37 tool set-results
0m Args:
{
  "EnableConfigs": [
    "IPV6"
  ],
  "FocusSymbols": [
    "tcp_rcv_listen_state_process",
    "do_ipv6_setsockopt"
  ],
  "Reasoning": "The patch modifies TCP listening socket packet processing by introducing `tcp_rcv_listen_state_process` and lockless listen receive paths (`tcp_v4_rcv_listen`, `tcp_v6_rcv_listen`). It also adds checks in `do_ipv6_setsockopt` for `IPV6_ADDRFORM` on TCP sockets with pending connection requests. These are functional changes to the core TCP stack and IPv6 socket options, reachable from user space and network traffic, and should be fuzzed.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "IPV6"
  ],
  "FocusSymbols": [
    "tcp_rcv_listen_state_process",
    "do_ipv6_setsockopt"
  ],
  "Reasoning": "The patch modifies TCP listening socket packet processing by introducing `tcp_rcv_listen_state_process` and lockless listen receive paths (`tcp_v4_rcv_listen`, `tcp_v6_rcv_listen`). It also adds checks in `do_ipv6_setsockopt` for `IPV6_ADDRFORM` on TCP sockets with pending connection requests. These are functional changes to the core TCP stack and IPv6 socket options, reachable from user space and network traffic, and should be fuzzed.",
  "WorthFuzzing": true
}

13/1 2026/08/24 04:37 action If
0m Args:
{
  "WorthFuzzing": true
}

Results:
null

14/2 2026/08/24 04:37 agent kmsan-evaluator
0m Model:
best-expensive

Args:
null

Results:
{
  "KMSANReasoning": "The patch implements lockless TCP listener processing and fixes several issues related to socket cloning and state inheritance (e.g., resetting `sk_tsq_flags`, `packets_out`, and `pinet6` in cloned sockets). \n\n1. The fields being explicitly zeroed or set to NULL in `sk_clone` and `tcp_create_openreq_child` do not represent uninitialized memory. They are already fully initialized via `sock_copy` (which copies the parent socket's state). The changes merely prevent the child socket from inheriting stale or incorrect values from the listener.\n2. The lockless listener processing (`tcp_v4_rcv_listen`) introduces concurrency changes. Any resulting bugs would be data races (caught by KCSAN) or use-after-free/memory corruption (caught by KASAN).\n3. The `IPV6_ADDRFORM` and `do_ipv6_setsockopt` changes address logic bugs and potential use-after-free scenarios, which are well within the domain of KASAN.\n\nThere are no new structures sent to user space, no new allocations left uninitialized, and no changes to bounds checking that would expose uninitialized memory. Thus, a dedicated KMSAN fuzzing session is not required.",
  "NeedsKMSAN": false
}

Instruction:
You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.

CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
  a comprehensive suite of debugging tools and sanitizers, including KASAN
  (out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
  (locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
  or page allocations) and kernel-to-user memory info-leaks.

Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.

Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.

Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
   attributes, ioctl output arguments, socket options, or BPF buffers) where fields
   or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
   or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
   could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
   uninitialized bytes of existing buffers.

Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
  dereferences, locking deadlocks, or use-after-free bugs (these are already caught
  by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
  or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.

Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 8ce5d56c06f9686e398cea7789e515fbf31b5ad8
Author: syz-cluster <triage@syzkaller.com>
Date:   Mon Aug 24 04:37:11 2026 +0000

    syz-cluster: applied patch under review

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 2c5b889530b55..add438d6561be 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -392,6 +392,8 @@ void tcp_write_timer_handler(struct sock *sk);
 void tcp_delack_timer_handler(struct sock *sk);
 int tcp_ioctl(struct sock *sk, int cmd, int *karg);
 enum skb_drop_reason tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb);
+enum skb_drop_reason tcp_rcv_listen_state_process(struct sock *sk,
+						  struct sk_buff *skb);
 void tcp_rcv_established(struct sock *sk, struct sk_buff *skb);
 void tcp_rcvbuf_grow(struct sock *sk, u32 newval);
 void tcp_rcv_space_adjust(struct sock *sk);
diff --git a/net/core/sock.c b/net/core/sock.c
index 1ad41904db25b..06fbb19824e26 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2479,7 +2479,7 @@ static void sk_init_common(struct sock *sk)
 struct sock *sk_clone(const struct sock *sk, const gfp_t priority,
 		      bool lock)
 {
-	struct proto *prot = READ_ONCE(sk->sk_prot);
+	struct proto *prot = sk->sk_prot_creator;
 	struct sk_filter *filter;
 	bool is_charged = true;
 	struct sock *newsk;
@@ -2533,6 +2533,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority,
 	newsk->sk_reserved_mem  = 0;
 	DEBUG_NET_WARN_ON_ONCE(newsk->sk_drop_counters);
 	sk_drops_reset(newsk);
+	newsk->sk_tsq_flags	= 0;
 	newsk->sk_send_head	= NULL;
 	newsk->sk_userlocks	= sk->sk_userlocks & ~SOCK_BINDPORT_LOCK;
 	atomic_set(&newsk->sk_zckey, 0);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 0f60a1dbf9274..77af18fba66b4 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -7141,6 +7141,42 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk)
 	tcp_rearm_rto(sk);
 }
 
+enum skb_drop_reason tcp_rcv_listen_state_process(struct sock *sk,
+						  struct sk_buff *skb)
+{
+	const struct tcphdr *th = tcp_hdr(skb);
+	SKB_DR(reason);
+
+	if (th->ack)
+		return SKB_DROP_REASON_TCP_FLAGS;
+
+	if (th->rst) {
+		SKB_DR_SET(reason, TCP_RESET);
+		goto discard;
+	}
+	if (th->syn) {
+		if (th->fin) {
+			SKB_DR_SET(reason, TCP_FLAGS);
+			goto discard;
+		}
+		/* It is possible that we process SYN packets from backlog,
+		 * so we need to make sure to disable BH and RCU right there.
+		 */
+		rcu_read_lock();
+		local_bh_disable();
+		inet_csk(sk)->icsk_af_ops->conn_request(sk, skb);
+		local_bh_enable();
+		rcu_read_unlock();
+
+		consume_skb(skb);
+		return 0;
+	}
+	SKB_DR_SET(reason, TCP_FLAGS);
+discard:
+	tcp_drop_reason(sk, skb, reason);
+	return 0;
+}
+
 /*
  *	This function implements the receiving procedure of RFC 793 for
  *	all states except ESTABLISHED and TIME_WAIT.
@@ -7152,7 +7188,6 @@ enum skb_drop_reason
 tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct inet_connection_sock *icsk = inet_csk(sk);
 	const struct tcphdr *th = tcp_hdr(skb);
 	struct request_sock *req;
 	int queued = 0;
@@ -7164,32 +7199,7 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
 		goto discard;
 
 	case TCP_LISTEN:
-		if (th->ack)
-			return SKB_DROP_REASON_TCP_FLAGS;
-
-		if (th->rst) {
-			SKB_DR_SET(reason, TCP_RESET);
-			goto discard;
-		}
-		if (th->syn) {
-			if (th->fin) {
-				SKB_DR_SET(reason, TCP_FLAGS);
-				goto discard;
-			}
-			/* It is possible that we process SYN packets from backlog,
-			 * so we need to make sure to disable BH and RCU right there.
-			 */
-			rcu_read_lock();
-			local_bh_disable();
-			icsk->icsk_af_ops->conn_request(sk, skb);
-			local_bh_enable();
-			rcu_read_unlock();
-
-			consume_skb(skb);
-			return 0;
-		}
-		SKB_DR_SET(reason, TCP_FLAGS);
-		goto discard;
+		return tcp_rcv_listen_state_process(sk, skb);
 
 	case TCP_SYN_SENT:
 		tp->rx_opt.saw_tstamp = 0;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 190c7af4cf923..2fa8958380a5b 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1714,6 +1714,14 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
 		inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
 	atomic_set(&newinet->inet_id, get_random_u16());
 
+#if IS_ENABLED(CONFIG_IPV6)
+	/* Never inherit the listener's ipv6_pinfo; IPV6_ADDRFORM leaves it set
+	 * on an AF_INET socket.  tcp_v6_mapped_child_init() installs our own.
+	 */
+	newinet->pinet6 = NULL;
+	newinet->ipv6_fl_list = NULL;
+#endif
+
 	/* Set ToS of the new socket based upon the value of incoming SYN.
 	 * ECT bits are set later in tcp_init_transfer().
 	 */
@@ -1820,7 +1828,7 @@ u16 tcp_v4_get_syncookie(struct sock *sk, struct iphdr *iph,
 INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
 							   u32));
 /* The socket must have it's spinlock held when we get
- * here, unless it is a TCP_LISTEN socket.
+ * here.
  *
  * We have a potential double-lock case here, so even when
  * doing backlog processing we use the BH locking scheme.
@@ -1898,6 +1906,46 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 	goto discard;
 }
 
+/* @sk is not locked here and can leave TCP_LISTEN; do not test sk_state. */
+static noinline int tcp_v4_rcv_listen(struct sock *sk, struct sk_buff *skb)
+{
+	enum skb_drop_reason reason;
+	struct sock *nsk;
+
+	reason = psp_sk_rx_policy_check(sk, skb);
+	if (reason)
+		goto err_discard;
+
+	if (tcp_checksum_complete(skb))
+		goto csum_err;
+
+	nsk = tcp_v4_cookie_check(sk, skb);
+	if (!nsk)
+		return 0;
+
+	if (nsk != sk) {
+		reason = tcp_child_process(sk, nsk, skb);
+		sock_put(nsk);
+	} else {
+		reason = tcp_rcv_listen_state_process(sk, skb);
+	}
+	if (!reason)
+		return 0;
+
+	tcp_v4_send_reset(sk, skb, sk_rst_convert_drop_reason(reason));
+discard:
+	sk_skb_reason_drop(sk, skb, reason);
+	return 0;
+
+csum_err:
+	reason = SKB_DROP_REASON_TCP_CSUM;
+	trace_tcp_bad_csum(skb);
+	TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
+err_discard:
+	TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
+	goto discard;
+}
+
 enum skb_drop_reason tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
 	u32 tail_gso_size, tail_gso_segs;
@@ -2235,7 +2283,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
 	skb->dev = NULL;
 
 	if (sk->sk_state == TCP_LISTEN) {
-		ret = tcp_v4_do_rcv(sk, skb);
+		ret = tcp_v4_rcv_listen(sk, skb);
 		goto put_and_return;
 	}
 
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 12254e6eb2f34..2fde196dd302f 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -591,6 +591,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
 	newtp->total_retrans = req->num_retrans;
 
 	tcp_init_xmit_timers(newsk);
+	newtp->out_of_order_queue = RB_ROOT;
 	WRITE_ONCE(newtp->write_seq, newtp->pushed_seq = treq->snt_isn + 1);
 
 	if (sock_flag(newsk, SOCK_KEEPOPEN))
@@ -659,6 +660,12 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
 	tcp_ecn_openreq_child(newsk, req, skb);
 	newtp->fastopen_req = NULL;
 	RCU_INIT_POINTER(newtp->fastopen_rsk, NULL);
+	newtp->packets_out = 0;
+	newtp->retrans_out = 0;
+	newtp->sacked_out = 0;
+	newtp->lost_out = 0;
+	newtp->retransmit_skb_hint = NULL;
+	newtp->highest_sack = NULL;
 
 	newtp->bpf_chg_cc_inprogress = 0;
 	tcp_bpf_clone(sk, newsk);
@@ -974,7 +981,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 		tcp_reset(sk, skb);
 	}
 	if (!fastopen) {
-		bool unlinked = inet_csk_reqsk_queue_drop(sk, req);
+		bool unlinked = inet_csk_reqsk_queue_drop(req->rsk_listener, req);
 
 		if (unlinked)
 			__NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 282912a119999..68b330f6941d0 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -479,6 +479,10 @@ void inet6_cleanup_sock(struct sock *sk)
 	struct sk_buff *skb;
 	struct ipv6_txoptions *opt;
 
+	/* AF_INET child of an IPV6_ADDRFORM'ed listener: nothing of its own. */
+	if (!np)
+		return;
+
 	/* Release rx options */
 
 	skb = xchg(&np->pktoptions, NULL);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index b4c977434c2e0..6d2dd9ae46a96 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -587,6 +587,21 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
 				break;
 			}
 
+			if (sk->sk_protocol == IPPROTO_TCP) {
+				if (inet_csk_reqsk_queue_len(sk)) {
+					retv = -EBUSY;
+					break;
+				}
+				/* A SYN that found this socket while it was
+				 * still listening may not be counted yet.
+				 */
+				synchronize_rcu();
+				if (inet_csk_reqsk_queue_len(sk)) {
+					retv = -EBUSY;
+					break;
+				}
+			}
+
 			__ipv6_sock_mc_close(sk);
 			__ipv6_sock_ac_close(sk);
 
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 9e9155b1b3aa7..a2deda9a4258b 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1556,7 +1556,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
 INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
 							   u32));
 /* The socket must have it's spinlock held when we get
- * here, unless it is a TCP_LISTEN socket.
+ * here.
  *
  * We have a potential double-lock case here, so even when
  * doing backlog processing we use the BH locking scheme.
@@ -1704,6 +1704,46 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
 	return 0;
 }
 
+/* @sk is not locked here and can leave TCP_LISTEN; do not test sk_state. */
+static noinline int tcp_v6_rcv_listen(struct sock *sk, struct sk_buff *skb)
+{
+	enum skb_drop_reason reason;
+	struct sock *nsk;
+
+	reason = psp_sk_rx_policy_check(sk, skb);
+	if (reason)
+		goto err_discard;
+
+	if (tcp_checksum_complete(skb))
+		goto csum_err;
+
+	nsk = tcp_v6_cookie_check(sk, skb);
+	if (!nsk)
+		return 0;
+
+	if (nsk != sk) {
+		reason = tcp_child_process(sk, nsk, skb);
+		sock_put(nsk);
+	} else {
+		reason = tcp_rcv_listen_state_process(sk, skb);
+	}
+	if (!reason)
+		return 0;
+
+	tcp_v6_send_reset(sk, skb, sk_rst_convert_drop_reason(reason));
+discard:
+	sk_skb_reason_drop(sk, skb, reason);
+	return 0;
+
+csum_err:
+	reason = SKB_DROP_REASON_TCP_CSUM;
+	trace_tcp_bad_csum(skb);
+	TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
+err_discard:
+	TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
+	goto discard;
+}
+
 static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr,
 			   const struct tcphdr *th)
 {
@@ -1891,7 +1931,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
 	skb->dev = NULL;
 
 	if (sk->sk_state == TCP_LISTEN) {
-		ret = tcp_v6_do_rcv(sk, skb);
+		ret = tcp_v6_rcv_listen(sk, skb);
 		goto put_and_return;
 	}
 

15/3 2026/08/24 04:37 llm kmsan-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 6551
							output: 293
							thoughts: 2484
						

Thoughts:
**KMSAN Assessment: This Patch Doesn't Warrant It**

Okay, so I've been digging into this patch. It's modifying TCP socket handling, especially around the `TCP_LISTEN` state and socket cloning. Initially, I thought this might be a KMSAN candidate, but after a deep dive, I'm pretty confident it's not.

The patch's core change is to make the TCP listener processing lockless, pulling the logic out into `tcp_v4_rcv_listen` and `tcp_v6_rcv_listen`. That's a huge shift – it's all about concurrency now. The big deal here is the potential for race conditions or use-after-free bugs because we're taking away that lock protection. However, these are precisely the kinds of things KCSAN (data races) and KASAN (UAF, memory corruption) are built to catch. KMSAN isn't the right tool for those types of concurrency issues.

There are also several changes related to socket cloning (`sk_clone` and `tcp_create_openreq_child`), making sure certain fields are reset when a new socket is created from the listener socket. I was concerned about uninitialized memory in the cloned socket, but that's not the case. The `sock_copy` function *fully* copies the parent socket's data using `memcpy`. The patch is simply resetting some of these fields (like `sk_tsq_flags`, `packets_out`, and `pinet6`) to their initial zero state in the child socket. It's about preventing the child socket from inheriting potentially stale or incorrect values from the parent, not about dealing with uninitialized memory. So, this isn't an uninitialized memory issue; it's a logic bug fix, or a defensive measure.

Finally, the fix for `IPV6_ADDRFORM` and the adjustments in `do_ipv6_setsockopt` specifically safeguard against potential double-free or use-after-free bugs related to `pinet6`. This falls squarely within KASAN's detection capabilities. Also, `do_ipv6_setsockopt` seems to be preventing socket options from being changed during connection establishment, likely to prevent more potential bugs.

In conclusion, none of these changes introduce, nor expose, uninitialized memory risks. The patch focuses on concurrency (KCSAN/KASAN) and correcting logic/data flow issues during cloning and state inheritance (KASAN). Given the "rules" for determining whether to include KMSAN in testing, this seems to be a hard "no".



16/3 2026/08/24 04:38 tool set-results
0m Args:
{
  "KMSANReasoning": "The patch implements lockless TCP listener processing and fixes several issues related to socket cloning and state inheritance (e.g., resetting `sk_tsq_flags`, `packets_out`, and `pinet6` in cloned sockets). \n\n1. The fields being explicitly zeroed or set to NULL in `sk_clone` and `tcp_create_openreq_child` do not represent uninitialized memory. They are already fully initialized via `sock_copy` (which copies the parent socket's state). The changes merely prevent the child socket from inheriting stale or incorrect values from the listener.\n2. The lockless listener processing (`tcp_v4_rcv_listen`) introduces concurrency changes. Any resulting bugs would be data races (caught by KCSAN) or use-after-free/memory corruption (caught by KASAN).\n3. The `IPV6_ADDRFORM` and `do_ipv6_setsockopt` changes address logic bugs and potential use-after-free scenarios, which are well within the domain of KASAN.\n\nThere are no new structures sent to user space, no new allocations left uninitialized, and no changes to bounds checking that would expose uninitialized memory. Thus, a dedicated KMSAN fuzzing session is not required.",
  "NeedsKMSAN": false
}

Results:
{
  "KMSANReasoning": "The patch implements lockless TCP listener processing and fixes several issues related to socket cloning and state inheritance (e.g., resetting `sk_tsq_flags`, `packets_out`, and `pinet6` in cloned sockets). \n\n1. The fields being explicitly zeroed or set to NULL in `sk_clone` and `tcp_create_openreq_child` do not represent uninitialized memory. They are already fully initialized via `sock_copy` (which copies the parent socket's state). The changes merely prevent the child socket from inheriting stale or incorrect values from the listener.\n2. The lockless listener processing (`tcp_v4_rcv_listen`) introduces concurrency changes. Any resulting bugs would be data races (caught by KCSAN) or use-after-free/memory corruption (caught by KASAN).\n3. The `IPV6_ADDRFORM` and `do_ipv6_setsockopt` changes address logic bugs and potential use-after-free scenarios, which are well within the domain of KASAN.\n\nThere are no new structures sent to user space, no new allocations left uninitialized, and no changes to bounds checking that would expose uninitialized memory. Thus, a dedicated KMSAN fuzzing session is not required.",
  "NeedsKMSAN": false
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)