AI Trajectory


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

Results:
{
  "EnableConfigs": [
    "MPTCP",
    "MPTCP_IPV6"
  ],
  "FocusSymbols": [
    "mptcp_pm_subflow_check_next",
    "mptcp_pm_nl_remove_doit",
    "mptcp_init_sock",
    "__mptcp_retrans",
    "mptcp_finish_join",
    "__mptcp_subflow_connect"
  ],
  "KMSANReasoning": "The patch series primarily focuses on:\n1. Removing the unused `data_ack` field from `struct mptcp_ext` and the corresponding `mptcp_dump_mpext` trace event.\n2. Adding new SNMP MIB counters for various MPTCP events (e.g., MP_JOIN failures, resets) and incrementing them in the appropriate error paths.\n3. Adding underflow checks (`WARN_ON_ONCE`) for `pm-\u003eextra_subflows`.\n4. Seeding RTO bounds (`icsk_rto_min`, `icsk_rto_max`) during MPTCP socket initialization.\n\nNone of these changes introduce new structures copied to user space, new buffer allocations, or complex conditional logic that could expose uninitialized memory. The removal of fields from the trace event and skb extension reduces the memory footprint, and the RTO bounds initialization ensures fields are properly seeded. Any potential bugs introduced by these changes (e.g., logic errors, out-of-bounds) would be adequately caught by standard KASAN and other default sanitizers. There is no risk of uninitialized memory usage or info-leaks that would necessitate a dedicated KMSAN fuzzing session.",
  "NeedsKMSAN": false,
  "Reasoning": "The patch introduces functional changes to the MPTCP subsystem. It adds `WARN_ON_ONCE` checks for subflow accounting in `mptcp_pm_subflow_check_next` and `__mptcp_pm_close_subflow` to catch underflows. It also updates the RTO bounds seeding to use sysctl values instead of hardcoded constants, affecting timeout calculations in `__mptcp_init_sock`, `mptcp_set_datafin_timeout`, and `__mptcp_set_timeout`. Additionally, it renames and restricts the scope of `mptcp_userspace_pm_remove_addr_entry`. These changes affect MPTCP connection management and timeout handling, which are reachable and should be fuzzed to ensure the new warnings are not triggered and timeouts behave correctly.",
  "WorthFuzzing": true
}

1/1 2026/08/12 17:12 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit acc20b625ef9d5f1a4da68bfbfd9d7b9be77bc07\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Wed Aug 12 17:12:15 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/include/net/mptcp.h b/include/net/mptcp.h\nindex 71b9fc5a57963..485d55b66ea67 100644\n--- a/include/net/mptcp.h\n+++ b/include/net/mptcp.h\n@@ -19,10 +19,6 @@ struct seq_file;\n \n /* MPTCP sk_buff extension data */\n struct mptcp_ext {\n-\tunion {\n-\t\tu64\tdata_ack;\n-\t\tu32\tdata_ack32;\n-\t};\n \tu64\t\tdata_seq;\n \tu32\t\tsubflow_seq;\n \tu16\t\tdata_len;\ndiff --git a/include/trace/events/mptcp.h b/include/trace/events/mptcp.h\nindex 04521acba4832..22882bd034593 100644\n--- a/include/trace/events/mptcp.h\n+++ b/include/trace/events/mptcp.h\n@@ -75,7 +75,6 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,\n \tTP_ARGS(mpext),\n \n \tTP_STRUCT__entry(\n-\t\t__field(u64, data_ack)\n \t\t__field(u64, data_seq)\n \t\t__field(u32, subflow_seq)\n \t\t__field(u16, data_len)\n@@ -94,7 +93,6 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,\n \t),\n \n \tTP_fast_assign(\n-\t\t__entry-\u003edata_ack = mpext-\u003eack64 ? mpext-\u003edata_ack : mpext-\u003edata_ack32;\n \t\t__entry-\u003edata_seq = mpext-\u003edata_seq;\n \t\t__entry-\u003esubflow_seq = mpext-\u003esubflow_seq;\n \t\t__entry-\u003edata_len = mpext-\u003edata_len;\n@@ -112,8 +110,8 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,\n \t\t__entry-\u003einfinite_map = mpext-\u003einfinite_map;\n \t),\n \n-\tTP_printk(\"data_ack=%llu data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u infinite_map=%u\",\n-\t\t  __entry-\u003edata_ack, __entry-\u003edata_seq,\n+\tTP_printk(\"data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u infinite_map=%u\",\n+\t\t  __entry-\u003edata_seq,\n \t\t  __entry-\u003esubflow_seq, __entry-\u003edata_len,\n \t\t  __entry-\u003ecsum, __entry-\u003euse_map,\n \t\t  __entry-\u003edsn64, __entry-\u003edata_fin,\ndiff --git a/net/mptcp/mib.c b/net/mptcp/mib.c\nindex 2569385bab7ca..608cb568897cf 100644\n--- a/net/mptcp/mib.c\n+++ b/net/mptcp/mib.c\n@@ -21,14 +21,19 @@ static const struct snmp_mib mptcp_snmp_list[] = {\n \tSNMP_MIB_ITEM(\"MPFallbackTokenInit\", MPTCP_MIB_TOKENFALLBACKINIT),\n \tSNMP_MIB_ITEM(\"MPTCPRetrans\", MPTCP_MIB_RETRANSSEGS),\n \tSNMP_MIB_ITEM(\"MPJoinNoTokenFound\", MPTCP_MIB_JOINNOTOKEN),\n+\tSNMP_MIB_ITEM(\"MPJoinNoIdFound\", MPTCP_MIB_MPJOINNOIDFOUND),\n \tSNMP_MIB_ITEM(\"MPJoinSynRx\", MPTCP_MIB_JOINSYNRX),\n \tSNMP_MIB_ITEM(\"MPJoinSynBackupRx\", MPTCP_MIB_JOINSYNBACKUPRX),\n \tSNMP_MIB_ITEM(\"MPJoinSynAckRx\", MPTCP_MIB_JOINSYNACKRX),\n \tSNMP_MIB_ITEM(\"MPJoinSynAckBackupRx\", MPTCP_MIB_JOINSYNACKBACKUPRX),\n \tSNMP_MIB_ITEM(\"MPJoinSynAckHMacFailure\", MPTCP_MIB_JOINSYNACKMAC),\n+\tSNMP_MIB_ITEM(\"MPJoinSynAckNoMPJoin\", MPTCP_MIB_MPJOINSYNACKNOMPJOIN),\n \tSNMP_MIB_ITEM(\"MPJoinAckRx\", MPTCP_MIB_JOINACKRX),\n \tSNMP_MIB_ITEM(\"MPJoinAckHMacFailure\", MPTCP_MIB_JOINACKMAC),\n+\tSNMP_MIB_ITEM(\"MPJoinAckNoMPJoin\", MPTCP_MIB_MPJOINACKNOMPJOIN),\n+\tSNMP_MIB_ITEM(\"MPJoinAckNoCtx\", MPTCP_MIB_MPJOINACKNOCTX),\n \tSNMP_MIB_ITEM(\"MPJoinRejected\", MPTCP_MIB_JOINREJECTED),\n+\tSNMP_MIB_ITEM(\"MPJoinNotEstablished\", MPTCP_MIB_MPJOINNOTESTABLISHED),\n \tSNMP_MIB_ITEM(\"MPJoinSynTx\", MPTCP_MIB_JOINSYNTX),\n \tSNMP_MIB_ITEM(\"MPJoinSynTxCreatSkErr\", MPTCP_MIB_JOINSYNTXCREATSKERR),\n \tSNMP_MIB_ITEM(\"MPJoinSynTxBindErr\", MPTCP_MIB_JOINSYNTXBINDERR),\n@@ -81,7 +86,9 @@ static const struct snmp_mib mptcp_snmp_list[] = {\n \tSNMP_MIB_ITEM(\"Blackhole\", MPTCP_MIB_BLACKHOLE),\n \tSNMP_MIB_ITEM(\"MPCapableDataFallback\", MPTCP_MIB_MPCAPABLEDATAFALLBACK),\n \tSNMP_MIB_ITEM(\"MD5SigFallback\", MPTCP_MIB_MD5SIGFALLBACK),\n+\tSNMP_MIB_ITEM(\"MD5SigReset\", MPTCP_MIB_MD5SIGRESET),\n \tSNMP_MIB_ITEM(\"DssFallback\", MPTCP_MIB_DSSFALLBACK),\n+\tSNMP_MIB_ITEM(\"DssReset\", MPTCP_MIB_DSSRESET),\n \tSNMP_MIB_ITEM(\"SimultConnectFallback\", MPTCP_MIB_SIMULTCONNFALLBACK),\n \tSNMP_MIB_ITEM(\"FallbackFailed\", MPTCP_MIB_FALLBACKFAILED),\n \tSNMP_MIB_ITEM(\"WinProbe\", MPTCP_MIB_WINPROBE),\ndiff --git a/net/mptcp/mib.h b/net/mptcp/mib.h\nindex 3a3425e258a76..1ebdb55e95343 100644\n--- a/net/mptcp/mib.h\n+++ b/net/mptcp/mib.h\n@@ -16,14 +16,19 @@ enum linux_mptcp_mib_field {\n \tMPTCP_MIB_TOKENFALLBACKINIT,\t/* Could not init/allocate token */\n \tMPTCP_MIB_RETRANSSEGS,\t\t/* Segments retransmitted at the MPTCP-level */\n \tMPTCP_MIB_JOINNOTOKEN,\t\t/* Received MP_JOIN but the token was not found */\n+\tMPTCP_MIB_MPJOINNOIDFOUND,\t/* Received MP_JOIN but no local ID was found */\n \tMPTCP_MIB_JOINSYNRX,\t\t/* Received a SYN + MP_JOIN */\n \tMPTCP_MIB_JOINSYNBACKUPRX,\t/* Received a SYN + MP_JOIN + backup flag */\n \tMPTCP_MIB_JOINSYNACKRX,\t\t/* Received a SYN/ACK + MP_JOIN */\n \tMPTCP_MIB_JOINSYNACKBACKUPRX,\t/* Received a SYN/ACK + MP_JOIN + backup flag */\n \tMPTCP_MIB_JOINSYNACKMAC,\t/* HMAC was wrong on SYN/ACK + MP_JOIN */\n+\tMPTCP_MIB_MPJOINSYNACKNOMPJOIN,\t/* MP_RST: missing MP_JOIN in SYN/ACK */\n \tMPTCP_MIB_JOINACKRX,\t\t/* Received an ACK + MP_JOIN */\n \tMPTCP_MIB_JOINACKMAC,\t\t/* HMAC was wrong on ACK + MP_JOIN */\n+\tMPTCP_MIB_MPJOINACKNOMPJOIN,\t/* MP_RST: missing MP_JOIN in ACK */\n+\tMPTCP_MIB_MPJOINACKNOCTX,\t/* MP_RST: no subflow context on ACK */\n \tMPTCP_MIB_JOINREJECTED,\t\t/* The PM rejected the JOIN request */\n+\tMPTCP_MIB_MPJOINNOTESTABLISHED,\t/* MP_RST: JOIN on not-fully-established msk */\n \tMPTCP_MIB_JOINSYNTX,\t\t/* Sending a SYN + MP_JOIN */\n \tMPTCP_MIB_JOINSYNTXCREATSKERR,\t/* Not able to create a socket when sending a SYN + MP_JOIN */\n \tMPTCP_MIB_JOINSYNTXBINDERR,\t/* Not able to bind() the address when sending a SYN + MP_JOIN */\n@@ -84,7 +89,9 @@ enum linux_mptcp_mib_field {\n \t\t\t\t\t * established packet\n \t\t\t\t\t */\n \tMPTCP_MIB_MD5SIGFALLBACK,\t/* Conflicting TCP option enabled */\n+\tMPTCP_MIB_MD5SIGRESET,\t\t/* MP_RST: MD5SIG enabled on listener */\n \tMPTCP_MIB_DSSFALLBACK,\t\t/* Bad or missing DSS */\n+\tMPTCP_MIB_DSSRESET,\t\t/* MP_RST: bad data mapping */\n \tMPTCP_MIB_SIMULTCONNFALLBACK,\t/* Simultaneous connect */\n \tMPTCP_MIB_FALLBACKFAILED,\t/* Can't fallback due to msk status */\n \tMPTCP_MIB_WINPROBE,\t\t/* MPTCP-level zero window probe */\ndiff --git a/net/mptcp/pm.c b/net/mptcp/pm.c\nindex d1f73c3e39fa3..8b68868255c50 100644\n--- a/net/mptcp/pm.c\n+++ b/net/mptcp/pm.c\n@@ -670,7 +670,8 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk,\n \tif (mptcp_pm_is_userspace(msk)) {\n \t\tif (update_subflows) {\n \t\t\tspin_lock_bh(\u0026pm-\u003elock);\n-\t\t\tpm-\u003eextra_subflows--;\n+\t\t\tif (!WARN_ON_ONCE(pm-\u003eextra_subflows == 0))\n+\t\t\t\tpm-\u003eextra_subflows--;\n \t\t\tspin_unlock_bh(\u0026pm-\u003elock);\n \t\t}\n \t\treturn;\ndiff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c\nindex 2203cc2d27485..b94fbb483bf94 100644\n--- a/net/mptcp/pm_userspace.c\n+++ b/net/mptcp/pm_userspace.c\n@@ -281,8 +281,9 @@ static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk)\n \treturn err;\n }\n \n-void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,\n-\t\t\t\tstruct mptcp_pm_addr_entry *entry)\n+static void\n+mptcp_userspace_pm_remove_addr_entry(struct mptcp_sock *msk,\n+\t\t\t\t     struct mptcp_pm_addr_entry *entry)\n {\n \tstruct mptcp_rm_list alist = { .nr = 0 };\n \tint anno_nr = 0;\n@@ -340,7 +341,7 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)\n \tlist_del_rcu(\u0026match-\u003elist);\n \tspin_unlock_bh(\u0026msk-\u003epm.lock);\n \n-\tmptcp_pm_remove_addr_entry(msk, match);\n+\tmptcp_userspace_pm_remove_addr_entry(msk, match);\n \n \trelease_sock(sk);\n \ndiff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c\nindex ec874d2ead6a4..b474d03620a75 100644\n--- a/net/mptcp/protocol.c\n+++ b/net/mptcp/protocol.c\n@@ -581,17 +581,23 @@ static bool mptcp_pending_data_fin(struct sock *sk, u64 *seq)\n static void mptcp_set_datafin_timeout(struct sock *sk)\n {\n \tstruct inet_connection_sock *icsk = inet_csk(sk);\n+\tu32 rto_min = READ_ONCE(icsk-\u003eicsk_rto_min);\n+\tu32 rto_max = READ_ONCE(icsk-\u003eicsk_rto_max);\n \tu32 retransmits;\n \n+\t/* The sysctls are validated independently: rto_min \u003e rto_max is\n+\t * possible, guard against ilog2(0).\n+\t */\n \tretransmits = min_t(u32, icsk-\u003eicsk_retransmits,\n-\t\t\t    ilog2(TCP_RTO_MAX / TCP_RTO_MIN));\n+\t\t\t    ilog2(max_t(u32, rto_max / rto_min, 1)));\n \n-\tmptcp_sk(sk)-\u003etimer_ival = TCP_RTO_MIN \u003c\u003c retransmits;\n+\tmptcp_sk(sk)-\u003etimer_ival = rto_min \u003c\u003c retransmits;\n }\n \n static void __mptcp_set_timeout(struct sock *sk, long tout)\n {\n-\tmptcp_sk(sk)-\u003etimer_ival = tout \u003e 0 ? tout : TCP_RTO_MIN;\n+\tmptcp_sk(sk)-\u003etimer_ival = tout \u003e 0 ? tout :\n+\t\t\t\t   READ_ONCE(inet_csk(sk)-\u003eicsk_rto_min);\n }\n \n static long mptcp_timeout_from_subflow(const struct mptcp_subflow_context *subflow)\n@@ -3161,7 +3167,9 @@ static void mptcp_worker(struct work_struct *work)\n \n static void __mptcp_init_sock(struct sock *sk)\n {\n+\tstruct inet_connection_sock *icsk = inet_csk(sk);\n \tstruct mptcp_sock *msk = mptcp_sk(sk);\n+\tstruct net *net = sock_net(sk);\n \n \tINIT_LIST_HEAD(\u0026msk-\u003econn_list);\n \tINIT_LIST_HEAD(\u0026msk-\u003ejoin_list);\n@@ -3170,7 +3178,13 @@ static void __mptcp_init_sock(struct sock *sk)\n \tINIT_WORK(\u0026msk-\u003ework, mptcp_worker);\n \tmsk-\u003eout_of_order_queue = RB_ROOT;\n \tmsk-\u003efirst_pending = NULL;\n-\tmsk-\u003etimer_ival = TCP_RTO_MIN;\n+\n+\t/* msk does not go through tcp_init_sock(); seed RTO bounds. */\n+\ticsk-\u003eicsk_rto_min =\n+\t\tusecs_to_jiffies(READ_ONCE(net-\u003eipv4.sysctl_tcp_rto_min_us));\n+\ticsk-\u003eicsk_rto_max =\n+\t\tmsecs_to_jiffies(READ_ONCE(net-\u003eipv4.sysctl_tcp_rto_max_ms));\n+\tmsk-\u003etimer_ival = icsk-\u003eicsk_rto_min;\n \tmsk-\u003escaling_ratio = TCP_DEFAULT_SCALING_RATIO;\n \tmsk-\u003ebacklog_len = 0;\n \tmptcp_init_rtt_est(msk);\n@@ -3988,6 +4002,7 @@ bool mptcp_finish_join(struct sock *ssk)\n \n \t/* mptcp socket already closing? */\n \tif (!mptcp_is_fully_established(parent)) {\n+\t\tMPTCP_INC_STATS(sock_net(parent), MPTCP_MIB_MPJOINNOTESTABLISHED);\n \t\tsubflow-\u003ereset_reason = MPTCP_RST_EMPTCP;\n \t\treturn false;\n \t}\ndiff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h\nindex b3af3462bdd16..06a107d4e8392 100644\n--- a/net/mptcp/protocol.h\n+++ b/net/mptcp/protocol.h\n@@ -1149,8 +1149,6 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,\n \t\t\t   const struct mptcp_addr_info *addr,\n \t\t\t   bool echo);\n int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list);\n-void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,\n-\t\t\t\tstruct mptcp_pm_addr_entry *entry);\n \n /* the default path manager, used in mptcp_pm_unregister */\n extern struct mptcp_pm_ops mptcp_pm_kernel;\n@@ -1254,7 +1252,8 @@ u8 mptcp_pm_get_limit_extra_subflows(const struct mptcp_sock *msk);\n /* called under PM lock */\n static inline void __mptcp_pm_close_subflow(struct mptcp_sock *msk)\n {\n-\tif (--msk-\u003epm.extra_subflows \u003c mptcp_pm_get_limit_extra_subflows(msk))\n+\tif (!WARN_ON_ONCE(msk-\u003epm.extra_subflows == 0) \u0026\u0026\n+\t    --msk-\u003epm.extra_subflows \u003c mptcp_pm_get_limit_extra_subflows(msk))\n \t\tWRITE_ONCE(msk-\u003epm.accept_subflow, true);\n }\n \ndiff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c\nindex e1f20ff8fdb42..af81ad5e699d1 100644\n--- a/net/mptcp/subflow.c\n+++ b/net/mptcp/subflow.c\n@@ -96,6 +96,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req)\n \n \tlocal_id = mptcp_pm_get_local_id(msk, (struct sock_common *)req);\n \tif (local_id \u003c 0) {\n+\t\tSUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPJOINNOIDFOUND);\n \t\tsock_put((struct sock *)msk);\n \t\treturn NULL;\n \t}\n@@ -160,6 +161,7 @@ static int subflow_check_req(struct request_sock *req,\n \t * TCP option space.\n \t */\n \tif (rcu_access_pointer(tcp_sk(sk_listener)-\u003emd5sig_info)) {\n+\t\tMPTCP_INC_STATS(sock_net(sk_listener), MPTCP_MIB_MD5SIGRESET);\n \t\tsubflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);\n \t\treturn -EINVAL;\n \t}\n@@ -563,6 +565,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)\n \t\tu8 hmac[SHA256_DIGEST_SIZE];\n \n \t\tif (!(mp_opt.suboptions \u0026 OPTION_MPTCP_MPJ_SYNACK)) {\n+\t\t\tMPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPJOINSYNACKNOMPJOIN);\n \t\t\tsubflow-\u003ereset_reason = MPTCP_RST_EMPTCP;\n \t\t\tgoto do_reset;\n \t\t}\n@@ -865,6 +868,12 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,\n \t\t */\n \t\tif (!ctx || fallback) {\n \t\t\tif (fallback_is_fatal) {\n+\t\t\t\tif (!ctx)\n+\t\t\t\t\tMPTCP_INC_STATS(sock_net(sk),\n+\t\t\t\t\t\t\tMPTCP_MIB_MPJOINACKNOCTX);\n+\t\t\t\telse\n+\t\t\t\t\tMPTCP_INC_STATS(sock_net(sk),\n+\t\t\t\t\t\t\tMPTCP_MIB_MPJOINACKNOMPJOIN);\n \t\t\t\tsubflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);\n \t\t\t\tgoto dispose_child;\n \t\t\t}\n@@ -1416,6 +1425,7 @@ static bool subflow_check_data_avail(struct sock *ssk)\n \t\t\t * subflow_error_report() will introduce the appropriate barriers\n \t\t\t */\n \t\t\tsubflow-\u003ereset_transient = 0;\n+\t\t\tMPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSRESET);\n \t\t\tsubflow-\u003ereset_reason = status == MAPPING_NODSS ?\n \t\t\t\t\t\tMPTCP_RST_EMIDDLEBOX :\n \t\t\t\t\t\tMPTCP_RST_EMPTCP;\ndiff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c\nindex cbe573c4ab3ad..ea4cb6c1bd5e2 100644\n--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c\n+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c\n@@ -1264,7 +1264,7 @@ static void apply_cmsg_types(int fd, const struct cfg_cmsg_types *cmsg)\n \n static void parse_cmsg_types(const char *type)\n {\n-\tchar *next = strchr(type, ',');\n+\tconst char *next = strchr(type, ',');\n \tunsigned int len = 0;\n \n \tcfg_cmsg_types.cmsg_enabled = 1;\n@@ -1292,7 +1292,7 @@ static void parse_cmsg_types(const char *type)\n \n static void parse_setsock_options(const char *name)\n {\n-\tchar *next = strchr(name, ',');\n+\tconst char *next = strchr(name, ',');\n \tunsigned int len = 0;\n \n \tif (next) {\ndiff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh\nindex d158678fa6ab0..7a2a851fa0adb 100755\n--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh\n+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh\n@@ -212,8 +212,8 @@ if $checksum; then\n fi\n \n if $capture; then\n-\trndh=\"${ns1:4}\"\n-\tmptcp_lib_pr_info \"Packet capture files will have this prefix: ${rndh}-\"\n+\tcapprefix=\"mptcp_connect-${ns1:4}\"\n+\tmptcp_lib_pr_info \"pcap will have this prefix: ${capprefix}-\"\n fi\n \n set_ethtool_flags() {\n@@ -372,8 +372,8 @@ do_transfer()\n \t\t\tcapuser=\"-Z $SUDO_USER\"\n \t\tfi\n \n-\t\tlocal capfile=\"${rndh}-${connector_ns:0:3}-${listener_ns:0:3}-${cl_proto}-${srv_proto}-${connect_addr}-${port}\"\n-\t\tlocal capopt=\"-i any -s 65535 -B 32768 ${capuser}\"\n+\t\tlocal capfile=\"${capprefix}-${connector_ns:0:3}-${listener_ns:0:3}-${cl_proto}-${srv_proto}-${connect_addr}-${port}\"\n+\t\tlocal capopt=\"-i any -s 128 -B 32768 ${capuser}\"\n \n \t\tip netns exec ${listener_ns} tcpdump ${capopt} \\\n \t\t\t-w \"${capfile}-listener.pcap\" \u003e\u003e \"${capout}\" 2\u003e\u00261 \u0026\ndiff --git a/tools/testing/selftests/net/mptcp/mptcp_diag.c b/tools/testing/selftests/net/mptcp/mptcp_diag.c\nindex 5e222ba977e4e..3b8d2c8a62160 100644\n--- a/tools/testing/selftests/net/mptcp/mptcp_diag.c\n+++ b/tools/testing/selftests/net/mptcp/mptcp_diag.c\n@@ -377,7 +377,8 @@ static void get_subflow_info(char *subflow_addrs)\n \tint ret;\n \tint fd;\n \n-\tret = sscanf(subflow_addrs, \"%[^:]:%d %[^:]:%d\", saddr, \u0026sport, daddr, \u0026dport);\n+\tret = sscanf(subflow_addrs, \"%63[^:]:%d %63[^:]:%d\",\n+\t\t     saddr, \u0026sport, daddr, \u0026dport);\n \tif (ret != 4)\n \t\tdie_perror(\"IP PORT Pairs has style problems!\");\n \ndiff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh\nindex 7dc91fac4917e..18ce7136a2b0e 100755\n--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh\n+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh\n@@ -75,6 +75,14 @@ unset join_syn_tx\n unset join_create_err\n unset join_bind_err\n unset join_connect_err\n+unset join_synack_no_mpjoin\n+unset join_ack_no_mpjoin\n+unset join_ack_no_ctx\n+unset join_not_established\n+unset join_no_id_found\n+\n+unset rst_md5sig\n+unset rst_dss\n \n unset fb_ns1\n unset fb_ns2\n@@ -971,7 +979,7 @@ cond_start_capture()\n \t\tcapfile=$(printf \"mp_join-%02u-%s.pcap\" \"$MPTCP_LIB_TEST_COUNTER\" \"$ns\")\n \n \t\techo \"Capturing traffic for test $MPTCP_LIB_TEST_COUNTER into $capfile\"\n-\t\tip netns exec \"$ns\" tcpdump -i any -s 65535 -B 32768 $capuser -w \"$capfile\" \u003e \"$capout\" 2\u003e\u00261 \u0026\n+\t\tip netns exec \"$ns\" tcpdump -i any -s 128 -B 32768 $capuser -w \"$capfile\" \u003e \"$capout\" 2\u003e\u00261 \u0026\n \t\tcappid=$!\n \n \t\tsleep 1\n@@ -1353,6 +1361,8 @@ chk_rst_nr()\n \tlocal rst_tx=$1\n \tlocal rst_rx=$2\n \tlocal ns_invert=${3:-\"\"}\n+\tlocal md5sig=${rst_md5sig:-0}\n+\tlocal dss=${rst_dss:-0}\n \tlocal count\n \tlocal ns_tx=$ns1\n \tlocal ns_rx=$ns2\n@@ -1389,6 +1399,21 @@ chk_rst_nr()\n \telse\n \t\tprint_ok\n \tfi\n+\n+\t# MPTCP_RST_EMPTCP reset-event counters; default 0, gated on\n+\t# availability.  Fixed namespaces: MD5SigReset fires on the listener\n+\t# (server), DssReset on the data receiver (client).\n+\tcount=$(mptcp_lib_get_counter ${ns1} \"MPTcpExtMD5SigReset\")\n+\tif [ -n \"$count\" ] \u0026\u0026 [ \"$count\" != \"$md5sig\" ]; then\n+\t\tprint_check \"MD5SigReset\"\n+\t\tfail_test \"got $count MD5SigReset expected $md5sig\"\n+\tfi\n+\n+\tcount=$(mptcp_lib_get_counter ${ns2} \"MPTcpExtDssReset\")\n+\tif [ -n \"$count\" ] \u0026\u0026 [ \"$count\" != \"$dss\" ]; then\n+\t\tprint_check \"DssReset\"\n+\t\tfail_test \"got $count DssReset expected $dss\"\n+\tfi\n }\n \n chk_infi_nr()\n@@ -1587,6 +1612,11 @@ chk_join_nr()\n \tlocal rst_nr=${join_rst_nr:-0}\n \tlocal infi_nr=${join_infi_nr:-0}\n \tlocal corrupted_pkts=${join_corrupted_pkts:-0}\n+\tlocal synack_no_mpjoin=${join_synack_no_mpjoin:-0}\n+\tlocal ack_no_mpjoin=${join_ack_no_mpjoin:-0}\n+\tlocal ack_no_ctx=${join_ack_no_ctx:-0}\n+\tlocal not_established=${join_not_established:-0}\n+\tlocal no_id_found=${join_no_id_found:-0}\n \tlocal rc=${KSFT_PASS}\n \tlocal count\n \tlocal with_cookie\n@@ -1655,6 +1685,44 @@ chk_join_nr()\n \t\tfail_test \"got $count JOIN[s] syn rejected expected $syn_rej\"\n \tfi\n \n+\t# Per-event MPTCP_RST_EMPTCP JOIN counters; default 0, gated on\n+\t# availability.  Fixed namespaces: the *SynAck* one fires on the\n+\t# client receiving the SYN/ACK, the others on the server.\n+\tcount=$(mptcp_lib_get_counter ${ns2} \"MPTcpExtMPJoinSynAckNoMPJoin\")\n+\tif [ -n \"$count\" ] \u0026\u0026 [ \"$count\" != \"$synack_no_mpjoin\" ]; then\n+\t\trc=${KSFT_FAIL}\n+\t\tprint_check \"synack no mpjoin\"\n+\t\tfail_test \"got $count JOIN[s] synack no mpjoin expected $synack_no_mpjoin\"\n+\tfi\n+\n+\tcount=$(mptcp_lib_get_counter ${ns1} \"MPTcpExtMPJoinAckNoMPJoin\")\n+\tif [ -n \"$count\" ] \u0026\u0026 [ \"$count\" != \"$ack_no_mpjoin\" ]; then\n+\t\trc=${KSFT_FAIL}\n+\t\tprint_check \"ack no mpjoin\"\n+\t\tfail_test \"got $count JOIN[s] ack no mpjoin expected $ack_no_mpjoin\"\n+\tfi\n+\n+\tcount=$(mptcp_lib_get_counter ${ns1} \"MPTcpExtMPJoinAckNoCtx\")\n+\tif [ -n \"$count\" ] \u0026\u0026 [ \"$count\" != \"$ack_no_ctx\" ]; then\n+\t\trc=${KSFT_FAIL}\n+\t\tprint_check \"ack no ctx\"\n+\t\tfail_test \"got $count JOIN[s] ack no ctx expected $ack_no_ctx\"\n+\tfi\n+\n+\tcount=$(mptcp_lib_get_counter ${ns1} \"MPTcpExtMPJoinNotEstablished\")\n+\tif [ -n \"$count\" ] \u0026\u0026 [ \"$count\" != \"$not_established\" ]; then\n+\t\trc=${KSFT_FAIL}\n+\t\tprint_check \"join not established\"\n+\t\tfail_test \"got $count JOIN[s] not established expected $not_established\"\n+\tfi\n+\n+\tcount=$(mptcp_lib_get_counter ${ns1} \"MPTcpExtMPJoinNoIdFound\")\n+\tif [ -n \"$count\" ] \u0026\u0026 [ \"$count\" != \"$no_id_found\" ]; then\n+\t\trc=${KSFT_FAIL}\n+\t\tprint_check \"join no id found\"\n+\t\tfail_test \"got $count JOIN[s] no id found expected $no_id_found\"\n+\tfi\n+\n \tprint_results \"join Rx\" ${rc}\n \n \tjoin_syn_tx=\"${join_syn_tx:-${syn_nr}}\" \\\n@@ -2359,6 +2427,31 @@ signal_address_tests()\n \t\t\tchk_add_nr 4 4\n \t\tfi\n \tfi\n+\n+\t# signalled address belongs to the client, where a TCP-only\n+\t# listener is bound at it: the client's MP_JOIN routes locally\n+\t# to the listener and receives a SYN/ACK without MP_JOIN.\n+\t# MPJoinSynAckNoMPJoin increments on the client side.\n+\tif reset \"signal address, TCP-only listener on client\"; then\n+\t\tlocal extra_bind\n+\t\tlocal port\n+\n+\t\tpm_nl_set_limits $ns1 0 1\n+\t\tpm_nl_set_limits $ns2 1 1\n+\t\tpm_nl_add_endpoint $ns1 10.0.2.2 flags signal\n+\n+\t\tport=$(get_port)\n+\t\tip netns exec ${ns2} ./mptcp_connect -l -t -1 -p \"$port\" \\\n+\t\t\t-s TCP 10.0.2.2 \u0026\n+\t\textra_bind=$!\n+\t\tmptcp_lib_wait_local_port_listen \"$ns2\" \"$port\"\n+\n+\t\trun_tests $ns1 $ns2 10.0.1.1\n+\t\tjoin_synack_no_mpjoin=1 join_syn_tx=1 \\\n+\t\t\tchk_join_nr 0 0 0\n+\n+\t\tkill ${extra_bind} 2\u003e/dev/null\n+\tfi\n }\n \n laminar_endp_tests()\ndiff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh\nindex 7b9aabe101704..3ea3d1efe32e1 100755\n--- a/tools/testing/selftests/net/mptcp/simult_flows.sh\n+++ b/tools/testing/selftests/net/mptcp/simult_flows.sh\n@@ -24,6 +24,7 @@ small=\"\"\n sout=\"\"\n cout=\"\"\n capout=\"\"\n+capprefix=\"\"\n size=0\n \n usage() {\n@@ -70,6 +71,11 @@ setup()\n \n \tmptcp_lib_ns_init ns1 ns2 ns3\n \n+\tif $capture; then\n+\t\tcapprefix=\"simult_flows-${ns1:4}\"\n+\t\tmptcp_lib_pr_info \"pcap will have this prefix: ${capprefix}-\"\n+\tfi\n+\n \tip link add ns1eth1 netns \"$ns1\" type veth peer name ns2eth1 netns \"$ns2\"\n \tip link add ns1eth2 netns \"$ns1\" type veth peer name ns2eth2 netns \"$ns2\"\n \tip link add ns2eth3 netns \"$ns2\" type veth peer name ns3eth1 netns \"$ns3\"\n@@ -136,15 +142,14 @@ do_transfer()\n \n \tif $capture; then\n \t\tlocal capuser\n-\t\tlocal rndh=\"${ns1:4}\"\n \t\tif [ -z $SUDO_USER ] ; then\n \t\t\tcapuser=\"\"\n \t\telse\n \t\t\tcapuser=\"-Z $SUDO_USER\"\n \t\tfi\n \n-\t\tlocal capfile=\"${rndh}-${port}\"\n-\t\tlocal capopt=\"-i any -s 65535 -B 32768 ${capuser}\"\n+\t\tlocal capfile=\"${capprefix}-${port}\"\n+\t\tlocal capopt=\"-i any -s 108 -B 32768 ${capuser}\"\n \n \t\tip netns exec ${ns3}  tcpdump ${capopt} -w \"${capfile}-listener.pcap\"  \u003e\u003e \"${capout}\" 2\u003e\u00261 \u0026\n \t\tlocal cappid_listener=$!\n"
}

2/1 2026/08/12 17:12 agent patch-evaluator
1m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": [
    "MPTCP",
    "MPTCP_IPV6"
  ],
  "FocusSymbols": [
    "mptcp_pm_subflow_check_next",
    "mptcp_pm_nl_remove_doit",
    "mptcp_init_sock",
    "__mptcp_retrans",
    "mptcp_finish_join",
    "__mptcp_subflow_connect"
  ],
  "Reasoning": "The patch introduces functional changes to the MPTCP subsystem. It adds `WARN_ON_ONCE` checks for subflow accounting in `mptcp_pm_subflow_check_next` and `__mptcp_pm_close_subflow` to catch underflows. It also updates the RTO bounds seeding to use sysctl values instead of hardcoded constants, affecting timeout calculations in `__mptcp_init_sock`, `mptcp_set_datafin_timeout`, and `__mptcp_set_timeout`. Additionally, it renames and restricts the scope of `mptcp_userspace_pm_remove_addr_entry`. These changes affect MPTCP connection management and timeout handling, which are reachable and should be fuzzed to ensure the new warnings are not triggered and timeouts behave correctly.",
  "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 acc20b625ef9d5f1a4da68bfbfd9d7b9be77bc07
Author: syz-cluster <triage@syzkaller.com>
Date:   Wed Aug 12 17:12:15 2026 +0000

    syz-cluster: applied patch under review

diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index 71b9fc5a57963..485d55b66ea67 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -19,10 +19,6 @@ struct seq_file;
 
 /* MPTCP sk_buff extension data */
 struct mptcp_ext {
-	union {
-		u64	data_ack;
-		u32	data_ack32;
-	};
 	u64		data_seq;
 	u32		subflow_seq;
 	u16		data_len;
diff --git a/include/trace/events/mptcp.h b/include/trace/events/mptcp.h
index 04521acba4832..22882bd034593 100644
--- a/include/trace/events/mptcp.h
+++ b/include/trace/events/mptcp.h
@@ -75,7 +75,6 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
 	TP_ARGS(mpext),
 
 	TP_STRUCT__entry(
-		__field(u64, data_ack)
 		__field(u64, data_seq)
 		__field(u32, subflow_seq)
 		__field(u16, data_len)
@@ -94,7 +93,6 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
 	),
 
 	TP_fast_assign(
-		__entry->data_ack = mpext->ack64 ? mpext->data_ack : mpext->data_ack32;
 		__entry->data_seq = mpext->data_seq;
 		__entry->subflow_seq = mpext->subflow_seq;
 		__entry->data_len = mpext->data_len;
@@ -112,8 +110,8 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
 		__entry->infinite_map = mpext->infinite_map;
 	),
 
-	TP_printk("data_ack=%llu data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u infinite_map=%u",
-		  __entry->data_ack, __entry->data_seq,
+	TP_printk("data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u infinite_map=%u",
+		  __entry->data_seq,
 		  __entry->subflow_seq, __entry->data_len,
 		  __entry->csum, __entry->use_map,
 		  __entry->dsn64, __entry->data_fin,
diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c
index 2569385bab7ca..608cb568897cf 100644
--- a/net/mptcp/mib.c
+++ b/net/mptcp/mib.c
@@ -21,14 +21,19 @@ static const struct snmp_mib mptcp_snmp_list[] = {
 	SNMP_MIB_ITEM("MPFallbackTokenInit", MPTCP_MIB_TOKENFALLBACKINIT),
 	SNMP_MIB_ITEM("MPTCPRetrans", MPTCP_MIB_RETRANSSEGS),
 	SNMP_MIB_ITEM("MPJoinNoTokenFound", MPTCP_MIB_JOINNOTOKEN),
+	SNMP_MIB_ITEM("MPJoinNoIdFound", MPTCP_MIB_MPJOINNOIDFOUND),
 	SNMP_MIB_ITEM("MPJoinSynRx", MPTCP_MIB_JOINSYNRX),
 	SNMP_MIB_ITEM("MPJoinSynBackupRx", MPTCP_MIB_JOINSYNBACKUPRX),
 	SNMP_MIB_ITEM("MPJoinSynAckRx", MPTCP_MIB_JOINSYNACKRX),
 	SNMP_MIB_ITEM("MPJoinSynAckBackupRx", MPTCP_MIB_JOINSYNACKBACKUPRX),
 	SNMP_MIB_ITEM("MPJoinSynAckHMacFailure", MPTCP_MIB_JOINSYNACKMAC),
+	SNMP_MIB_ITEM("MPJoinSynAckNoMPJoin", MPTCP_MIB_MPJOINSYNACKNOMPJOIN),
 	SNMP_MIB_ITEM("MPJoinAckRx", MPTCP_MIB_JOINACKRX),
 	SNMP_MIB_ITEM("MPJoinAckHMacFailure", MPTCP_MIB_JOINACKMAC),
+	SNMP_MIB_ITEM("MPJoinAckNoMPJoin", MPTCP_MIB_MPJOINACKNOMPJOIN),
+	SNMP_MIB_ITEM("MPJoinAckNoCtx", MPTCP_MIB_MPJOINACKNOCTX),
 	SNMP_MIB_ITEM("MPJoinRejected", MPTCP_MIB_JOINREJECTED),
+	SNMP_MIB_ITEM("MPJoinNotEstablished", MPTCP_MIB_MPJOINNOTESTABLISHED),
 	SNMP_MIB_ITEM("MPJoinSynTx", MPTCP_MIB_JOINSYNTX),
 	SNMP_MIB_ITEM("MPJoinSynTxCreatSkErr", MPTCP_MIB_JOINSYNTXCREATSKERR),
 	SNMP_MIB_ITEM("MPJoinSynTxBindErr", MPTCP_MIB_JOINSYNTXBINDERR),
@@ -81,7 +86,9 @@ static const struct snmp_mib mptcp_snmp_list[] = {
 	SNMP_MIB_ITEM("Blackhole", MPTCP_MIB_BLACKHOLE),
 	SNMP_MIB_ITEM("MPCapableDataFallback", MPTCP_MIB_MPCAPABLEDATAFALLBACK),
 	SNMP_MIB_ITEM("MD5SigFallback", MPTCP_MIB_MD5SIGFALLBACK),
+	SNMP_MIB_ITEM("MD5SigReset", MPTCP_MIB_MD5SIGRESET),
 	SNMP_MIB_ITEM("DssFallback", MPTCP_MIB_DSSFALLBACK),
+	SNMP_MIB_ITEM("DssReset", MPTCP_MIB_DSSRESET),
 	SNMP_MIB_ITEM("SimultConnectFallback", MPTCP_MIB_SIMULTCONNFALLBACK),
 	SNMP_MIB_ITEM("FallbackFailed", MPTCP_MIB_FALLBACKFAILED),
 	SNMP_MIB_ITEM("WinProbe", MPTCP_MIB_WINPROBE),
diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h
index 3a3425e258a76..1ebdb55e95343 100644
--- a/net/mptcp/mib.h
+++ b/net/mptcp/mib.h
@@ -16,14 +16,19 @@ enum linux_mptcp_mib_field {
 	MPTCP_MIB_TOKENFALLBACKINIT,	/* Could not init/allocate token */
 	MPTCP_MIB_RETRANSSEGS,		/* Segments retransmitted at the MPTCP-level */
 	MPTCP_MIB_JOINNOTOKEN,		/* Received MP_JOIN but the token was not found */
+	MPTCP_MIB_MPJOINNOIDFOUND,	/* Received MP_JOIN but no local ID was found */
 	MPTCP_MIB_JOINSYNRX,		/* Received a SYN + MP_JOIN */
 	MPTCP_MIB_JOINSYNBACKUPRX,	/* Received a SYN + MP_JOIN + backup flag */
 	MPTCP_MIB_JOINSYNACKRX,		/* Received a SYN/ACK + MP_JOIN */
 	MPTCP_MIB_JOINSYNACKBACKUPRX,	/* Received a SYN/ACK + MP_JOIN + backup flag */
 	MPTCP_MIB_JOINSYNACKMAC,	/* HMAC was wrong on SYN/ACK + MP_JOIN */
+	MPTCP_MIB_MPJOINSYNACKNOMPJOIN,	/* MP_RST: missing MP_JOIN in SYN/ACK */
 	MPTCP_MIB_JOINACKRX,		/* Received an ACK + MP_JOIN */
 	MPTCP_MIB_JOINACKMAC,		/* HMAC was wrong on ACK + MP_JOIN */
+	MPTCP_MIB_MPJOINACKNOMPJOIN,	/* MP_RST: missing MP_JOIN in ACK */
+	MPTCP_MIB_MPJOINACKNOCTX,	/* MP_RST: no subflow context on ACK */
 	MPTCP_MIB_JOINREJECTED,		/* The PM rejected the JOIN request */
+	MPTCP_MIB_MPJOINNOTESTABLISHED,	/* MP_RST: JOIN on not-fully-established msk */
 	MPTCP_MIB_JOINSYNTX,		/* Sending a SYN + MP_JOIN */
 	MPTCP_MIB_JOINSYNTXCREATSKERR,	/* Not able to create a socket when sending a SYN + MP_JOIN */
 	MPTCP_MIB_JOINSYNTXBINDERR,	/* Not able to bind() the address when sending a SYN + MP_JOIN */
@@ -84,7 +89,9 @@ enum linux_mptcp_mib_field {
 					 * established packet
 					 */
 	MPTCP_MIB_MD5SIGFALLBACK,	/* Conflicting TCP option enabled */
+	MPTCP_MIB_MD5SIGRESET,		/* MP_RST: MD5SIG enabled on listener */
 	MPTCP_MIB_DSSFALLBACK,		/* Bad or missing DSS */
+	MPTCP_MIB_DSSRESET,		/* MP_RST: bad data mapping */
 	MPTCP_MIB_SIMULTCONNFALLBACK,	/* Simultaneous connect */
 	MPTCP_MIB_FALLBACKFAILED,	/* Can't fallback due to msk status */
 	MPTCP_MIB_WINPROBE,		/* MPTCP-level zero window probe */
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index d1f73c3e39fa3..8b68868255c50 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -670,7 +670,8 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk,
 	if (mptcp_pm_is_userspace(msk)) {
 		if (update_subflows) {
 			spin_lock_bh(&pm->lock);
-			pm->extra_subflows--;
+			if (!WARN_ON_ONCE(pm->extra_subflows == 0))
+				pm->extra_subflows--;
 			spin_unlock_bh(&pm->lock);
 		}
 		return;
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index 2203cc2d27485..b94fbb483bf94 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -281,8 +281,9 @@ static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk)
 	return err;
 }
 
-void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
-				struct mptcp_pm_addr_entry *entry)
+static void
+mptcp_userspace_pm_remove_addr_entry(struct mptcp_sock *msk,
+				     struct mptcp_pm_addr_entry *entry)
 {
 	struct mptcp_rm_list alist = { .nr = 0 };
 	int anno_nr = 0;
@@ -340,7 +341,7 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
 	list_del_rcu(&match->list);
 	spin_unlock_bh(&msk->pm.lock);
 
-	mptcp_pm_remove_addr_entry(msk, match);
+	mptcp_userspace_pm_remove_addr_entry(msk, match);
 
 	release_sock(sk);
 
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index ec874d2ead6a4..b474d03620a75 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -581,17 +581,23 @@ static bool mptcp_pending_data_fin(struct sock *sk, u64 *seq)
 static void mptcp_set_datafin_timeout(struct sock *sk)
 {
 	struct inet_connection_sock *icsk = inet_csk(sk);
+	u32 rto_min = READ_ONCE(icsk->icsk_rto_min);
+	u32 rto_max = READ_ONCE(icsk->icsk_rto_max);
 	u32 retransmits;
 
+	/* The sysctls are validated independently: rto_min > rto_max is
+	 * possible, guard against ilog2(0).
+	 */
 	retransmits = min_t(u32, icsk->icsk_retransmits,
-			    ilog2(TCP_RTO_MAX / TCP_RTO_MIN));
+			    ilog2(max_t(u32, rto_max / rto_min, 1)));
 
-	mptcp_sk(sk)->timer_ival = TCP_RTO_MIN << retransmits;
+	mptcp_sk(sk)->timer_ival = rto_min << retransmits;
 }
 
 static void __mptcp_set_timeout(struct sock *sk, long tout)
 {
-	mptcp_sk(sk)->timer_ival = tout > 0 ? tout : TCP_RTO_MIN;
+	mptcp_sk(sk)->timer_ival = tout > 0 ? tout :
+				   READ_ONCE(inet_csk(sk)->icsk_rto_min);
 }
 
 static long mptcp_timeout_from_subflow(const struct mptcp_subflow_context *subflow)
@@ -3161,7 +3167,9 @@ static void mptcp_worker(struct work_struct *work)
 
 static void __mptcp_init_sock(struct sock *sk)
 {
+	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct mptcp_sock *msk = mptcp_sk(sk);
+	struct net *net = sock_net(sk);
 
 	INIT_LIST_HEAD(&msk->conn_list);
 	INIT_LIST_HEAD(&msk->join_list);
@@ -3170,7 +3178,13 @@ static void __mptcp_init_sock(struct sock *sk)
 	INIT_WORK(&msk->work, mptcp_worker);
 	msk->out_of_order_queue = RB_ROOT;
 	msk->first_pending = NULL;
-	msk->timer_ival = TCP_RTO_MIN;
+
+	/* msk does not go through tcp_init_sock(); seed RTO bounds. */
+	icsk->icsk_rto_min =
+		usecs_to_jiffies(READ_ONCE(net->ipv4.sysctl_tcp_rto_min_us));
+	icsk->icsk_rto_max =
+		msecs_to_jiffies(READ_ONCE(net->ipv4.sysctl_tcp_rto_max_ms));
+	msk->timer_ival = icsk->icsk_rto_min;
 	msk->scaling_ratio = TCP_DEFAULT_SCALING_RATIO;
 	msk->backlog_len = 0;
 	mptcp_init_rtt_est(msk);
@@ -3988,6 +4002,7 @@ bool mptcp_finish_join(struct sock *ssk)
 
 	/* mptcp socket already closing? */
 	if (!mptcp_is_fully_established(parent)) {
+		MPTCP_INC_STATS(sock_net(parent), MPTCP_MIB_MPJOINNOTESTABLISHED);
 		subflow->reset_reason = MPTCP_RST_EMPTCP;
 		return false;
 	}
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index b3af3462bdd16..06a107d4e8392 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -1149,8 +1149,6 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 			   const struct mptcp_addr_info *addr,
 			   bool echo);
 int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list);
-void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
-				struct mptcp_pm_addr_entry *entry);
 
 /* the default path manager, used in mptcp_pm_unregister */
 extern struct mptcp_pm_ops mptcp_pm_kernel;
@@ -1254,7 +1252,8 @@ u8 mptcp_pm_get_limit_extra_subflows(const struct mptcp_sock *msk);
 /* called under PM lock */
 static inline void __mptcp_pm_close_subflow(struct mptcp_sock *msk)
 {
-	if (--msk->pm.extra_subflows < mptcp_pm_get_limit_extra_subflows(msk))
+	if (!WARN_ON_ONCE(msk->pm.extra_subflows == 0) &&
+	    --msk->pm.extra_subflows < mptcp_pm_get_limit_extra_subflows(msk))
 		WRITE_ONCE(msk->pm.accept_subflow, true);
 }
 
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index e1f20ff8fdb42..af81ad5e699d1 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -96,6 +96,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req)
 
 	local_id = mptcp_pm_get_local_id(msk, (struct sock_common *)req);
 	if (local_id < 0) {
+		SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPJOINNOIDFOUND);
 		sock_put((struct sock *)msk);
 		return NULL;
 	}
@@ -160,6 +161,7 @@ static int subflow_check_req(struct request_sock *req,
 	 * TCP option space.
 	 */
 	if (rcu_access_pointer(tcp_sk(sk_listener)->md5sig_info)) {
+		MPTCP_INC_STATS(sock_net(sk_listener), MPTCP_MIB_MD5SIGRESET);
 		subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);
 		return -EINVAL;
 	}
@@ -563,6 +565,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
 		u8 hmac[SHA256_DIGEST_SIZE];
 
 		if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_SYNACK)) {
+			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPJOINSYNACKNOMPJOIN);
 			subflow->reset_reason = MPTCP_RST_EMPTCP;
 			goto do_reset;
 		}
@@ -865,6 +868,12 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
 		 */
 		if (!ctx || fallback) {
 			if (fallback_is_fatal) {
+				if (!ctx)
+					MPTCP_INC_STATS(sock_net(sk),
+							MPTCP_MIB_MPJOINACKNOCTX);
+				else
+					MPTCP_INC_STATS(sock_net(sk),
+							MPTCP_MIB_MPJOINACKNOMPJOIN);
 				subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);
 				goto dispose_child;
 			}
@@ -1416,6 +1425,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
 			 * subflow_error_report() will introduce the appropriate barriers
 			 */
 			subflow->reset_transient = 0;
+			MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSRESET);
 			subflow->reset_reason = status == MAPPING_NODSS ?
 						MPTCP_RST_EMIDDLEBOX :
 						MPTCP_RST_EMPTCP;
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index cbe573c4ab3ad..ea4cb6c1bd5e2 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -1264,7 +1264,7 @@ static void apply_cmsg_types(int fd, const struct cfg_cmsg_types *cmsg)
 
 static void parse_cmsg_types(const char *type)
 {
-	char *next = strchr(type, ',');
+	const char *next = strchr(type, ',');
 	unsigned int len = 0;
 
 	cfg_cmsg_types.cmsg_enabled = 1;
@@ -1292,7 +1292,7 @@ static void parse_cmsg_types(const char *type)
 
 static void parse_setsock_options(const char *name)
 {
-	char *next = strchr(name, ',');
+	const char *next = strchr(name, ',');
 	unsigned int len = 0;
 
 	if (next) {
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
index d158678fa6ab0..7a2a851fa0adb 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
@@ -212,8 +212,8 @@ if $checksum; then
 fi
 
 if $capture; then
-	rndh="${ns1:4}"
-	mptcp_lib_pr_info "Packet capture files will have this prefix: ${rndh}-"
+	capprefix="mptcp_connect-${ns1:4}"
+	mptcp_lib_pr_info "pcap will have this prefix: ${capprefix}-"
 fi
 
 set_ethtool_flags() {
@@ -372,8 +372,8 @@ do_transfer()
 			capuser="-Z $SUDO_USER"
 		fi
 
-		local capfile="${rndh}-${connector_ns:0:3}-${listener_ns:0:3}-${cl_proto}-${srv_proto}-${connect_addr}-${port}"
-		local capopt="-i any -s 65535 -B 32768 ${capuser}"
+		local capfile="${capprefix}-${connector_ns:0:3}-${listener_ns:0:3}-${cl_proto}-${srv_proto}-${connect_addr}-${port}"
+		local capopt="-i any -s 128 -B 32768 ${capuser}"
 
 		ip netns exec ${listener_ns} tcpdump ${capopt} \
 			-w "${capfile}-listener.pcap" >> "${capout}" 2>&1 &
diff --git a/tools/testing/selftests/net/mptcp/mptcp_diag.c b/tools/testing/selftests/net/mptcp/mptcp_diag.c
index 5e222ba977e4e..3b8d2c8a62160 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_diag.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_diag.c
@@ -377,7 +377,8 @@ static void get_subflow_info(char *subflow_addrs)
 	int ret;
 	int fd;
 
-	ret = sscanf(subflow_addrs, "%[^:]:%d %[^:]:%d", saddr, &sport, daddr, &dport);
+	ret = sscanf(subflow_addrs, "%63[^:]:%d %63[^:]:%d",
+		     saddr, &sport, daddr, &dport);
 	if (ret != 4)
 		die_perror("IP PORT Pairs has style problems!");
 
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 7dc91fac4917e..18ce7136a2b0e 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -75,6 +75,14 @@ unset join_syn_tx
 unset join_create_err
 unset join_bind_err
 unset join_connect_err
+unset join_synack_no_mpjoin
+unset join_ack_no_mpjoin
+unset join_ack_no_ctx
+unset join_not_established
+unset join_no_id_found
+
+unset rst_md5sig
+unset rst_dss
 
 unset fb_ns1
 unset fb_ns2
@@ -971,7 +979,7 @@ cond_start_capture()
 		capfile=$(printf "mp_join-%02u-%s.pcap" "$MPTCP_LIB_TEST_COUNTER" "$ns")
 
 		echo "Capturing traffic for test $MPTCP_LIB_TEST_COUNTER into $capfile"
-		ip netns exec "$ns" tcpdump -i any -s 65535 -B 32768 $capuser -w "$capfile" > "$capout" 2>&1 &
+		ip netns exec "$ns" tcpdump -i any -s 128 -B 32768 $capuser -w "$capfile" > "$capout" 2>&1 &
 		cappid=$!
 
 		sleep 1
@@ -1353,6 +1361,8 @@ chk_rst_nr()
 	local rst_tx=$1
 	local rst_rx=$2
 	local ns_invert=${3:-""}
+	local md5sig=${rst_md5sig:-0}
+	local dss=${rst_dss:-0}
 	local count
 	local ns_tx=$ns1
 	local ns_rx=$ns2
@@ -1389,6 +1399,21 @@ chk_rst_nr()
 	else
 		print_ok
 	fi
+
+	# MPTCP_RST_EMPTCP reset-event counters; default 0, gated on
+	# availability.  Fixed namespaces: MD5SigReset fires on the listener
+	# (server), DssReset on the data receiver (client).
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMD5SigReset")
+	if [ -n "$count" ] && [ "$count" != "$md5sig" ]; then
+		print_check "MD5SigReset"
+		fail_test "got $count MD5SigReset expected $md5sig"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtDssReset")
+	if [ -n "$count" ] && [ "$count" != "$dss" ]; then
+		print_check "DssReset"
+		fail_test "got $count DssReset expected $dss"
+	fi
 }
 
 chk_infi_nr()
@@ -1587,6 +1612,11 @@ chk_join_nr()
 	local rst_nr=${join_rst_nr:-0}
 	local infi_nr=${join_infi_nr:-0}
 	local corrupted_pkts=${join_corrupted_pkts:-0}
+	local synack_no_mpjoin=${join_synack_no_mpjoin:-0}
+	local ack_no_mpjoin=${join_ack_no_mpjoin:-0}
+	local ack_no_ctx=${join_ack_no_ctx:-0}
+	local not_established=${join_not_established:-0}
+	local no_id_found=${join_no_id_found:-0}
 	local rc=${KSFT_PASS}
 	local count
 	local with_cookie
@@ -1655,6 +1685,44 @@ chk_join_nr()
 		fail_test "got $count JOIN[s] syn rejected expected $syn_rej"
 	fi
 
+	# Per-event MPTCP_RST_EMPTCP JOIN counters; default 0, gated on
+	# availability.  Fixed namespaces: the *SynAck* one fires on the
+	# client receiving the SYN/ACK, the others on the server.
+	count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynAckNoMPJoin")
+	if [ -n "$count" ] && [ "$count" != "$synack_no_mpjoin" ]; then
+		rc=${KSFT_FAIL}
+		print_check "synack no mpjoin"
+		fail_test "got $count JOIN[s] synack no mpjoin expected $synack_no_mpjoin"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinAckNoMPJoin")
+	if [ -n "$count" ] && [ "$count" != "$ack_no_mpjoin" ]; then
+		rc=${KSFT_FAIL}
+		print_check "ack no mpjoin"
+		fail_test "got $count JOIN[s] ack no mpjoin expected $ack_no_mpjoin"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinAckNoCtx")
+	if [ -n "$count" ] && [ "$count" != "$ack_no_ctx" ]; then
+		rc=${KSFT_FAIL}
+		print_check "ack no ctx"
+		fail_test "got $count JOIN[s] ack no ctx expected $ack_no_ctx"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinNotEstablished")
+	if [ -n "$count" ] && [ "$count" != "$not_established" ]; then
+		rc=${KSFT_FAIL}
+		print_check "join not established"
+		fail_test "got $count JOIN[s] not established expected $not_established"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinNoIdFound")
+	if [ -n "$count" ] && [ "$count" != "$no_id_found" ]; then
+		rc=${KSFT_FAIL}
+		print_check "join no id found"
+		fail_test "got $count JOIN[s] no id found expected $no_id_found"
+	fi
+
 	print_results "join Rx" ${rc}
 
 	join_syn_tx="${join_syn_tx:-${syn_nr}}" \
@@ -2359,6 +2427,31 @@ signal_address_tests()
 			chk_add_nr 4 4
 		fi
 	fi
+
+	# signalled address belongs to the client, where a TCP-only
+	# listener is bound at it: the client's MP_JOIN routes locally
+	# to the listener and receives a SYN/ACK without MP_JOIN.
+	# MPJoinSynAckNoMPJoin increments on the client side.
+	if reset "signal address, TCP-only listener on client"; then
+		local extra_bind
+		local port
+
+		pm_nl_set_limits $ns1 0 1
+		pm_nl_set_limits $ns2 1 1
+		pm_nl_add_endpoint $ns1 10.0.2.2 flags signal
+
+		port=$(get_port)
+		ip netns exec ${ns2} ./mptcp_connect -l -t -1 -p "$port" \
+			-s TCP 10.0.2.2 &
+		extra_bind=$!
+		mptcp_lib_wait_local_port_listen "$ns2" "$port"
+
+		run_tests $ns1 $ns2 10.0.1.1
+		join_synack_no_mpjoin=1 join_syn_tx=1 \
+			chk_join_nr 0 0 0
+
+		kill ${extra_bind} 2>/dev/null
+	fi
 }
 
 laminar_endp_tests()
diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh
index 7b9aabe101704..3ea3d1efe32e1 100755
--- a/tools/testing/selftests/net/mptcp/simult_flows.sh
+++ b/tools/testing/selftests/net/mptcp/simult_flows.sh
@@ -24,6 +24,7 @@ small=""
 sout=""
 cout=""
 capout=""
+capprefix=""
 size=0
 
 usage() {
@@ -70,6 +71,11 @@ setup()
 
 	mptcp_lib_ns_init ns1 ns2 ns3
 
+	if $capture; then
+		capprefix="simult_flows-${ns1:4}"
+		mptcp_lib_pr_info "pcap will have this prefix: ${capprefix}-"
+	fi
+
 	ip link add ns1eth1 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"
 	ip link add ns1eth2 netns "$ns1" type veth peer name ns2eth2 netns "$ns2"
 	ip link add ns2eth3 netns "$ns2" type veth peer name ns3eth1 netns "$ns3"
@@ -136,15 +142,14 @@ do_transfer()
 
 	if $capture; then
 		local capuser
-		local rndh="${ns1:4}"
 		if [ -z $SUDO_USER ] ; then
 			capuser=""
 		else
 			capuser="-Z $SUDO_USER"
 		fi
 
-		local capfile="${rndh}-${port}"
-		local capopt="-i any -s 65535 -B 32768 ${capuser}"
+		local capfile="${capprefix}-${port}"
+		local capopt="-i any -s 108 -B 32768 ${capuser}"
 
 		ip netns exec ${ns3}  tcpdump ${capopt} -w "${capfile}-listener.pcap"  >> "${capout}" 2>&1 &
 		local cappid_listener=$!

3/2 2026/08/12 17:12 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 11136
							output: 37
							thoughts: 1204
						

Thoughts:
**MPTCP Patch Analysis and Fuzzing Strategy**

Okay, so this patch is touching a fair bit of the MPTCP subsystem, specifically across several key areas: the headers, MIB (Management Information Base) interactions, path management, and the core protocol logic. My initial assessment is that it's a mix of cleanup, observability improvements, and subtle, but potentially impactful, adjustments to the TCP/MPTCP interaction, specifically regarding timeout calculations.

First, I see the removal of `data_ack` and `data_ack32` from `mptcp_ext` and its tracepoint. This is likely a simplification or refactoring, assuming those fields were either redundant or no longer relevant. These are cosmetic, unlikely to be impactful.

The addition of new SNMP MIB counters is primarily about providing better visibility into MPTCP's internal state. This is good for debugging and monitoring, but the addition itself won't be something to fuzz directly. This is good stuff.

Now, where it gets interesting is the code in `net/mptcp/pm.c` with the added `WARN_ON_ONCE(pm->extra_subflows == 0)` check before decrementing. This is a potential bug trap. This is screaming for fuzzing because it can indicate a problem in how the kernel is tracking subflows. Definitely a high priority area.

The rename of `mptcp_pm_remove_addr_entry` and making it `static` in `pm_userspace.c` is just code hygiene.

The changes in `net/mptcp/protocol.c` are what I'm really focusing on. The shift to using `icsk->icsk_rto_min` and `icsk->icsk_rto_max` (based on system tuning with `sysctl_tcp_rto_min_us` and `sysctl_tcp_rto_max_ms`) instead of hardcoded TCP RTO values in `mptcp_set_datafin_timeout`, `__mptcp_set_timeout` and `__mptcp_init_sock` is a significant change. It's essentially allowing the system administrator to *tune* the MPTCP connection establishment process through the system wide network parameters. This changes the timing of how connections are established which can be good or bad depending on the target network. This is the place to try and generate timing related issues. These RTO changes will likely affect overall connection performance under various network conditions, so this bears closer scrutiny.

The increment of `MPTCP_MIB_MPJOINNOTESTABLISHED` in `mptcp_finish_join` is for monitoring purposes and likely won't affect us.

In `net/mptcp/protocol.h`, the `WARN_ON_ONCE` check is repeated, and `mptcp_pm_remove_addr_entry` has gone away.

The incrementing of various MIB counters in `subflow.c` based on different connection states (e.g., `MPJOINNOIDFOUND`, `MD5SIGRESET`, etc.) is purely for SNMP/MIB reporting and monitoring and is not a priority for fuzzing.

My priorities for fuzzing:

1.  **Triggering the `WARN_ON_ONCE`**: I want to find a way to make `pm->extra_subflows` go to zero unexpectedly before the decrement happens. This likely means corrupting the subflow accounting or causing the removal of an extra subflow. The functions I need to look closely at include `mptcp_pm_subflow_check_next`, `__mptcp_pm_close_subflow` and its callers (`mptcp_pm_close_subflow`, `mptcp_pm_nl_rm_subflow_received`, etc.) since they are related to subflow management.
2.  **Exploring the RTO Bounds Change**: I need to test how the new RTO calculations impact connection establishment under various network conditions. I will focus on `mptcp_set_datafin_timeout`, `__mptcp_set_timeout` and `__mptcp_init_sock`.

I'll be starting by looking into the calls in `net/mptcp/pm.c` and `net/mptcp/protocol.c` to see how the code is accounting for subflows.



4/2 2026/08/12 17:12 tool grepper
0m Args:
{
  "Expression": "__mptcp_pm_close_subflow",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/pm.c=662=void mptcp_pm_subflow_check_next(struct mptcp_sock *msk,\n--\nnet/mptcp/pm.c-684-\tif (update_subflows)\nnet/mptcp/pm.c:685:\t\t__mptcp_pm_close_subflow(msk);\nnet/mptcp/pm.c-686-\n--\nnet/mptcp/protocol.h=1250=u8 mptcp_pm_get_limit_extra_subflows(const struct mptcp_sock *msk);\n--\nnet/mptcp/protocol.h-1252-/* called under PM lock */\nnet/mptcp/protocol.h:1253:static inline void __mptcp_pm_close_subflow(struct mptcp_sock *msk)\nnet/mptcp/protocol.h-1254-{\n--\nnet/mptcp/protocol.h=1260=static inline void mptcp_pm_close_subflow(struct mptcp_sock *msk)\n--\nnet/mptcp/protocol.h-1262-\tspin_lock_bh(\u0026msk-\u003epm.lock);\nnet/mptcp/protocol.h:1263:\t__mptcp_pm_close_subflow(msk);\nnet/mptcp/protocol.h-1264-\tspin_unlock_bh(\u0026msk-\u003epm.lock);\n"
}

5/2 2026/08/12 17:12 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 13693
							output: 36
							thoughts: 59
						

Thoughts:
Okay, here's my breakdown of this.

**Investigating MPTCP Flow Management**

Right, so I'm looking at potential candidates for optimization or troubleshooting within this MPTCP code. From what I've seen, `mptcp_pm_subflow_check_next` and `mptcp_pm_close_subflow` seem like strong starting points. They likely handle the subflow management, which is often a bottleneck. However, before I delve deeper into those, I should also verify the role of timeout mechanisms. I will check both `mptcp_set_datafin_timeout` and `__mptcp_set_timeout` to see if those routines are part of the bottleneck. My goal is to determine if timeouts are contributing to a negative subflow experience.



6/2 2026/08/12 17:12 tool grepper
0m Args:
{
  "Expression": "mptcp_set_datafin_timeout",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/protocol.c=561=static bool mptcp_pending_data_fin(struct sock *sk, u64 *seq)\n--\nnet/mptcp/protocol.c-580-\nnet/mptcp/protocol.c:581:static void mptcp_set_datafin_timeout(struct sock *sk)\nnet/mptcp/protocol.c-582-{\n--\nnet/mptcp/protocol.c=2920=static void __mptcp_retrans(struct sock *sk)\n--\nnet/mptcp/protocol.c-3001-\t\t\t\t   icsk-\u003eicsk_retransmits + 1);\nnet/mptcp/protocol.c:3002:\t\t\tmptcp_set_datafin_timeout(sk);\nnet/mptcp/protocol.c-3003-\t\t\tmptcp_send_ack(msk);\n"
}

7/2 2026/08/12 17:12 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 14196
							output: 34
							thoughts: 37
						

Thoughts:
Here's my summary, as though I'm thinking through this process:

**Diving into MPTCP Retransmission Timeouts**

Okay, so `__mptcp_retrans` is the function that's handling retransmissions in MPTCP, and I see it's calling `mptcp_set_datafin_timeout`. My brain immediately jumps to `__mptcp_set_timeout`, since that seems like the central function to understand timeout configuration in this context. Let's dig into that and see how the timeout mechanisms are really working under the hood. I suspect that understanding how those timeouts are set is key to optimizing performance and diagnosing any congestion-related issues. I'll focus on how `__mptcp_set_timeout` interacts with the different timeout types.



8/2 2026/08/12 17:12 tool grepper
0m Args:
{
  "Expression": "__mptcp_set_timeout",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/protocol.c=581=static void mptcp_set_datafin_timeout(struct sock *sk)\n--\nnet/mptcp/protocol.c-596-\nnet/mptcp/protocol.c:597:static void __mptcp_set_timeout(struct sock *sk, long tout)\nnet/mptcp/protocol.c-598-{\n--\nnet/mptcp/protocol.c=611=static void mptcp_set_timeout(struct sock *sk)\n--\nnet/mptcp/protocol.c-617-\t\ttout = max(tout, mptcp_timeout_from_subflow(subflow));\nnet/mptcp/protocol.c:618:\t__mptcp_set_timeout(sk, tout);\nnet/mptcp/protocol.c-619-}\n--\nnet/mptcp/protocol.c=1587=struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)\n--\nnet/mptcp/protocol.c-1628-\t}\nnet/mptcp/protocol.c:1629:\t__mptcp_set_timeout(sk, tout);\nnet/mptcp/protocol.c-1630-\n"
}

9/2 2026/08/12 17:12 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 14771
							output: 40
							thoughts: 111
						

Thoughts:
**Analyzing MPTCP Timeout and Subflow Management**

Okay, so I'm looking into how timeout mechanisms and subflow management are handled within MPTCP, specifically focusing on potential areas for improvement. It seems that both `mptcp_set_timeout` and `mptcp_subflow_get_send` utilize the `__mptcp_set_timeout` function, which warrants a closer inspection of those calling points. My initial thought is that `mptcp_subflow_get_send` might be a promising starting point for optimization or refactoring. I'll focus on that one for now.

Now, let me shift gears a bit. I need to understand the connection between these two areas, as well as the related functions to the timeout mechanism. I'm going to shift my focus to `mptcp_userspace_pm_remove_addr_entry`. Right, I recall it was originally named `mptcp_pm_remove_addr_entry`, and it has since been made static. That's relevant. I see that it's now called from `mptcp_pm_nl_remove_doit`. I'll want to check that chain of calls, as I'm thinking of how the addresses are being managed.



10/2 2026/08/12 17:12 tool grepper
0m Args:
{
  "Expression": "mptcp_userspace_pm_remove_addr_entry",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/pm_userspace.c=284=static void\nnet/mptcp/pm_userspace.c:285:mptcp_userspace_pm_remove_addr_entry(struct mptcp_sock *msk,\nnet/mptcp/pm_userspace.c-286-\t\t\t\t     struct mptcp_pm_addr_entry *entry)\n--\nnet/mptcp/pm_userspace.c=305=int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)\n--\nnet/mptcp/pm_userspace.c-343-\nnet/mptcp/pm_userspace.c:344:\tmptcp_userspace_pm_remove_addr_entry(msk, match);\nnet/mptcp/pm_userspace.c-345-\n"
}

11/2 2026/08/12 17:12 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15425
							output: 30
							thoughts: 32
						

Thoughts:
Okay, here's my take on those thoughts, framed as an expert's internal monologue:

**Investigating MPTCP Removal**

Right, `mptcp_pm_nl_remove_doit`. That looks like a promising function for handling the removal process of MPTCP. I've seen that name come up in the kernel code before, and based on the naming, it's highly likely it interacts with the netlink interface for managing MPTCP parameters. I'll need to confirm that suspicion, of course, but it's a good place to start digging.

Before I jump too far down that rabbit hole, however, I should probably double-check the system configurations to make sure I'm not missing something obvious. I'll take a quick scan for the essential MPTCP config options that are needed. I need to refresh my memory on the core modules involved and the dependancies they may have. That may quickly clarify if something else is at play, or if there is something else that I should look into.



12/2 2026/08/12 17:12 tool grepper
0m Args:
{
  "Expression": "config MPTCP",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/Kconfig-1-\nnet/mptcp/Kconfig:2:config MPTCP\nnet/mptcp/Kconfig-3-\tbool \"MPTCP: Multipath TCP\"\n--\nnet/mptcp/Kconfig=16=config INET_MPTCP_DIAG\n--\nnet/mptcp/Kconfig-19-\nnet/mptcp/Kconfig:20:config MPTCP_IPV6\nnet/mptcp/Kconfig-21-\tbool \"MPTCP: IPv6 support for Multipath TCP\"\n--\nnet/mptcp/Kconfig-24-\nnet/mptcp/Kconfig:25:config MPTCP_KUNIT_TEST\nnet/mptcp/Kconfig-26-\ttristate \"This builds the MPTCP KUnit tests\" if !KUNIT_ALL_TESTS\n"
}

13/2 2026/08/12 17:12 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15928
							output: 34
							thoughts: 27
						

Thoughts:
Here's my thought process, as if I were considering this myself:

**Diving into the MPTCP Configuration**

Okay, so I'm focusing on `MPTCP` as the central configuration point. Naturally, the first place I'll head is the `net/mptcp/Kconfig` file. I need to understand all the dependencies surrounding this key module. I need to make sure I know *exactly* what other components it relies on, and what other configurations might need to be in place for `MPTCP` to function properly. This Kconfig file should illuminate those relationships pretty clearly. Time to dig in and get a handle on the bigger picture.



14/2 2026/08/12 17:12 tool read-file
0m Args:
{
  "File": "net/mptcp/Kconfig",
  "FirstLine": 1,
  "LineCount": 20
}

Results:
{
  "Contents": "   1:\t\n   2:\tconfig MPTCP\n   3:\t\tbool \"MPTCP: Multipath TCP\"\n   4:\t\tdepends on INET\n   5:\t\tselect SKB_EXTENSIONS\n   6:\t\tselect CRYPTO_LIB_SHA256\n   7:\t\tselect CRYPTO_LIB_UTILS\n   8:\t\thelp\n   9:\t\t  Multipath TCP (MPTCP) connections send and receive data over multiple\n  10:\t\t  subflows in order to utilize multiple network paths. Each subflow\n  11:\t\t  uses the TCP protocol, and TCP options carry header information for\n  12:\t\t  MPTCP.\n  13:\t\n  14:\tif MPTCP\n  15:\t\n  16:\tconfig INET_MPTCP_DIAG\n  17:\t\tdepends on INET_DIAG\n  18:\t\tdef_tristate INET_DIAG\n  19:\t\n  20:\tconfig MPTCP_IPV6\n"
}

15/2 2026/08/12 17:12 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 16378
							output: 36
							thoughts: 182
						

Thoughts:
**Fuzzing the MPTCP Configuration**

Okay, so I'm looking at this `MPTCP` configuration, and the patch details some functional changes. Things like RTO bounds and `WARN_ON_ONCE` really pique my interest – those are definitely worth a fuzzing campaign.

I've identified some key symbols to target: `mptcp_pm_subflow_check_next`, `mptcp_pm_close_subflow`, `mptcp_pm_nl_remove_doit`, `mptcp_subflow_get_send`, and `__mptcp_retrans`. These look like prime candidates for exposing subtle bugs.

Now, let me just quickly verify if `mptcp_pm_close_subflow` is defined as `static inline`. Ah, yes, it's right here in `protocol.h`. That means I can't fuzz it directly, as the compiler will likely substitute its functionality at the call site. Not ideal, but I'll make a note of that limitation.

Alright, if `mptcp_pm_close_subflow` is off the table, what about `mptcp_pm_nl_rm_subflow_received`? That might be a more promising entry point. Let's see...



16/2 2026/08/12 17:12 tool grepper
0m Args:
{
  "Expression": "mptcp_pm_close_subflow",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/pm.c=662=void mptcp_pm_subflow_check_next(struct mptcp_sock *msk,\n--\nnet/mptcp/pm.c-684-\tif (update_subflows)\nnet/mptcp/pm.c:685:\t\t__mptcp_pm_close_subflow(msk);\nnet/mptcp/pm.c-686-\n--\nnet/mptcp/protocol.c=3994=bool mptcp_finish_join(struct sock *ssk)\n--\nnet/mptcp/protocol.c-4053-\tif (!ret) {\nnet/mptcp/protocol.c:4054:\t\tmptcp_pm_close_subflow(msk);\nnet/mptcp/protocol.c-4055-err_prohibited:\n--\nnet/mptcp/protocol.h=1250=u8 mptcp_pm_get_limit_extra_subflows(const struct mptcp_sock *msk);\n--\nnet/mptcp/protocol.h-1252-/* called under PM lock */\nnet/mptcp/protocol.h:1253:static inline void __mptcp_pm_close_subflow(struct mptcp_sock *msk)\nnet/mptcp/protocol.h-1254-{\n--\nnet/mptcp/protocol.h-1259-\nnet/mptcp/protocol.h:1260:static inline void mptcp_pm_close_subflow(struct mptcp_sock *msk)\nnet/mptcp/protocol.h-1261-{\nnet/mptcp/protocol.h-1262-\tspin_lock_bh(\u0026msk-\u003epm.lock);\nnet/mptcp/protocol.h:1263:\t__mptcp_pm_close_subflow(msk);\nnet/mptcp/protocol.h-1264-\tspin_unlock_bh(\u0026msk-\u003epm.lock);\n--\nnet/mptcp/subflow.c=1618=int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_pm_local *local,\n--\nnet/mptcp/subflow.c-1723-\t */\nnet/mptcp/subflow.c:1724:\tmptcp_pm_close_subflow(msk);\nnet/mptcp/subflow.c-1725-\treturn err;\n"
}

17/2 2026/08/12 17:12 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 17510
							output: 38
							thoughts: 83
						

Thoughts:
Here's my thought process, as it stands:

**Focusing In on MPTCP Subflow Connection**

Okay, so I'm honing in on the MPTCP connection process. I need to zero in on specific points in the code. My immediate focus needs to be on the `mptcp_finish_join` and `__mptcp_subflow_connect` functions. These seem like critical points in the subflow joining process, and will allow me to have a more granular understanding. I'll add these to the list of focus symbols.

I'll also keep in mind `mptcp_pm_subflow_check_next` since it looks like an important function within the overall flow and is probably something related to selecting and validating the next subflow.

In addition, since I'm concerned about connection/disconnection issues, I should also check `mptcp_pm_nl_remove_doit`. I'll need to understand how subflows are removed as well, to be able to have a full understanding of the process.



18/2 2026/08/12 17:13 tool grepper
0m Args:
{
  "Expression": "mptcp_pm_nl_remove_doit",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/mptcp_pm_gen.c=92=const struct genl_ops mptcp_pm_nl_ops[11] = {\n--\nnet/mptcp/mptcp_pm_gen.c-158-\t\t.validate\t= GENL_DONT_VALIDATE_STRICT,\nnet/mptcp/mptcp_pm_gen.c:159:\t\t.doit\t\t= mptcp_pm_nl_remove_doit,\nnet/mptcp/mptcp_pm_gen.c-160-\t\t.policy\t\t= mptcp_pm_remove_nl_policy,\n--\nnet/mptcp/mptcp_pm_gen.h=52=int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info);\nnet/mptcp/mptcp_pm_gen.h:53:int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info);\nnet/mptcp/mptcp_pm_gen.h-54-int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb,\n--\nnet/mptcp/pm_userspace.c=285=mptcp_userspace_pm_remove_addr_entry(struct mptcp_sock *msk,\n--\nnet/mptcp/pm_userspace.c-304-\nnet/mptcp/pm_userspace.c:305:int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)\nnet/mptcp/pm_userspace.c-306-{\n"
}

19/2 2026/08/12 17:13 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 18305
							output: 36
							thoughts: 45
						

Thoughts:
Okay, here's my interpretation of those thoughts, framed as my own:

**Analyzing a Netlink Callback and Subflow Handling**

Right, `mptcp_pm_nl_remove_doit`. That's a netlink `doit` callback, specifically for a "remove" operation, which means it deals with deleting something. Netlink callbacks are often where you can start digging to find core functionality. It seems like a good place to start my investigation.

My next step, and this is where I would start, is to check `mptcp_subflow_get_send`. The goal, in context, is to determine which processes interact. Since `mptcp_pm_nl_remove_doit` is involved in removing something, it stands to reason that `mptcp_subflow_get_send` might be involved.



20/2 2026/08/12 17:13 tool grepper
0m Args:
{
  "Expression": "mptcp_subflow_get_send",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/protocol.c=1566=bool mptcp_subflow_active(struct mptcp_subflow_context *subflow)\n--\nnet/mptcp/protocol.c-1586- */\nnet/mptcp/protocol.c:1587:struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)\nnet/mptcp/protocol.c-1588-{\n--\nnet/mptcp/protocol.c-1606-\nnet/mptcp/protocol.c:1607:\t\ttrace_mptcp_subflow_get_send(subflow);\nnet/mptcp/protocol.c-1608-\t\tssk =  mptcp_subflow_tcp_sock(subflow);\n--\nnet/mptcp/protocol.h=857=void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow,\nnet/mptcp/protocol.h-858-\t\t\t\t bool scheduled);\nnet/mptcp/protocol.h:859:struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk);\nnet/mptcp/protocol.h-860-struct sock *mptcp_subflow_get_retrans(struct mptcp_sock *msk);\n--\nnet/mptcp/sched.c=19=static int mptcp_sched_default_get_send(struct mptcp_sock *msk)\n--\nnet/mptcp/sched.c-22-\nnet/mptcp/sched.c:23:\tssk = mptcp_subflow_get_send(msk);\nnet/mptcp/sched.c-24-\tif (!ssk)\n--\nnet/mptcp/sched.c=168=int mptcp_sched_get_send(struct mptcp_sock *msk)\n--\nnet/mptcp/sched.c-173-\nnet/mptcp/sched.c:174:\t/* the following check is moved out of mptcp_subflow_get_send */\nnet/mptcp/sched.c-175-\tif (__mptcp_check_fallback(msk)) {\n"
}

21/2 2026/08/12 17:13 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 19139
							output: 33
							thoughts: 60
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own reasoning:

**Analyzing MPTCP Subflow Scheduling**

Alright, I'm digging into how MPTCP subflows are managed for sending data. It looks like `mptcp_subflow_get_send` is the key function here, called directly from `mptcp_sched_default_get_send`. That makes sense; the default scheduler likely needs to get a subflow to actually *do* the sending. Then, let me think a moment, `mptcp_sched_get_send` seems like another likely function for me to look into, if I want to dive further into the scheduling process.

But, before I get lost in the broader scheduling logic, a quick check on `__mptcp_retrans` seems essential. Retransmissions can significantly affect subflow selection and prioritization. It's often where the rubber meets the road in terms of performance and reliability, so understanding how retransmissions are handled relative to subflow selection is likely very important. I need to be sure any analysis considers that. I'll make a note to come back to that.



22/2 2026/08/12 17:13 tool grepper
0m Args:
{
  "Expression": "__mptcp_retrans",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/pm.c=1070=mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)\n--\nnet/mptcp/pm.c-1091-\t\t\t\tsubflow-\u003estale = 1;\nnet/mptcp/pm.c:1092:\t\t\t\t__mptcp_retransmit_pending_data(sk);\nnet/mptcp/pm.c-1093-\t\t\t\tMPTCP_INC_STATS(net, MPTCP_MIB_SUBFLOWSTALE);\n--\nnet/mptcp/protocol.c=2519=struct sock *mptcp_subflow_get_retrans(struct mptcp_sock *msk)\n--\nnet/mptcp/protocol.c-2553-\nnet/mptcp/protocol.c:2554:bool __mptcp_retransmit_pending_data(struct sock *sk)\nnet/mptcp/protocol.c-2555-{\n--\nnet/mptcp/protocol.c=2638=static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,\n--\nnet/mptcp/protocol.c-2687-\nnet/mptcp/protocol.c:2688:\tneed_push = (flags \u0026 MPTCP_CF_PUSH) \u0026\u0026 __mptcp_retransmit_pending_data(sk);\nnet/mptcp/protocol.c-2689-\tif (!dispose_it) {\n--\nnet/mptcp/protocol.c=2858=static int __mptcp_push_retrans(struct sock *sk, struct mptcp_data_frag *dfrag,\n--\nnet/mptcp/protocol.c-2919-\nnet/mptcp/protocol.c:2920:static void __mptcp_retrans(struct sock *sk)\nnet/mptcp/protocol.c-2921-{\n--\nnet/mptcp/protocol.c-2946-\t\t/* `already_sent` can be 0 for `dfrag` belonging to the RTX\nnet/mptcp/protocol.c:2947:\t\t *  queue due to __mptcp_retransmit_pending_data().\nnet/mptcp/protocol.c-2948-\t\t */\n--\nnet/mptcp/protocol.c=3119=static void mptcp_worker(struct work_struct *work)\n--\nnet/mptcp/protocol.c-3156-\tif (test_and_clear_bit(MPTCP_WORK_RTX, \u0026msk-\u003eflags))\nnet/mptcp/protocol.c:3157:\t\t__mptcp_retrans(sk);\nnet/mptcp/protocol.c-3158-\n--\nnet/mptcp/protocol.c=3807=static void mptcp_release_cb(struct sock *sk)\n--\nnet/mptcp/protocol.c-3839-\t\tif (flags \u0026 BIT(MPTCP_RETRANSMIT))\nnet/mptcp/protocol.c:3840:\t\t\t__mptcp_retrans(sk);\nnet/mptcp/protocol.c-3841-\t\tif (spool_bl \u0026\u0026 __mptcp_move_skbs(sk, \u0026skbs, \u0026moved)) {\n--\nnet/mptcp/protocol.h=813=void __mptcp_subflow_fully_established(struct mptcp_sock *msk,\n--\nnet/mptcp/protocol.h-815-\t\t\t\t       const struct mptcp_options_received *mp_opt);\nnet/mptcp/protocol.h:816:bool __mptcp_retransmit_pending_data(struct sock *sk);\nnet/mptcp/protocol.h-817-void mptcp_check_and_set_pending(struct sock *sk);\n"
}

23/2 2026/08/12 17:13 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 20464
							output: 34
							thoughts: 29
						

Thoughts:
Okay, here's my take on those thoughts, framed as an expert's internal monologue:

**Investigating a Retransmission Opportunity**

Alright, let's see... looking at the MPTCP code, `__mptcp_retrans` immediately feels like a solid starting point. It's often where the core retransmission logic lives, so it's probably where I'll find the most relevant context for this.

But, before I get too deep in there, let me just quickly glance at `__mptcp_init_sock`. Gotta make sure I'm not missing something fundamental about the socket initialization process. Retransmissions are obviously dependent on proper socket setup, so understanding the initial state is crucial for identifying any potential issues. It might be that the root cause lies in how the socket is being configured. A quick review can save me a lot of time later.



24/2 2026/08/12 17:13 tool grepper
0m Args:
{
  "Expression": "__mptcp_init_sock",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/protocol.c=3119=static void mptcp_worker(struct work_struct *work)\n--\nnet/mptcp/protocol.c-3167-\nnet/mptcp/protocol.c:3168:static void __mptcp_init_sock(struct sock *sk)\nnet/mptcp/protocol.c-3169-{\n--\nnet/mptcp/protocol.c=3224=static int mptcp_init_sock(struct sock *sk)\n--\nnet/mptcp/protocol.c-3228-\nnet/mptcp/protocol.c:3229:\t__mptcp_init_sock(sk);\nnet/mptcp/protocol.c-3230-\n--\nnet/mptcp/protocol.c-3245-\nnet/mptcp/protocol.c:3246:\t/* fetch the ca name; do it outside __mptcp_init_sock(), so that clone will\nnet/mptcp/protocol.c-3247-\t * propagate the correct value\n--\nnet/mptcp/protocol.c=3696=struct sock *mptcp_sk_clone_init(const struct sock *sk,\n--\nnet/mptcp/protocol.c-3713-\nnet/mptcp/protocol.c:3714:\t__mptcp_init_sock(nsk);\nnet/mptcp/protocol.c-3715-\n"
}

25/2 2026/08/12 17:13 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 21097
							output: 38
							thoughts: 67
						

Thoughts:
Here's my summary, as though I'm thinking through this process:

**Diving into MPTCP Socket Initialization**

Okay, so I'm looking at how MPTCP sockets are initialized. From the code, it seems pretty clear that both `mptcp_init_sock` and `mptcp_sk_clone_init` ultimately rely on a common function: `__mptcp_init_sock`. That makes sense; centralizing the core initialization logic reduces redundancy and likely improves maintainability. `mptcp_init_sock` is specifically tagged as the socket init function, as the name suggests.

Now, I need to understand how the subflows are handled. The next thing I need to investigate is `mptcp_pm_subflow_check_next`. This sounds critical for determining which subflow to use.



26/2 2026/08/12 17:13 tool grepper
0m Args:
{
  "Expression": "mptcp_pm_subflow_check_next",
  "PathPrefix": "net/mptcp/"
}

Results:
{
  "Output": "net/mptcp/pm.c=645=void mptcp_pm_subflow_established(struct mptcp_sock *msk)\n--\nnet/mptcp/pm.c-661-\nnet/mptcp/pm.c:662:void mptcp_pm_subflow_check_next(struct mptcp_sock *msk,\nnet/mptcp/pm.c-663-\t\t\t\t const struct mptcp_subflow_context *subflow)\n--\nnet/mptcp/protocol.c=2744=void mptcp_close_ssk(struct sock *sk, struct sock *ssk,\n--\nnet/mptcp/protocol.c-2758-\t */\nnet/mptcp/protocol.c:2759:\tmptcp_pm_subflow_check_next(mptcp_sk(sk), subflow);\nnet/mptcp/protocol.c-2760-\n--\nnet/mptcp/protocol.h=1115=bool mptcp_pm_nl_check_work_pending(struct mptcp_sock *msk);\nnet/mptcp/protocol.h:1116:void mptcp_pm_subflow_check_next(struct mptcp_sock *msk,\nnet/mptcp/protocol.h-1117-\t\t\t\t const struct mptcp_subflow_context *subflow);\n"
}

27/2 2026/08/12 17:13 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 21742
							output: 34
							thoughts: 323
						

Thoughts:
**My Analysis of MPTCP Code Reachability and Configuration**

Okay, so I'm looking at how we can analyze the reachability of these core MPTCP functions. My initial thought is that `mptcp_pm_subflow_check_next` gets called from `mptcp_close_ssk`, so that's a good starting point. I need to understand how these different parts of the code connect.

The key symbols I'm focusing on are: `mptcp_pm_subflow_check_next`, `mptcp_pm_nl_remove_doit`, `mptcp_finish_join`, `__mptcp_retrans`, and `mptcp_init_sock`.

Let's see: `mptcp_pm_nl_remove_doit` is reachable through the netlink interface, that makes sense. `mptcp_pm_subflow_check_next` is directly related to closing subflows, which is important. `mptcp_finish_join` is triggered when a join is completed. `__mptcp_retrans` is definitely called on retransmissions, a crucial function. And finally, `mptcp_init_sock` is called when we create an MPTCP socket.

Now, for configuration, obviously, `MPTCP` is the big one. I need to verify that it's sufficient to build and test these features. Ah, right, `MPTCP` depends on `INET` which I knew, and `MPTCP_IPV6` would be useful for IPv6 testing, so I'll be including `MPTCP` and `MPTCP_IPV6`.

Just to be thorough, I'll quickly double-check `net/mptcp/Kconfig` to make sure I haven't missed any other potentially important configuration options. That's always a good idea.



28/2 2026/08/12 17:13 tool read-file
0m Args:
{
  "File": "net/mptcp/Kconfig",
  "FirstLine": 1,
  "LineCount": 50
}

Results:
{
  "Contents": "   1:\t\n   2:\tconfig MPTCP\n   3:\t\tbool \"MPTCP: Multipath TCP\"\n   4:\t\tdepends on INET\n   5:\t\tselect SKB_EXTENSIONS\n   6:\t\tselect CRYPTO_LIB_SHA256\n   7:\t\tselect CRYPTO_LIB_UTILS\n   8:\t\thelp\n   9:\t\t  Multipath TCP (MPTCP) connections send and receive data over multiple\n  10:\t\t  subflows in order to utilize multiple network paths. Each subflow\n  11:\t\t  uses the TCP protocol, and TCP options carry header information for\n  12:\t\t  MPTCP.\n  13:\t\n  14:\tif MPTCP\n  15:\t\n  16:\tconfig INET_MPTCP_DIAG\n  17:\t\tdepends on INET_DIAG\n  18:\t\tdef_tristate INET_DIAG\n  19:\t\n  20:\tconfig MPTCP_IPV6\n  21:\t\tbool \"MPTCP: IPv6 support for Multipath TCP\"\n  22:\t\tdepends on IPV6=y\n  23:\t\tdefault y\n  24:\t\n  25:\tconfig MPTCP_KUNIT_TEST\n  26:\t\ttristate \"This builds the MPTCP KUnit tests\" if !KUNIT_ALL_TESTS\n  27:\t\tdepends on KUNIT\n  28:\t\tdefault KUNIT_ALL_TESTS\n  29:\t\thelp\n  30:\t\t  Currently covers the MPTCP crypto and token helpers.\n  31:\t\t  Only useful for kernel devs running KUnit test harness and are not\n  32:\t\t  for inclusion into a production build.\n  33:\t\n  34:\t\t  For more information on KUnit and unit tests in general please refer\n  35:\t\t  to the KUnit documentation in Documentation/dev-tools/kunit/.\n  36:\t\n  37:\t\t  If unsure, say N.\n  38:\t\n  39:\tendif\n"
}

29/2 2026/08/12 17:13 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 23007
							output: 291
							thoughts: 1509
						

Thoughts:
**MPTCP Patch Analysis: Functional Changes and Fuzzing Strategy**

Okay, so I'm looking at this MPTCP patch. The main configurations affected are `MPTCP` and `MPTCP_IPV6`, so that's the scope to keep in mind. Let's break down the implications.

First, there are a few functional changes that stick out. The patch introduces `WARN_ON_ONCE` checks for `extra_subflows` in `mptcp_pm_subflow_check_next` and the static inline `mptcp_pm_close_subflow` which is called from  `mptcp_finish_join` and `__mptcp_subflow_connect`. This suggests the patch is trying to harden subflow accounting, specifically when the number of extra subflows might be inconsistent with the current state. This is critical. We need to fuzz these conditions to make sure these new warnings don't fire spuriously under normal or even adversarial conditions.

Then, there's a subtle but important change to how RTO bounds are seeded. The patch modifies `__mptcp_init_sock`,  `mptcp_set_datafin_timeout` (which is called by `__mptcp_retrans`) and `__mptcp_set_timeout` to utilize sysctl values for `icsk_rto_min` and `icsk_rto_max` instead of the previous hardcoded values. This is likely aimed at improving adaptability to different network conditions and reducing the chances of overly aggressive or conservative retransmissions. This changes the behaviour of the MPTCP connection establishment process. We need to fuzz timeout behavior to verify the new sysctl values are appropriately integrated and that retransmission timeouts are behaving correctly under different network conditions.

There's also a renaming and scoping change: `mptcp_userspace_pm_remove_addr_entry` is renamed and made static, and can now be reached through `mptcp_pm_nl_remove_doit`. This is less critical but still needs attention during fuzzing.

Beyond these core functional shifts, there are new SNMP counters incremented in functions like `subflow_token_join_request`, `subflow_check_req`, `subflow_finish_connect`, `subflow_syn_recv_sock`, and `subflow_check_data_avail`. While these counters themselves aren't functional in the traditional sense, they do indicate that the patch touches on various connection establishment edge cases. The paths are already covered in MPTCP connection fuzzing, so we can focus on the core functional changes first. The new counters could inform future fuzzing campaigns targeting specific edge cases, but for now, they are mostly informative.

So, in summary, I'm focusing on the following:
*   `mptcp_pm_subflow_check_next` and `mptcp_pm_nl_remove_doit`: Because these trigger the new `WARN_ON_ONCE` checks in subflow management.
*   `mptcp_init_sock`: As the initial RTO value settings are now affected.
*   `__mptcp_retrans`: As the RTO settings affect the datafin timeout which is related to retransmissions.
*   `mptcp_finish_join` and `__mptcp_subflow_connect`: As these now call the `WARN_ON_ONCE`-triggering function.

I need to design fuzzing campaigns that specifically target these areas to confirm the new warnings are not triggered spuriously and that the RTO changes behave as expected under a variety of network conditions and edge cases. These are the key attack surfaces introduced by the patch.



30/2 2026/08/12 17:13 tool set-results
0m Args:
{
  "EnableConfigs": [
    "MPTCP",
    "MPTCP_IPV6"
  ],
  "FocusSymbols": [
    "mptcp_pm_subflow_check_next",
    "mptcp_pm_nl_remove_doit",
    "mptcp_init_sock",
    "__mptcp_retrans",
    "mptcp_finish_join",
    "__mptcp_subflow_connect"
  ],
  "Reasoning": "The patch introduces functional changes to the MPTCP subsystem. It adds `WARN_ON_ONCE` checks for subflow accounting in `mptcp_pm_subflow_check_next` and `__mptcp_pm_close_subflow` to catch underflows. It also updates the RTO bounds seeding to use sysctl values instead of hardcoded constants, affecting timeout calculations in `__mptcp_init_sock`, `mptcp_set_datafin_timeout`, and `__mptcp_set_timeout`. Additionally, it renames and restricts the scope of `mptcp_userspace_pm_remove_addr_entry`. These changes affect MPTCP connection management and timeout handling, which are reachable and should be fuzzed to ensure the new warnings are not triggered and timeouts behave correctly.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "MPTCP",
    "MPTCP_IPV6"
  ],
  "FocusSymbols": [
    "mptcp_pm_subflow_check_next",
    "mptcp_pm_nl_remove_doit",
    "mptcp_init_sock",
    "__mptcp_retrans",
    "mptcp_finish_join",
    "__mptcp_subflow_connect"
  ],
  "Reasoning": "The patch introduces functional changes to the MPTCP subsystem. It adds `WARN_ON_ONCE` checks for subflow accounting in `mptcp_pm_subflow_check_next` and `__mptcp_pm_close_subflow` to catch underflows. It also updates the RTO bounds seeding to use sysctl values instead of hardcoded constants, affecting timeout calculations in `__mptcp_init_sock`, `mptcp_set_datafin_timeout`, and `__mptcp_set_timeout`. Additionally, it renames and restricts the scope of `mptcp_userspace_pm_remove_addr_entry`. These changes affect MPTCP connection management and timeout handling, which are reachable and should be fuzzed to ensure the new warnings are not triggered and timeouts behave correctly.",
  "WorthFuzzing": true
}

31/1 2026/08/12 17:13 action If
0m Args:
{
  "WorthFuzzing": true
}

Results:
null

32/2 2026/08/12 17:13 agent kmsan-evaluator
0m Model:
best-expensive

Args:
null

Results:
{
  "KMSANReasoning": "The patch series primarily focuses on:\n1. Removing the unused `data_ack` field from `struct mptcp_ext` and the corresponding `mptcp_dump_mpext` trace event.\n2. Adding new SNMP MIB counters for various MPTCP events (e.g., MP_JOIN failures, resets) and incrementing them in the appropriate error paths.\n3. Adding underflow checks (`WARN_ON_ONCE`) for `pm-\u003eextra_subflows`.\n4. Seeding RTO bounds (`icsk_rto_min`, `icsk_rto_max`) during MPTCP socket initialization.\n\nNone of these changes introduce new structures copied to user space, new buffer allocations, or complex conditional logic that could expose uninitialized memory. The removal of fields from the trace event and skb extension reduces the memory footprint, and the RTO bounds initialization ensures fields are properly seeded. Any potential bugs introduced by these changes (e.g., logic errors, out-of-bounds) would be adequately caught by standard KASAN and other default sanitizers. There is no risk of uninitialized memory usage or info-leaks that would necessitate a dedicated KMSAN fuzzing session.",
  "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 acc20b625ef9d5f1a4da68bfbfd9d7b9be77bc07
Author: syz-cluster <triage@syzkaller.com>
Date:   Wed Aug 12 17:12:15 2026 +0000

    syz-cluster: applied patch under review

diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index 71b9fc5a57963..485d55b66ea67 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -19,10 +19,6 @@ struct seq_file;
 
 /* MPTCP sk_buff extension data */
 struct mptcp_ext {
-	union {
-		u64	data_ack;
-		u32	data_ack32;
-	};
 	u64		data_seq;
 	u32		subflow_seq;
 	u16		data_len;
diff --git a/include/trace/events/mptcp.h b/include/trace/events/mptcp.h
index 04521acba4832..22882bd034593 100644
--- a/include/trace/events/mptcp.h
+++ b/include/trace/events/mptcp.h
@@ -75,7 +75,6 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
 	TP_ARGS(mpext),
 
 	TP_STRUCT__entry(
-		__field(u64, data_ack)
 		__field(u64, data_seq)
 		__field(u32, subflow_seq)
 		__field(u16, data_len)
@@ -94,7 +93,6 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
 	),
 
 	TP_fast_assign(
-		__entry->data_ack = mpext->ack64 ? mpext->data_ack : mpext->data_ack32;
 		__entry->data_seq = mpext->data_seq;
 		__entry->subflow_seq = mpext->subflow_seq;
 		__entry->data_len = mpext->data_len;
@@ -112,8 +110,8 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
 		__entry->infinite_map = mpext->infinite_map;
 	),
 
-	TP_printk("data_ack=%llu data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u infinite_map=%u",
-		  __entry->data_ack, __entry->data_seq,
+	TP_printk("data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u infinite_map=%u",
+		  __entry->data_seq,
 		  __entry->subflow_seq, __entry->data_len,
 		  __entry->csum, __entry->use_map,
 		  __entry->dsn64, __entry->data_fin,
diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c
index 2569385bab7ca..608cb568897cf 100644
--- a/net/mptcp/mib.c
+++ b/net/mptcp/mib.c
@@ -21,14 +21,19 @@ static const struct snmp_mib mptcp_snmp_list[] = {
 	SNMP_MIB_ITEM("MPFallbackTokenInit", MPTCP_MIB_TOKENFALLBACKINIT),
 	SNMP_MIB_ITEM("MPTCPRetrans", MPTCP_MIB_RETRANSSEGS),
 	SNMP_MIB_ITEM("MPJoinNoTokenFound", MPTCP_MIB_JOINNOTOKEN),
+	SNMP_MIB_ITEM("MPJoinNoIdFound", MPTCP_MIB_MPJOINNOIDFOUND),
 	SNMP_MIB_ITEM("MPJoinSynRx", MPTCP_MIB_JOINSYNRX),
 	SNMP_MIB_ITEM("MPJoinSynBackupRx", MPTCP_MIB_JOINSYNBACKUPRX),
 	SNMP_MIB_ITEM("MPJoinSynAckRx", MPTCP_MIB_JOINSYNACKRX),
 	SNMP_MIB_ITEM("MPJoinSynAckBackupRx", MPTCP_MIB_JOINSYNACKBACKUPRX),
 	SNMP_MIB_ITEM("MPJoinSynAckHMacFailure", MPTCP_MIB_JOINSYNACKMAC),
+	SNMP_MIB_ITEM("MPJoinSynAckNoMPJoin", MPTCP_MIB_MPJOINSYNACKNOMPJOIN),
 	SNMP_MIB_ITEM("MPJoinAckRx", MPTCP_MIB_JOINACKRX),
 	SNMP_MIB_ITEM("MPJoinAckHMacFailure", MPTCP_MIB_JOINACKMAC),
+	SNMP_MIB_ITEM("MPJoinAckNoMPJoin", MPTCP_MIB_MPJOINACKNOMPJOIN),
+	SNMP_MIB_ITEM("MPJoinAckNoCtx", MPTCP_MIB_MPJOINACKNOCTX),
 	SNMP_MIB_ITEM("MPJoinRejected", MPTCP_MIB_JOINREJECTED),
+	SNMP_MIB_ITEM("MPJoinNotEstablished", MPTCP_MIB_MPJOINNOTESTABLISHED),
 	SNMP_MIB_ITEM("MPJoinSynTx", MPTCP_MIB_JOINSYNTX),
 	SNMP_MIB_ITEM("MPJoinSynTxCreatSkErr", MPTCP_MIB_JOINSYNTXCREATSKERR),
 	SNMP_MIB_ITEM("MPJoinSynTxBindErr", MPTCP_MIB_JOINSYNTXBINDERR),
@@ -81,7 +86,9 @@ static const struct snmp_mib mptcp_snmp_list[] = {
 	SNMP_MIB_ITEM("Blackhole", MPTCP_MIB_BLACKHOLE),
 	SNMP_MIB_ITEM("MPCapableDataFallback", MPTCP_MIB_MPCAPABLEDATAFALLBACK),
 	SNMP_MIB_ITEM("MD5SigFallback", MPTCP_MIB_MD5SIGFALLBACK),
+	SNMP_MIB_ITEM("MD5SigReset", MPTCP_MIB_MD5SIGRESET),
 	SNMP_MIB_ITEM("DssFallback", MPTCP_MIB_DSSFALLBACK),
+	SNMP_MIB_ITEM("DssReset", MPTCP_MIB_DSSRESET),
 	SNMP_MIB_ITEM("SimultConnectFallback", MPTCP_MIB_SIMULTCONNFALLBACK),
 	SNMP_MIB_ITEM("FallbackFailed", MPTCP_MIB_FALLBACKFAILED),
 	SNMP_MIB_ITEM("WinProbe", MPTCP_MIB_WINPROBE),
diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h
index 3a3425e258a76..1ebdb55e95343 100644
--- a/net/mptcp/mib.h
+++ b/net/mptcp/mib.h
@@ -16,14 +16,19 @@ enum linux_mptcp_mib_field {
 	MPTCP_MIB_TOKENFALLBACKINIT,	/* Could not init/allocate token */
 	MPTCP_MIB_RETRANSSEGS,		/* Segments retransmitted at the MPTCP-level */
 	MPTCP_MIB_JOINNOTOKEN,		/* Received MP_JOIN but the token was not found */
+	MPTCP_MIB_MPJOINNOIDFOUND,	/* Received MP_JOIN but no local ID was found */
 	MPTCP_MIB_JOINSYNRX,		/* Received a SYN + MP_JOIN */
 	MPTCP_MIB_JOINSYNBACKUPRX,	/* Received a SYN + MP_JOIN + backup flag */
 	MPTCP_MIB_JOINSYNACKRX,		/* Received a SYN/ACK + MP_JOIN */
 	MPTCP_MIB_JOINSYNACKBACKUPRX,	/* Received a SYN/ACK + MP_JOIN + backup flag */
 	MPTCP_MIB_JOINSYNACKMAC,	/* HMAC was wrong on SYN/ACK + MP_JOIN */
+	MPTCP_MIB_MPJOINSYNACKNOMPJOIN,	/* MP_RST: missing MP_JOIN in SYN/ACK */
 	MPTCP_MIB_JOINACKRX,		/* Received an ACK + MP_JOIN */
 	MPTCP_MIB_JOINACKMAC,		/* HMAC was wrong on ACK + MP_JOIN */
+	MPTCP_MIB_MPJOINACKNOMPJOIN,	/* MP_RST: missing MP_JOIN in ACK */
+	MPTCP_MIB_MPJOINACKNOCTX,	/* MP_RST: no subflow context on ACK */
 	MPTCP_MIB_JOINREJECTED,		/* The PM rejected the JOIN request */
+	MPTCP_MIB_MPJOINNOTESTABLISHED,	/* MP_RST: JOIN on not-fully-established msk */
 	MPTCP_MIB_JOINSYNTX,		/* Sending a SYN + MP_JOIN */
 	MPTCP_MIB_JOINSYNTXCREATSKERR,	/* Not able to create a socket when sending a SYN + MP_JOIN */
 	MPTCP_MIB_JOINSYNTXBINDERR,	/* Not able to bind() the address when sending a SYN + MP_JOIN */
@@ -84,7 +89,9 @@ enum linux_mptcp_mib_field {
 					 * established packet
 					 */
 	MPTCP_MIB_MD5SIGFALLBACK,	/* Conflicting TCP option enabled */
+	MPTCP_MIB_MD5SIGRESET,		/* MP_RST: MD5SIG enabled on listener */
 	MPTCP_MIB_DSSFALLBACK,		/* Bad or missing DSS */
+	MPTCP_MIB_DSSRESET,		/* MP_RST: bad data mapping */
 	MPTCP_MIB_SIMULTCONNFALLBACK,	/* Simultaneous connect */
 	MPTCP_MIB_FALLBACKFAILED,	/* Can't fallback due to msk status */
 	MPTCP_MIB_WINPROBE,		/* MPTCP-level zero window probe */
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index d1f73c3e39fa3..8b68868255c50 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -670,7 +670,8 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk,
 	if (mptcp_pm_is_userspace(msk)) {
 		if (update_subflows) {
 			spin_lock_bh(&pm->lock);
-			pm->extra_subflows--;
+			if (!WARN_ON_ONCE(pm->extra_subflows == 0))
+				pm->extra_subflows--;
 			spin_unlock_bh(&pm->lock);
 		}
 		return;
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index 2203cc2d27485..b94fbb483bf94 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -281,8 +281,9 @@ static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk)
 	return err;
 }
 
-void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
-				struct mptcp_pm_addr_entry *entry)
+static void
+mptcp_userspace_pm_remove_addr_entry(struct mptcp_sock *msk,
+				     struct mptcp_pm_addr_entry *entry)
 {
 	struct mptcp_rm_list alist = { .nr = 0 };
 	int anno_nr = 0;
@@ -340,7 +341,7 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
 	list_del_rcu(&match->list);
 	spin_unlock_bh(&msk->pm.lock);
 
-	mptcp_pm_remove_addr_entry(msk, match);
+	mptcp_userspace_pm_remove_addr_entry(msk, match);
 
 	release_sock(sk);
 
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index ec874d2ead6a4..b474d03620a75 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -581,17 +581,23 @@ static bool mptcp_pending_data_fin(struct sock *sk, u64 *seq)
 static void mptcp_set_datafin_timeout(struct sock *sk)
 {
 	struct inet_connection_sock *icsk = inet_csk(sk);
+	u32 rto_min = READ_ONCE(icsk->icsk_rto_min);
+	u32 rto_max = READ_ONCE(icsk->icsk_rto_max);
 	u32 retransmits;
 
+	/* The sysctls are validated independently: rto_min > rto_max is
+	 * possible, guard against ilog2(0).
+	 */
 	retransmits = min_t(u32, icsk->icsk_retransmits,
-			    ilog2(TCP_RTO_MAX / TCP_RTO_MIN));
+			    ilog2(max_t(u32, rto_max / rto_min, 1)));
 
-	mptcp_sk(sk)->timer_ival = TCP_RTO_MIN << retransmits;
+	mptcp_sk(sk)->timer_ival = rto_min << retransmits;
 }
 
 static void __mptcp_set_timeout(struct sock *sk, long tout)
 {
-	mptcp_sk(sk)->timer_ival = tout > 0 ? tout : TCP_RTO_MIN;
+	mptcp_sk(sk)->timer_ival = tout > 0 ? tout :
+				   READ_ONCE(inet_csk(sk)->icsk_rto_min);
 }
 
 static long mptcp_timeout_from_subflow(const struct mptcp_subflow_context *subflow)
@@ -3161,7 +3167,9 @@ static void mptcp_worker(struct work_struct *work)
 
 static void __mptcp_init_sock(struct sock *sk)
 {
+	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct mptcp_sock *msk = mptcp_sk(sk);
+	struct net *net = sock_net(sk);
 
 	INIT_LIST_HEAD(&msk->conn_list);
 	INIT_LIST_HEAD(&msk->join_list);
@@ -3170,7 +3178,13 @@ static void __mptcp_init_sock(struct sock *sk)
 	INIT_WORK(&msk->work, mptcp_worker);
 	msk->out_of_order_queue = RB_ROOT;
 	msk->first_pending = NULL;
-	msk->timer_ival = TCP_RTO_MIN;
+
+	/* msk does not go through tcp_init_sock(); seed RTO bounds. */
+	icsk->icsk_rto_min =
+		usecs_to_jiffies(READ_ONCE(net->ipv4.sysctl_tcp_rto_min_us));
+	icsk->icsk_rto_max =
+		msecs_to_jiffies(READ_ONCE(net->ipv4.sysctl_tcp_rto_max_ms));
+	msk->timer_ival = icsk->icsk_rto_min;
 	msk->scaling_ratio = TCP_DEFAULT_SCALING_RATIO;
 	msk->backlog_len = 0;
 	mptcp_init_rtt_est(msk);
@@ -3988,6 +4002,7 @@ bool mptcp_finish_join(struct sock *ssk)
 
 	/* mptcp socket already closing? */
 	if (!mptcp_is_fully_established(parent)) {
+		MPTCP_INC_STATS(sock_net(parent), MPTCP_MIB_MPJOINNOTESTABLISHED);
 		subflow->reset_reason = MPTCP_RST_EMPTCP;
 		return false;
 	}
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index b3af3462bdd16..06a107d4e8392 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -1149,8 +1149,6 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 			   const struct mptcp_addr_info *addr,
 			   bool echo);
 int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list);
-void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
-				struct mptcp_pm_addr_entry *entry);
 
 /* the default path manager, used in mptcp_pm_unregister */
 extern struct mptcp_pm_ops mptcp_pm_kernel;
@@ -1254,7 +1252,8 @@ u8 mptcp_pm_get_limit_extra_subflows(const struct mptcp_sock *msk);
 /* called under PM lock */
 static inline void __mptcp_pm_close_subflow(struct mptcp_sock *msk)
 {
-	if (--msk->pm.extra_subflows < mptcp_pm_get_limit_extra_subflows(msk))
+	if (!WARN_ON_ONCE(msk->pm.extra_subflows == 0) &&
+	    --msk->pm.extra_subflows < mptcp_pm_get_limit_extra_subflows(msk))
 		WRITE_ONCE(msk->pm.accept_subflow, true);
 }
 
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index e1f20ff8fdb42..af81ad5e699d1 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -96,6 +96,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req)
 
 	local_id = mptcp_pm_get_local_id(msk, (struct sock_common *)req);
 	if (local_id < 0) {
+		SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPJOINNOIDFOUND);
 		sock_put((struct sock *)msk);
 		return NULL;
 	}
@@ -160,6 +161,7 @@ static int subflow_check_req(struct request_sock *req,
 	 * TCP option space.
 	 */
 	if (rcu_access_pointer(tcp_sk(sk_listener)->md5sig_info)) {
+		MPTCP_INC_STATS(sock_net(sk_listener), MPTCP_MIB_MD5SIGRESET);
 		subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);
 		return -EINVAL;
 	}
@@ -563,6 +565,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
 		u8 hmac[SHA256_DIGEST_SIZE];
 
 		if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_SYNACK)) {
+			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPJOINSYNACKNOMPJOIN);
 			subflow->reset_reason = MPTCP_RST_EMPTCP;
 			goto do_reset;
 		}
@@ -865,6 +868,12 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
 		 */
 		if (!ctx || fallback) {
 			if (fallback_is_fatal) {
+				if (!ctx)
+					MPTCP_INC_STATS(sock_net(sk),
+							MPTCP_MIB_MPJOINACKNOCTX);
+				else
+					MPTCP_INC_STATS(sock_net(sk),
+							MPTCP_MIB_MPJOINACKNOMPJOIN);
 				subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);
 				goto dispose_child;
 			}
@@ -1416,6 +1425,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
 			 * subflow_error_report() will introduce the appropriate barriers
 			 */
 			subflow->reset_transient = 0;
+			MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSRESET);
 			subflow->reset_reason = status == MAPPING_NODSS ?
 						MPTCP_RST_EMIDDLEBOX :
 						MPTCP_RST_EMPTCP;
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index cbe573c4ab3ad..ea4cb6c1bd5e2 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -1264,7 +1264,7 @@ static void apply_cmsg_types(int fd, const struct cfg_cmsg_types *cmsg)
 
 static void parse_cmsg_types(const char *type)
 {
-	char *next = strchr(type, ',');
+	const char *next = strchr(type, ',');
 	unsigned int len = 0;
 
 	cfg_cmsg_types.cmsg_enabled = 1;
@@ -1292,7 +1292,7 @@ static void parse_cmsg_types(const char *type)
 
 static void parse_setsock_options(const char *name)
 {
-	char *next = strchr(name, ',');
+	const char *next = strchr(name, ',');
 	unsigned int len = 0;
 
 	if (next) {
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
index d158678fa6ab0..7a2a851fa0adb 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
@@ -212,8 +212,8 @@ if $checksum; then
 fi
 
 if $capture; then
-	rndh="${ns1:4}"
-	mptcp_lib_pr_info "Packet capture files will have this prefix: ${rndh}-"
+	capprefix="mptcp_connect-${ns1:4}"
+	mptcp_lib_pr_info "pcap will have this prefix: ${capprefix}-"
 fi
 
 set_ethtool_flags() {
@@ -372,8 +372,8 @@ do_transfer()
 			capuser="-Z $SUDO_USER"
 		fi
 
-		local capfile="${rndh}-${connector_ns:0:3}-${listener_ns:0:3}-${cl_proto}-${srv_proto}-${connect_addr}-${port}"
-		local capopt="-i any -s 65535 -B 32768 ${capuser}"
+		local capfile="${capprefix}-${connector_ns:0:3}-${listener_ns:0:3}-${cl_proto}-${srv_proto}-${connect_addr}-${port}"
+		local capopt="-i any -s 128 -B 32768 ${capuser}"
 
 		ip netns exec ${listener_ns} tcpdump ${capopt} \
 			-w "${capfile}-listener.pcap" >> "${capout}" 2>&1 &
diff --git a/tools/testing/selftests/net/mptcp/mptcp_diag.c b/tools/testing/selftests/net/mptcp/mptcp_diag.c
index 5e222ba977e4e..3b8d2c8a62160 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_diag.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_diag.c
@@ -377,7 +377,8 @@ static void get_subflow_info(char *subflow_addrs)
 	int ret;
 	int fd;
 
-	ret = sscanf(subflow_addrs, "%[^:]:%d %[^:]:%d", saddr, &sport, daddr, &dport);
+	ret = sscanf(subflow_addrs, "%63[^:]:%d %63[^:]:%d",
+		     saddr, &sport, daddr, &dport);
 	if (ret != 4)
 		die_perror("IP PORT Pairs has style problems!");
 
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 7dc91fac4917e..18ce7136a2b0e 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -75,6 +75,14 @@ unset join_syn_tx
 unset join_create_err
 unset join_bind_err
 unset join_connect_err
+unset join_synack_no_mpjoin
+unset join_ack_no_mpjoin
+unset join_ack_no_ctx
+unset join_not_established
+unset join_no_id_found
+
+unset rst_md5sig
+unset rst_dss
 
 unset fb_ns1
 unset fb_ns2
@@ -971,7 +979,7 @@ cond_start_capture()
 		capfile=$(printf "mp_join-%02u-%s.pcap" "$MPTCP_LIB_TEST_COUNTER" "$ns")
 
 		echo "Capturing traffic for test $MPTCP_LIB_TEST_COUNTER into $capfile"
-		ip netns exec "$ns" tcpdump -i any -s 65535 -B 32768 $capuser -w "$capfile" > "$capout" 2>&1 &
+		ip netns exec "$ns" tcpdump -i any -s 128 -B 32768 $capuser -w "$capfile" > "$capout" 2>&1 &
 		cappid=$!
 
 		sleep 1
@@ -1353,6 +1361,8 @@ chk_rst_nr()
 	local rst_tx=$1
 	local rst_rx=$2
 	local ns_invert=${3:-""}
+	local md5sig=${rst_md5sig:-0}
+	local dss=${rst_dss:-0}
 	local count
 	local ns_tx=$ns1
 	local ns_rx=$ns2
@@ -1389,6 +1399,21 @@ chk_rst_nr()
 	else
 		print_ok
 	fi
+
+	# MPTCP_RST_EMPTCP reset-event counters; default 0, gated on
+	# availability.  Fixed namespaces: MD5SigReset fires on the listener
+	# (server), DssReset on the data receiver (client).
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMD5SigReset")
+	if [ -n "$count" ] && [ "$count" != "$md5sig" ]; then
+		print_check "MD5SigReset"
+		fail_test "got $count MD5SigReset expected $md5sig"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtDssReset")
+	if [ -n "$count" ] && [ "$count" != "$dss" ]; then
+		print_check "DssReset"
+		fail_test "got $count DssReset expected $dss"
+	fi
 }
 
 chk_infi_nr()
@@ -1587,6 +1612,11 @@ chk_join_nr()
 	local rst_nr=${join_rst_nr:-0}
 	local infi_nr=${join_infi_nr:-0}
 	local corrupted_pkts=${join_corrupted_pkts:-0}
+	local synack_no_mpjoin=${join_synack_no_mpjoin:-0}
+	local ack_no_mpjoin=${join_ack_no_mpjoin:-0}
+	local ack_no_ctx=${join_ack_no_ctx:-0}
+	local not_established=${join_not_established:-0}
+	local no_id_found=${join_no_id_found:-0}
 	local rc=${KSFT_PASS}
 	local count
 	local with_cookie
@@ -1655,6 +1685,44 @@ chk_join_nr()
 		fail_test "got $count JOIN[s] syn rejected expected $syn_rej"
 	fi
 
+	# Per-event MPTCP_RST_EMPTCP JOIN counters; default 0, gated on
+	# availability.  Fixed namespaces: the *SynAck* one fires on the
+	# client receiving the SYN/ACK, the others on the server.
+	count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynAckNoMPJoin")
+	if [ -n "$count" ] && [ "$count" != "$synack_no_mpjoin" ]; then
+		rc=${KSFT_FAIL}
+		print_check "synack no mpjoin"
+		fail_test "got $count JOIN[s] synack no mpjoin expected $synack_no_mpjoin"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinAckNoMPJoin")
+	if [ -n "$count" ] && [ "$count" != "$ack_no_mpjoin" ]; then
+		rc=${KSFT_FAIL}
+		print_check "ack no mpjoin"
+		fail_test "got $count JOIN[s] ack no mpjoin expected $ack_no_mpjoin"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinAckNoCtx")
+	if [ -n "$count" ] && [ "$count" != "$ack_no_ctx" ]; then
+		rc=${KSFT_FAIL}
+		print_check "ack no ctx"
+		fail_test "got $count JOIN[s] ack no ctx expected $ack_no_ctx"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinNotEstablished")
+	if [ -n "$count" ] && [ "$count" != "$not_established" ]; then
+		rc=${KSFT_FAIL}
+		print_check "join not established"
+		fail_test "got $count JOIN[s] not established expected $not_established"
+	fi
+
+	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinNoIdFound")
+	if [ -n "$count" ] && [ "$count" != "$no_id_found" ]; then
+		rc=${KSFT_FAIL}
+		print_check "join no id found"
+		fail_test "got $count JOIN[s] no id found expected $no_id_found"
+	fi
+
 	print_results "join Rx" ${rc}
 
 	join_syn_tx="${join_syn_tx:-${syn_nr}}" \
@@ -2359,6 +2427,31 @@ signal_address_tests()
 			chk_add_nr 4 4
 		fi
 	fi
+
+	# signalled address belongs to the client, where a TCP-only
+	# listener is bound at it: the client's MP_JOIN routes locally
+	# to the listener and receives a SYN/ACK without MP_JOIN.
+	# MPJoinSynAckNoMPJoin increments on the client side.
+	if reset "signal address, TCP-only listener on client"; then
+		local extra_bind
+		local port
+
+		pm_nl_set_limits $ns1 0 1
+		pm_nl_set_limits $ns2 1 1
+		pm_nl_add_endpoint $ns1 10.0.2.2 flags signal
+
+		port=$(get_port)
+		ip netns exec ${ns2} ./mptcp_connect -l -t -1 -p "$port" \
+			-s TCP 10.0.2.2 &
+		extra_bind=$!
+		mptcp_lib_wait_local_port_listen "$ns2" "$port"
+
+		run_tests $ns1 $ns2 10.0.1.1
+		join_synack_no_mpjoin=1 join_syn_tx=1 \
+			chk_join_nr 0 0 0
+
+		kill ${extra_bind} 2>/dev/null
+	fi
 }
 
 laminar_endp_tests()
diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh
index 7b9aabe101704..3ea3d1efe32e1 100755
--- a/tools/testing/selftests/net/mptcp/simult_flows.sh
+++ b/tools/testing/selftests/net/mptcp/simult_flows.sh
@@ -24,6 +24,7 @@ small=""
 sout=""
 cout=""
 capout=""
+capprefix=""
 size=0
 
 usage() {
@@ -70,6 +71,11 @@ setup()
 
 	mptcp_lib_ns_init ns1 ns2 ns3
 
+	if $capture; then
+		capprefix="simult_flows-${ns1:4}"
+		mptcp_lib_pr_info "pcap will have this prefix: ${capprefix}-"
+	fi
+
 	ip link add ns1eth1 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"
 	ip link add ns1eth2 netns "$ns1" type veth peer name ns2eth2 netns "$ns2"
 	ip link add ns2eth3 netns "$ns2" type veth peer name ns3eth1 netns "$ns3"
@@ -136,15 +142,14 @@ do_transfer()
 
 	if $capture; then
 		local capuser
-		local rndh="${ns1:4}"
 		if [ -z $SUDO_USER ] ; then
 			capuser=""
 		else
 			capuser="-Z $SUDO_USER"
 		fi
 
-		local capfile="${rndh}-${port}"
-		local capopt="-i any -s 65535 -B 32768 ${capuser}"
+		local capfile="${capprefix}-${port}"
+		local capopt="-i any -s 108 -B 32768 ${capuser}"
 
 		ip netns exec ${ns3}  tcpdump ${capopt} -w "${capfile}-listener.pcap"  >> "${capout}" 2>&1 &
 		local cappid_listener=$!

33/3 2026/08/12 17:13 llm kmsan-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 11133
							output: 283
							thoughts: 1491
						

Thoughts:
**KMSAN Evaluation: No Dedicated Session Required**

Okay, let's break this patch series down from a KMSAN perspective. We need to determine if any of these changes warrant a dedicated KMSAN fuzzing run, which would detect uninitialized memory reads or kernel-to-user memory leaks.

First, I see the changes, and it looks like we're mostly dealing with:

1.  **Removal of `data_ack` field:** This is a key observation. The removal of `data_ack` (and its associated `data_ack32` union member) from `struct mptcp_ext` and the `mptcp_dump_mpext` trace event is a **net reduction** in data and potential issues. Less data is better, in this case. We're removing, not adding. The trace event change doesn't introduce any new user-space exposure of sensitive data, and the `struct mptcp_ext` change involves an `skb_ext_add()` allocation. Less data in the skb extension is a positive thing for reducing memory usage.
2.  **SNMP MIB Items:** These are just counters, incremented using `MPTCP_INC_STATS`. The information exposed through `/proc/net/snmp` or similar is entirely benign. We're not leaking anything sensitive to user space; we're just providing more statistics.
3.  **Underflow Checks & RTO Initialization:** The `WARN_ON_ONCE` checks for `extra_subflows` are defensive coding practices. More importantly, the explicit initialization of `icsk->icsk_rto_min` and `icsk->icsk_rto_max` with values from `net->ipv4.sysctl_tcp_rto_min_us` and `net->ipv4.sysctl_tcp_rto_max_ms` is a **positive**. It *prevents* uninitialized memory usage, where previously the variables might have been uninitialized. This is good practice.

Considering all of this, let's analyze the relevant points.

*   **User-Space Exposure:** There are no new structures copied directly to user space. The trace event *removes* a field and so the data that will be copied is smaller now. The MIB items increment counters, which is not concerning for KMSAN. The removal of the `data_ack` field in the skb extension is a reduction in size.
*   **Uninitialized Memory:** We're removing a field from an skb extension. We are now initializing an RTO and those were not initialized previously, which addresses previous potential uninitialized usage. There are no buffer allocations or new complex data structures created.

We're adding checks to underflow, so not a problem. The addition of the counters is fine. The RTO seeding initializes fields, effectively preventing a source of potential issues.

Therefore, this patch series doesn't introduce any KMSAN risks. The changes are straightforward. The removal of the field and the seeding of the RTO should reduce the risk of uninitialized reads. KASAN and other default sanitizers should adequately handle any potential bugs (logic errors, out-of-bounds). A dedicated KMSAN session is not necessary.
I'm setting NeedsKMSAN=false for this one.



34/3 2026/08/12 17:14 tool set-results
0m Args:
{
  "KMSANReasoning": "The patch series primarily focuses on:\n1. Removing the unused `data_ack` field from `struct mptcp_ext` and the corresponding `mptcp_dump_mpext` trace event.\n2. Adding new SNMP MIB counters for various MPTCP events (e.g., MP_JOIN failures, resets) and incrementing them in the appropriate error paths.\n3. Adding underflow checks (`WARN_ON_ONCE`) for `pm-\u003eextra_subflows`.\n4. Seeding RTO bounds (`icsk_rto_min`, `icsk_rto_max`) during MPTCP socket initialization.\n\nNone of these changes introduce new structures copied to user space, new buffer allocations, or complex conditional logic that could expose uninitialized memory. The removal of fields from the trace event and skb extension reduces the memory footprint, and the RTO bounds initialization ensures fields are properly seeded. Any potential bugs introduced by these changes (e.g., logic errors, out-of-bounds) would be adequately caught by standard KASAN and other default sanitizers. There is no risk of uninitialized memory usage or info-leaks that would necessitate a dedicated KMSAN fuzzing session.",
  "NeedsKMSAN": false
}

Results:
{
  "KMSANReasoning": "The patch series primarily focuses on:\n1. Removing the unused `data_ack` field from `struct mptcp_ext` and the corresponding `mptcp_dump_mpext` trace event.\n2. Adding new SNMP MIB counters for various MPTCP events (e.g., MP_JOIN failures, resets) and incrementing them in the appropriate error paths.\n3. Adding underflow checks (`WARN_ON_ONCE`) for `pm-\u003eextra_subflows`.\n4. Seeding RTO bounds (`icsk_rto_min`, `icsk_rto_max`) during MPTCP socket initialization.\n\nNone of these changes introduce new structures copied to user space, new buffer allocations, or complex conditional logic that could expose uninitialized memory. The removal of fields from the trace event and skb extension reduces the memory footprint, and the RTO bounds initialization ensures fields are properly seeded. Any potential bugs introduced by these changes (e.g., logic errors, out-of-bounds) would be adequately caught by standard KASAN and other default sanitizers. There is no risk of uninitialized memory usage or info-leaks that would necessitate a dedicated KMSAN fuzzing session.",
  "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)