AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/07/25 19:44 flow patch-triage
2m Args:
null

Results:
{
  "EnableConfigs": [
    "MPTCP"
  ],
  "FocusSymbols": [
    "mptcp_incoming_options",
    "mptcp_data_ready"
  ],
  "Reasoning": "The patch modifies the core MPTCP protocol logic to handle memory constraints and retransmissions. It introduces new memory limit checks that drop packets or prune the out-of-order queue when limits are exceeded, and refactors the retransmission logic to handle multiple fragments. These are functional changes to reachable core networking code.",
  "WorthFuzzing": true
}

1/1 2026/07/25 19:44 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit e87a314ccc37c2e34ceda1d2aaa467015a47bf83\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Sat Jul 25 19:44:16 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/net/mptcp/mib.c b/net/mptcp/mib.c\nindex f23fda0c55a720..d9bd4f4afcc0e7 100644\n--- a/net/mptcp/mib.c\n+++ b/net/mptcp/mib.c\n@@ -85,6 +85,9 @@ static const struct snmp_mib mptcp_snmp_list[] = {\n \tSNMP_MIB_ITEM(\"SimultConnectFallback\", MPTCP_MIB_SIMULTCONNFALLBACK),\n \tSNMP_MIB_ITEM(\"FallbackFailed\", MPTCP_MIB_FALLBACKFAILED),\n \tSNMP_MIB_ITEM(\"WinProbe\", MPTCP_MIB_WINPROBE),\n+\tSNMP_MIB_ITEM(\"BacklogDrop\", MPTCP_MIB_BACKLOGDROP),\n+\tSNMP_MIB_ITEM(\"RcvPruned\", MPTCP_MIB_RCVPRUNED),\n+\tSNMP_MIB_ITEM(\"OfoPruned\", MPTCP_MIB_OFO_PRUNED),\n };\n \n /* mptcp_mib_alloc - allocate percpu mib counters\ndiff --git a/net/mptcp/mib.h b/net/mptcp/mib.h\nindex 812218b5ed2bfc..18f35f7e0a2d4e 100644\n--- a/net/mptcp/mib.h\n+++ b/net/mptcp/mib.h\n@@ -88,6 +88,9 @@ enum linux_mptcp_mib_field {\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 */\n+\tMPTCP_MIB_BACKLOGDROP,\t\t/* Backlog over memory limit */\n+\tMPTCP_MIB_RCVPRUNED,\t\t/* Dropped due to memory constrains */\n+\tMPTCP_MIB_OFO_PRUNED,\t\t/* MPTCP-level OoO queue pruned */\n \t__MPTCP_MIB_MAX\n };\n \ndiff --git a/net/mptcp/options.c b/net/mptcp/options.c\nindex c664023d37ba8e..7b954ef7867230 100644\n--- a/net/mptcp/options.c\n+++ b/net/mptcp/options.c\n@@ -1127,8 +1127,30 @@ static bool add_addr_hmac_valid(struct mptcp_sock *msk,\n \treturn hmac == mp_opt-\u003eahmac;\n }\n \n-/* Return false in case of error (or subflow has been reset),\n- * else return true.\n+static bool mptcp_over_limit(struct sock *sk, struct sock *ssk,\n+\t\t\t     const struct sk_buff *skb)\n+{\n+\tstruct mptcp_sock *msk = mptcp_sk(sk);\n+\tu64 mem = sk_rmem_alloc_get(sk);\n+\n+\tmem += READ_ONCE(msk-\u003ebacklog_len);\n+\tif (likely(mem \u003c= READ_ONCE(sk-\u003esk_rcvbuf)))\n+\t\treturn false;\n+\n+\t/* Avoid silently dropping pure acks, fin or zero win probes. */\n+\tif (TCP_SKB_CB(skb)-\u003eseq == TCP_SKB_CB(skb)-\u003eend_seq ||\n+\t    TCP_SKB_CB(skb)-\u003etcp_flags \u0026 TCPHDR_FIN ||\n+\t    !after(TCP_SKB_CB(skb)-\u003eend_seq, tcp_sk(ssk)-\u003ercv_nxt))\n+\t\treturn false;\n+\n+\t/* Dropped due to memory constraints, schedule an ack. */\n+\tinet_csk(ssk)-\u003eicsk_ack.pending |= ICSK_ACK_NOMEM | ICSK_ACK_NOW;\n+\tinet_csk_schedule_ack(ssk);\n+\treturn true;\n+}\n+\n+/* Return false when the caller must drop the packet, i.e. in case of error,\n+ * subflow has been reset, or over memory limits.\n  */\n bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)\n {\n@@ -1154,7 +1176,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)\n \n \t\t__mptcp_data_acked(subflow-\u003econn);\n \t\tmptcp_data_unlock(subflow-\u003econn);\n-\t\treturn true;\n+\t\treturn !mptcp_over_limit(subflow-\u003econn, sk, skb);\n \t}\n \n \tmptcp_get_options(skb, \u0026mp_opt);\ndiff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c\nindex ca644ec53eedb1..5cf44eab76f1c4 100644\n--- a/net/mptcp/protocol.c\n+++ b/net/mptcp/protocol.c\n@@ -373,6 +373,49 @@ static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset,\n \tskb_dst_drop(skb);\n }\n \n+/* \"Inspired\" from the TCP version; main difference: stop as soon as the MPTCP\n+ * socket is under memory limit.\n+ */\n+static bool mptcp_prune_ofo_queue(struct sock *sk, u64 seq)\n+{\n+\tstruct mptcp_sock *msk = mptcp_sk(sk);\n+\tstruct rb_node *node, *prev;\n+\tbool pruned = false;\n+\tu64 mem;\n+\n+\tif (RB_EMPTY_ROOT(\u0026msk-\u003eout_of_order_queue))\n+\t\tgoto out;\n+\n+\tnode = \u0026msk-\u003eooo_last_skb-\u003erbnode;\n+\n+\tdo {\n+\t\tstruct sk_buff *skb = rb_to_skb(node);\n+\n+\t\t/* Stop pruning if the incoming skb would land in OoO tail. */\n+\t\tif (after64(seq, MPTCP_SKB_CB(skb)-\u003emap_seq))\n+\t\t\tbreak;\n+\n+\t\tpruned = true;\n+\t\tprev = rb_prev(node);\n+\t\trb_erase(node, \u0026msk-\u003eout_of_order_queue);\n+\t\tmptcp_drop(sk, skb);\n+\t\tmsk-\u003eooo_last_skb = rb_to_skb(prev);\n+\n+\t\tmem = (unsigned int)sk_rmem_alloc_get(sk);\n+\t\tif (mem \u003c= sk-\u003esk_rcvbuf)\n+\t\t\tbreak;\n+\n+\t\tnode = prev;\n+\t} while (node);\n+\n+\tif (pruned)\n+\t\tMPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFO_PRUNED);\n+\n+out:\n+\tmem = (unsigned int)sk_rmem_alloc_get(sk);\n+\treturn mem \u003c= sk-\u003esk_rcvbuf;\n+}\n+\n static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb)\n {\n \tu64 copy_len = MPTCP_SKB_CB(skb)-\u003eend_seq - MPTCP_SKB_CB(skb)-\u003emap_seq;\n@@ -381,6 +424,17 @@ static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb)\n \n \tmptcp_borrow_fwdmem(sk, skb);\n \n+\t/* Can't drop packets for fallback socket this late, or the stream\n+\t * will break.\n+\t */\n+\tif (unlikely(sk_rmem_alloc_get(sk) \u003e READ_ONCE(sk-\u003esk_rcvbuf)) \u0026\u0026\n+\t    !__mptcp_check_fallback(msk) \u0026\u0026\n+\t    !mptcp_prune_ofo_queue(sk, MPTCP_SKB_CB(skb)-\u003emap_seq)) {\n+\t\tMPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED);\n+\t\tmptcp_drop(sk, skb);\n+\t\treturn false;\n+\t}\n+\n \tif (MPTCP_SKB_CB(skb)-\u003emap_seq == msk-\u003eack_seq) {\n \t\t/* in sequence */\n \t\tmsk-\u003ebytes_received += copy_len;\n@@ -675,6 +729,7 @@ static void __mptcp_add_backlog(struct sock *sk,\n \tstruct sk_buff *tail = NULL;\n \tstruct sock *ssk = skb-\u003esk;\n \tbool fragstolen;\n+\tu64 limit;\n \tint delta;\n \n \tif (unlikely(sk-\u003esk_state == TCP_CLOSE)) {\n@@ -682,6 +737,16 @@ static void __mptcp_add_backlog(struct sock *sk,\n \t\treturn;\n \t}\n \n+\t/* Similar additional allowance as plain TCP. */\n+\tlimit = READ_ONCE(sk-\u003esk_rcvbuf);\n+\tlimit += (limit \u003e\u003e 1) + 64 * 1024;\n+\tlimit = min_t(u64, limit, UINT_MAX);\n+\tif (msk-\u003ebacklog_len \u003e limit \u0026\u0026 !__mptcp_check_fallback(msk)) {\n+\t\t__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_BACKLOGDROP);\n+\t\tkfree_skb_reason(skb, SKB_DROP_REASON_SOCKET_BACKLOG);\n+\t\treturn;\n+\t}\n+\n \t/* Try to coalesce with the last skb in our backlog */\n \tif (!list_empty(\u0026msk-\u003ebacklog_list))\n \t\ttail = list_last_entry(\u0026msk-\u003ebacklog_list, struct sk_buff, list);\n@@ -753,7 +818,7 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,\n \n \t\t\tmptcp_init_skb(ssk, skb, offset, len);\n \n-\t\t\tif (own_msk \u0026\u0026 sk_rmem_alloc_get(sk) \u003c sk-\u003esk_rcvbuf) {\n+\t\t\tif (own_msk) {\n \t\t\t\tmptcp_subflow_lend_fwdmem(subflow, skb);\n \t\t\t\tret |= __mptcp_move_skb(sk, skb);\n \t\t\t} else {\n@@ -1136,13 +1201,6 @@ static void __mptcp_clean_una_wakeup(struct sock *sk)\n \tmptcp_write_space(sk);\n }\n \n-static void mptcp_clean_una_wakeup(struct sock *sk)\n-{\n-\tmptcp_data_lock(sk);\n-\t__mptcp_clean_una_wakeup(sk);\n-\tmptcp_data_unlock(sk);\n-}\n-\n static void mptcp_enter_memory_pressure(struct sock *sk)\n {\n \tstruct mptcp_subflow_context *subflow;\n@@ -2209,12 +2267,7 @@ static bool __mptcp_move_skbs(struct sock *sk, struct list_head *skbs, u32 *delt\n \tstruct mptcp_sock *msk = mptcp_sk(sk);\n \tbool moved = false;\n \n-\t*delta = 0;\n \twhile (1) {\n-\t\t/* If the msk recvbuf is full stop, don't drop */\n-\t\tif (sk_rmem_alloc_get(sk) \u003e sk-\u003esk_rcvbuf)\n-\t\t\tbreak;\n-\n \t\tprefetch(skb-\u003enext);\n \t\tlist_del(\u0026skb-\u003elist);\n \t\t*delta += skb-\u003etruesize;\n@@ -2242,9 +2295,7 @@ static bool mptcp_can_spool_backlog(struct sock *sk, struct list_head *skbs)\n \tDEBUG_NET_WARN_ON_ONCE(msk-\u003ebacklog_unaccounted \u0026\u0026 sk-\u003esk_socket \u0026\u0026\n \t\t\t       mem_cgroup_from_sk(sk));\n \n-\t/* Don't spool the backlog if the rcvbuf is full. */\n-\tif (list_empty(\u0026msk-\u003ebacklog_list) ||\n-\t    sk_rmem_alloc_get(sk) \u003e sk-\u003esk_rcvbuf)\n+\tif (list_empty(\u0026msk-\u003ebacklog_list))\n \t\treturn false;\n \n \tINIT_LIST_HEAD(skbs);\n@@ -2252,20 +2303,12 @@ static bool mptcp_can_spool_backlog(struct sock *sk, struct list_head *skbs)\n \treturn true;\n }\n \n-static void mptcp_backlog_spooled(struct sock *sk, u32 moved,\n-\t\t\t\t  struct list_head *skbs)\n-{\n-\tstruct mptcp_sock *msk = mptcp_sk(sk);\n-\n-\tWRITE_ONCE(msk-\u003ebacklog_len, msk-\u003ebacklog_len - moved);\n-\tlist_splice(skbs, \u0026msk-\u003ebacklog_list);\n-}\n-\n static bool mptcp_move_skbs(struct sock *sk)\n {\n+\tstruct mptcp_sock *msk = mptcp_sk(sk);\n \tstruct list_head skbs;\n \tbool enqueued = false;\n-\tu32 moved;\n+\tu32 moved = 0;\n \n \tmptcp_data_lock(sk);\n \twhile (mptcp_can_spool_backlog(sk, \u0026skbs)) {\n@@ -2273,8 +2316,8 @@ static bool mptcp_move_skbs(struct sock *sk)\n \t\tenqueued |= __mptcp_move_skbs(sk, \u0026skbs, \u0026moved);\n \n \t\tmptcp_data_lock(sk);\n-\t\tmptcp_backlog_spooled(sk, moved, \u0026skbs);\n \t}\n+\tWRITE_ONCE(msk-\u003ebacklog_len, msk-\u003ebacklog_len - moved);\n \tmptcp_data_unlock(sk);\n \n \tif (enqueued \u0026\u0026 mptcp_epollin_ready(sk))\n@@ -2785,44 +2828,22 @@ static void mptcp_check_fastclose(struct mptcp_sock *msk)\n \tsk_error_report(sk);\n }\n \n-static void __mptcp_retrans(struct sock *sk)\n+/*\n+ * Retransmit the specified data fragment on all the selected subflows,\n+ * starting from the specified sequence\n+ */\n+static int __mptcp_push_retrans(struct sock *sk, struct mptcp_data_frag *dfrag,\n+\t\t\t\tu64 sent_seq)\n {\n \tstruct mptcp_sendmsg_info info = { .data_lock_held = true, };\n \tstruct mptcp_sock *msk = mptcp_sk(sk);\n \tstruct mptcp_subflow_context *subflow;\n-\tstruct mptcp_data_frag *dfrag;\n \tstruct sock *ssk;\n-\tint ret, err;\n-\tu16 len = 0;\n-\n-\tmptcp_clean_una_wakeup(sk);\n-\n-\t/* first check ssk: need to kick \"stale\" logic */\n-\terr = mptcp_sched_get_retrans(msk);\n-\tdfrag = mptcp_rtx_head(sk);\n-\tif (!dfrag) {\n-\t\tif (mptcp_data_fin_enabled(msk)) {\n-\t\t\tstruct inet_connection_sock *icsk = inet_csk(sk);\n-\n-\t\t\tWRITE_ONCE(icsk-\u003eicsk_retransmits,\n-\t\t\t\t   icsk-\u003eicsk_retransmits + 1);\n-\t\t\tmptcp_set_datafin_timeout(sk);\n-\t\t\tmptcp_send_ack(msk);\n-\n-\t\t\tgoto reset_timer;\n-\t\t}\n-\n-\t\tif (!mptcp_send_head(sk))\n-\t\t\tgoto clear_scheduled;\n-\n-\t\tgoto reset_timer;\n-\t}\n-\n-\tif (err)\n-\t\tgoto reset_timer;\n+\tint ret, len = 0;\n \n \tmptcp_for_each_subflow(msk, subflow) {\n \t\tif (READ_ONCE(subflow-\u003escheduled)) {\n+\t\t\tu16 offset = sent_seq - dfrag-\u003edata_seq;\n \t\t\tu16 copied = 0;\n \n \t\t\tmptcp_subflow_set_scheduled(subflow, false);\n@@ -2832,7 +2853,7 @@ static void __mptcp_retrans(struct sock *sk)\n \t\t\tlock_sock(ssk);\n \n \t\t\t/* limit retransmission to the bytes already sent on some subflows */\n-\t\t\tinfo.sent = 0;\n+\t\t\tinfo.sent = offset;\n \t\t\tinfo.limit = READ_ONCE(msk-\u003ecsum_enabled) ? dfrag-\u003edata_len :\n \t\t\t\t\t\t\t\t    dfrag-\u003ealready_sent;\n \n@@ -2847,7 +2868,7 @@ static void __mptcp_retrans(struct sock *sk)\n \t\t\t    !msk-\u003eallow_subflows) {\n \t\t\t\tspin_unlock_bh(\u0026msk-\u003efallback_lock);\n \t\t\t\trelease_sock(ssk);\n-\t\t\t\tgoto clear_scheduled;\n+\t\t\t\treturn -1;\n \t\t\t}\n \n \t\t\twhile (info.sent \u003c info.limit) {\n@@ -2870,13 +2891,109 @@ static void __mptcp_retrans(struct sock *sk)\n \t\t\trelease_sock(ssk);\n \t\t}\n \t}\n+\treturn len;\n+}\n+\n+static void __mptcp_retrans(struct sock *sk)\n+{\n+\tstruct mptcp_sock *msk = mptcp_sk(sk);\n+\tstruct mptcp_subflow_context *subflow;\n+\tstruct mptcp_data_frag *dfrag;\n+\tbool need_retrans;\n+\tu64 retrans_seq;\n+\tint err, len;\n \n-\tmsk-\u003ebytes_retrans += len;\n-\tdfrag-\u003ealready_sent = max(dfrag-\u003ealready_sent, len);\n+\tmptcp_data_lock(sk);\n+\t__mptcp_clean_una_wakeup(sk);\n+\tretrans_seq = msk-\u003esnd_una;\n+\tdfrag = mptcp_rtx_head(sk);\n+\tneed_retrans = !!dfrag;\n+\tmptcp_data_unlock(sk);\n+\tif (!dfrag)\n+\t\tgoto check_data_fin;\n \n-\t/* With csum enabled retransmission can send new data. */\n-\tif (after64(dfrag-\u003ealready_sent + dfrag-\u003edata_seq, msk-\u003esnd_nxt))\n-\t\tWRITE_ONCE(msk-\u003esnd_nxt, dfrag-\u003ealready_sent + dfrag-\u003edata_seq);\n+\tfor (;;) {\n+\t\tbool already_retrans;\n+\t\tu64 sent_seq;\n+\n+\t\t/* The default scheduler will kick \"stale\" logic, that in\n+\t\t * turn can process incoming acks and clean the RTX queue;\n+\t\t * ensure that the current dfrag will still be around\n+\t\t * afterwards.\n+\t\t */\n+\t\tget_page(dfrag-\u003epage);\n+\t\terr = mptcp_sched_get_retrans(msk);\n+\t\tif (err) {\n+\t\t\tput_page(dfrag-\u003epage);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\t/* Incoming acks can have moved retrans sequence after\n+\t\t * the current dfrag, if so try to start again from RTX head.\n+\t\t */\n+\t\tmptcp_data_lock(sk);\n+\t\talready_retrans = !before64(msk-\u003esnd_una, dfrag-\u003edata_seq +\n+\t\t\t\t\t    dfrag-\u003ealready_sent);\n+\t\tput_page(dfrag-\u003epage);\n+\t\tif (already_retrans) {\n+\t\t\t__mptcp_clean_una_wakeup(sk);\n+\t\t\tretrans_seq = msk-\u003esnd_una;\n+\t\t\tdfrag = mptcp_rtx_head(sk);\n+\t\t\tneed_retrans = !!dfrag;\n+\t\t} else if (after64(msk-\u003esnd_una, retrans_seq)) {\n+\t\t\tretrans_seq = msk-\u003esnd_una;\n+\t\t}\n+\t\tmptcp_data_unlock(sk);\n+\n+\t\t/* `already_sent` can be 0 for `dfrag` belonging to the RTX\n+\t\t *  queue due to __mptcp_retransmit_pending_data().\n+\t\t */\n+\t\tif (!dfrag || !dfrag-\u003ealready_sent)\n+\t\t\tbreak;\n+\n+\t\t/* Can fail only in case of fallback. */\n+\t\tlen = __mptcp_push_retrans(sk, dfrag, retrans_seq);\n+\t\tif (len \u003c 0)\n+\t\t\tgoto clear_scheduled;\n+\n+\t\tretrans_seq += len;\n+\t\tmsk-\u003ebytes_retrans += len;\n+\t\tdfrag-\u003ealready_sent = max_t(u16, dfrag-\u003ealready_sent,\n+\t\t\t\t\t    retrans_seq - dfrag-\u003edata_seq);\n+\n+\t\t/* With csum enabled retransmission can send new data. */\n+\t\tsent_seq = dfrag-\u003ealready_sent + dfrag-\u003edata_seq;\n+\t\tif (after64(sent_seq, msk-\u003esnd_nxt))\n+\t\t\tWRITE_ONCE(msk-\u003esnd_nxt, sent_seq);\n+\n+\t\t/* Attempt the next fragment only if the current one is\n+\t\t * completely retransmitted.\n+\t\t */\n+\t\tif (before64(retrans_seq, dfrag-\u003edata_seq + dfrag-\u003edata_len))\n+\t\t\tbreak;\n+\n+\t\tdfrag = list_is_last(\u0026dfrag-\u003elist, \u0026msk-\u003ertx_queue) ?\n+\t\t\t\tNULL : list_next_entry(dfrag, list);\n+\t\tif (!dfrag)\n+\t\t\tbreak;\n+\t}\n+\n+\t/* Attempt data-fin retransmission only when the RTX queue is empty. */\n+\tif (!need_retrans) {\n+check_data_fin:\n+\t\tif (mptcp_data_fin_enabled(msk)) {\n+\t\t\tstruct inet_connection_sock *icsk = inet_csk(sk);\n+\n+\t\t\tWRITE_ONCE(icsk-\u003eicsk_retransmits,\n+\t\t\t\t   icsk-\u003eicsk_retransmits + 1);\n+\t\t\tmptcp_set_datafin_timeout(sk);\n+\t\t\tmptcp_send_ack(msk);\n+\t\t\tgoto reset_timer;\n+\t\t}\n+\n+\t\tif (!mptcp_send_head(sk))\n+\t\t\tgoto clear_scheduled;\n+\t}\n \n reset_timer:\n \tmptcp_check_and_set_pending(sk);\n@@ -3670,12 +3787,12 @@ static void mptcp_release_cb(struct sock *sk)\n \t__must_hold(\u0026sk-\u003esk_lock.slock)\n {\n \tstruct mptcp_sock *msk = mptcp_sk(sk);\n+\tu32 moved = 0;\n \n \tfor (;;) {\n \t\tunsigned long flags = (msk-\u003ecb_flags \u0026 MPTCP_FLAGS_PROCESS_CTX_NEED);\n \t\tstruct list_head join_list, skbs;\n \t\tbool spool_bl;\n-\t\tu32 moved;\n \n \t\tspool_bl = mptcp_can_spool_backlog(sk, \u0026skbs);\n \t\tif (!flags \u0026\u0026 !spool_bl)\n@@ -3708,9 +3825,9 @@ static void mptcp_release_cb(struct sock *sk)\n \n \t\tcond_resched();\n \t\tspin_lock_bh(\u0026sk-\u003esk_lock.slock);\n-\t\tif (spool_bl)\n-\t\t\tmptcp_backlog_spooled(sk, moved, \u0026skbs);\n \t}\n+\tif (moved)\n+\t\tWRITE_ONCE(msk-\u003ebacklog_len, msk-\u003ebacklog_len - moved);\n \n \tif (__test_and_clear_bit(MPTCP_CLEAN_UNA, \u0026msk-\u003ecb_flags))\n \t\t__mptcp_clean_una_wakeup(sk);\n"
}

2/1 2026/07/25 19:44 agent patch-evaluator
2m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": [
    "MPTCP"
  ],
  "FocusSymbols": [
    "mptcp_incoming_options",
    "mptcp_data_ready"
  ],
  "Reasoning": "The patch modifies the core MPTCP protocol logic to handle memory constraints and retransmissions. It introduces new memory limit checks that drop packets or prune the out-of-order queue when limits are exceeded, and refactors the retransmission logic to handle multiple fragments. These are functional changes to reachable core networking code.",
  "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 e87a314ccc37c2e34ceda1d2aaa467015a47bf83
Author: syz-cluster <triage@syzkaller.com>
Date:   Sat Jul 25 19:44:16 2026 +0000

    syz-cluster: applied patch under review

diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c
index f23fda0c55a720..d9bd4f4afcc0e7 100644
--- a/net/mptcp/mib.c
+++ b/net/mptcp/mib.c
@@ -85,6 +85,9 @@ static const struct snmp_mib mptcp_snmp_list[] = {
 	SNMP_MIB_ITEM("SimultConnectFallback", MPTCP_MIB_SIMULTCONNFALLBACK),
 	SNMP_MIB_ITEM("FallbackFailed", MPTCP_MIB_FALLBACKFAILED),
 	SNMP_MIB_ITEM("WinProbe", MPTCP_MIB_WINPROBE),
+	SNMP_MIB_ITEM("BacklogDrop", MPTCP_MIB_BACKLOGDROP),
+	SNMP_MIB_ITEM("RcvPruned", MPTCP_MIB_RCVPRUNED),
+	SNMP_MIB_ITEM("OfoPruned", MPTCP_MIB_OFO_PRUNED),
 };
 
 /* mptcp_mib_alloc - allocate percpu mib counters
diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h
index 812218b5ed2bfc..18f35f7e0a2d4e 100644
--- a/net/mptcp/mib.h
+++ b/net/mptcp/mib.h
@@ -88,6 +88,9 @@ enum linux_mptcp_mib_field {
 	MPTCP_MIB_SIMULTCONNFALLBACK,	/* Simultaneous connect */
 	MPTCP_MIB_FALLBACKFAILED,	/* Can't fallback due to msk status */
 	MPTCP_MIB_WINPROBE,		/* MPTCP-level zero window probe */
+	MPTCP_MIB_BACKLOGDROP,		/* Backlog over memory limit */
+	MPTCP_MIB_RCVPRUNED,		/* Dropped due to memory constrains */
+	MPTCP_MIB_OFO_PRUNED,		/* MPTCP-level OoO queue pruned */
 	__MPTCP_MIB_MAX
 };
 
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index c664023d37ba8e..7b954ef7867230 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -1127,8 +1127,30 @@ static bool add_addr_hmac_valid(struct mptcp_sock *msk,
 	return hmac == mp_opt->ahmac;
 }
 
-/* Return false in case of error (or subflow has been reset),
- * else return true.
+static bool mptcp_over_limit(struct sock *sk, struct sock *ssk,
+			     const struct sk_buff *skb)
+{
+	struct mptcp_sock *msk = mptcp_sk(sk);
+	u64 mem = sk_rmem_alloc_get(sk);
+
+	mem += READ_ONCE(msk->backlog_len);
+	if (likely(mem <= READ_ONCE(sk->sk_rcvbuf)))
+		return false;
+
+	/* Avoid silently dropping pure acks, fin or zero win probes. */
+	if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq ||
+	    TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN ||
+	    !after(TCP_SKB_CB(skb)->end_seq, tcp_sk(ssk)->rcv_nxt))
+		return false;
+
+	/* Dropped due to memory constraints, schedule an ack. */
+	inet_csk(ssk)->icsk_ack.pending |= ICSK_ACK_NOMEM | ICSK_ACK_NOW;
+	inet_csk_schedule_ack(ssk);
+	return true;
+}
+
+/* Return false when the caller must drop the packet, i.e. in case of error,
+ * subflow has been reset, or over memory limits.
  */
 bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
 {
@@ -1154,7 +1176,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
 
 		__mptcp_data_acked(subflow->conn);
 		mptcp_data_unlock(subflow->conn);
-		return true;
+		return !mptcp_over_limit(subflow->conn, sk, skb);
 	}
 
 	mptcp_get_options(skb, &mp_opt);
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index ca644ec53eedb1..5cf44eab76f1c4 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -373,6 +373,49 @@ static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset,
 	skb_dst_drop(skb);
 }
 
+/* "Inspired" from the TCP version; main difference: stop as soon as the MPTCP
+ * socket is under memory limit.
+ */
+static bool mptcp_prune_ofo_queue(struct sock *sk, u64 seq)
+{
+	struct mptcp_sock *msk = mptcp_sk(sk);
+	struct rb_node *node, *prev;
+	bool pruned = false;
+	u64 mem;
+
+	if (RB_EMPTY_ROOT(&msk->out_of_order_queue))
+		goto out;
+
+	node = &msk->ooo_last_skb->rbnode;
+
+	do {
+		struct sk_buff *skb = rb_to_skb(node);
+
+		/* Stop pruning if the incoming skb would land in OoO tail. */
+		if (after64(seq, MPTCP_SKB_CB(skb)->map_seq))
+			break;
+
+		pruned = true;
+		prev = rb_prev(node);
+		rb_erase(node, &msk->out_of_order_queue);
+		mptcp_drop(sk, skb);
+		msk->ooo_last_skb = rb_to_skb(prev);
+
+		mem = (unsigned int)sk_rmem_alloc_get(sk);
+		if (mem <= sk->sk_rcvbuf)
+			break;
+
+		node = prev;
+	} while (node);
+
+	if (pruned)
+		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFO_PRUNED);
+
+out:
+	mem = (unsigned int)sk_rmem_alloc_get(sk);
+	return mem <= sk->sk_rcvbuf;
+}
+
 static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb)
 {
 	u64 copy_len = MPTCP_SKB_CB(skb)->end_seq - MPTCP_SKB_CB(skb)->map_seq;
@@ -381,6 +424,17 @@ static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb)
 
 	mptcp_borrow_fwdmem(sk, skb);
 
+	/* Can't drop packets for fallback socket this late, or the stream
+	 * will break.
+	 */
+	if (unlikely(sk_rmem_alloc_get(sk) > READ_ONCE(sk->sk_rcvbuf)) &&
+	    !__mptcp_check_fallback(msk) &&
+	    !mptcp_prune_ofo_queue(sk, MPTCP_SKB_CB(skb)->map_seq)) {
+		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED);
+		mptcp_drop(sk, skb);
+		return false;
+	}
+
 	if (MPTCP_SKB_CB(skb)->map_seq == msk->ack_seq) {
 		/* in sequence */
 		msk->bytes_received += copy_len;
@@ -675,6 +729,7 @@ static void __mptcp_add_backlog(struct sock *sk,
 	struct sk_buff *tail = NULL;
 	struct sock *ssk = skb->sk;
 	bool fragstolen;
+	u64 limit;
 	int delta;
 
 	if (unlikely(sk->sk_state == TCP_CLOSE)) {
@@ -682,6 +737,16 @@ static void __mptcp_add_backlog(struct sock *sk,
 		return;
 	}
 
+	/* Similar additional allowance as plain TCP. */
+	limit = READ_ONCE(sk->sk_rcvbuf);
+	limit += (limit >> 1) + 64 * 1024;
+	limit = min_t(u64, limit, UINT_MAX);
+	if (msk->backlog_len > limit && !__mptcp_check_fallback(msk)) {
+		__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_BACKLOGDROP);
+		kfree_skb_reason(skb, SKB_DROP_REASON_SOCKET_BACKLOG);
+		return;
+	}
+
 	/* Try to coalesce with the last skb in our backlog */
 	if (!list_empty(&msk->backlog_list))
 		tail = list_last_entry(&msk->backlog_list, struct sk_buff, list);
@@ -753,7 +818,7 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
 
 			mptcp_init_skb(ssk, skb, offset, len);
 
-			if (own_msk && sk_rmem_alloc_get(sk) < sk->sk_rcvbuf) {
+			if (own_msk) {
 				mptcp_subflow_lend_fwdmem(subflow, skb);
 				ret |= __mptcp_move_skb(sk, skb);
 			} else {
@@ -1136,13 +1201,6 @@ static void __mptcp_clean_una_wakeup(struct sock *sk)
 	mptcp_write_space(sk);
 }
 
-static void mptcp_clean_una_wakeup(struct sock *sk)
-{
-	mptcp_data_lock(sk);
-	__mptcp_clean_una_wakeup(sk);
-	mptcp_data_unlock(sk);
-}
-
 static void mptcp_enter_memory_pressure(struct sock *sk)
 {
 	struct mptcp_subflow_context *subflow;
@@ -2209,12 +2267,7 @@ static bool __mptcp_move_skbs(struct sock *sk, struct list_head *skbs, u32 *delt
 	struct mptcp_sock *msk = mptcp_sk(sk);
 	bool moved = false;
 
-	*delta = 0;
 	while (1) {
-		/* If the msk recvbuf is full stop, don't drop */
-		if (sk_rmem_alloc_get(sk) > sk->sk_rcvbuf)
-			break;
-
 		prefetch(skb->next);
 		list_del(&skb->list);
 		*delta += skb->truesize;
@@ -2242,9 +2295,7 @@ static bool mptcp_can_spool_backlog(struct sock *sk, struct list_head *skbs)
 	DEBUG_NET_WARN_ON_ONCE(msk->backlog_unaccounted && sk->sk_socket &&
 			       mem_cgroup_from_sk(sk));
 
-	/* Don't spool the backlog if the rcvbuf is full. */
-	if (list_empty(&msk->backlog_list) ||
-	    sk_rmem_alloc_get(sk) > sk->sk_rcvbuf)
+	if (list_empty(&msk->backlog_list))
 		return false;
 
 	INIT_LIST_HEAD(skbs);
@@ -2252,20 +2303,12 @@ static bool mptcp_can_spool_backlog(struct sock *sk, struct list_head *skbs)
 	return true;
 }
 
-static void mptcp_backlog_spooled(struct sock *sk, u32 moved,
-				  struct list_head *skbs)
-{
-	struct mptcp_sock *msk = mptcp_sk(sk);
-
-	WRITE_ONCE(msk->backlog_len, msk->backlog_len - moved);
-	list_splice(skbs, &msk->backlog_list);
-}
-
 static bool mptcp_move_skbs(struct sock *sk)
 {
+	struct mptcp_sock *msk = mptcp_sk(sk);
 	struct list_head skbs;
 	bool enqueued = false;
-	u32 moved;
+	u32 moved = 0;
 
 	mptcp_data_lock(sk);
 	while (mptcp_can_spool_backlog(sk, &skbs)) {
@@ -2273,8 +2316,8 @@ static bool mptcp_move_skbs(struct sock *sk)
 		enqueued |= __mptcp_move_skbs(sk, &skbs, &moved);
 
 		mptcp_data_lock(sk);
-		mptcp_backlog_spooled(sk, moved, &skbs);
 	}
+	WRITE_ONCE(msk->backlog_len, msk->backlog_len - moved);
 	mptcp_data_unlock(sk);
 
 	if (enqueued && mptcp_epollin_ready(sk))
@@ -2785,44 +2828,22 @@ static void mptcp_check_fastclose(struct mptcp_sock *msk)
 	sk_error_report(sk);
 }
 
-static void __mptcp_retrans(struct sock *sk)
+/*
+ * Retransmit the specified data fragment on all the selected subflows,
+ * starting from the specified sequence
+ */
+static int __mptcp_push_retrans(struct sock *sk, struct mptcp_data_frag *dfrag,
+				u64 sent_seq)
 {
 	struct mptcp_sendmsg_info info = { .data_lock_held = true, };
 	struct mptcp_sock *msk = mptcp_sk(sk);
 	struct mptcp_subflow_context *subflow;
-	struct mptcp_data_frag *dfrag;
 	struct sock *ssk;
-	int ret, err;
-	u16 len = 0;
-
-	mptcp_clean_una_wakeup(sk);
-
-	/* first check ssk: need to kick "stale" logic */
-	err = mptcp_sched_get_retrans(msk);
-	dfrag = mptcp_rtx_head(sk);
-	if (!dfrag) {
-		if (mptcp_data_fin_enabled(msk)) {
-			struct inet_connection_sock *icsk = inet_csk(sk);
-
-			WRITE_ONCE(icsk->icsk_retransmits,
-				   icsk->icsk_retransmits + 1);
-			mptcp_set_datafin_timeout(sk);
-			mptcp_send_ack(msk);
-
-			goto reset_timer;
-		}
-
-		if (!mptcp_send_head(sk))
-			goto clear_scheduled;
-
-		goto reset_timer;
-	}
-
-	if (err)
-		goto reset_timer;
+	int ret, len = 0;
 
 	mptcp_for_each_subflow(msk, subflow) {
 		if (READ_ONCE(subflow->scheduled)) {
+			u16 offset = sent_seq - dfrag->data_seq;
 			u16 copied = 0;
 
 			mptcp_subflow_set_scheduled(subflow, false);
@@ -2832,7 +2853,7 @@ static void __mptcp_retrans(struct sock *sk)
 			lock_sock(ssk);
 
 			/* limit retransmission to the bytes already sent on some subflows */
-			info.sent = 0;
+			info.sent = offset;
 			info.limit = READ_ONCE(msk->csum_enabled) ? dfrag->data_len :
 								    dfrag->already_sent;
 
@@ -2847,7 +2868,7 @@ static void __mptcp_retrans(struct sock *sk)
 			    !msk->allow_subflows) {
 				spin_unlock_bh(&msk->fallback_lock);
 				release_sock(ssk);
-				goto clear_scheduled;
+				return -1;
 			}
 
 			while (info.sent < info.limit) {
@@ -2870,13 +2891,109 @@ static void __mptcp_retrans(struct sock *sk)
 			release_sock(ssk);
 		}
 	}
+	return len;
+}
+
+static void __mptcp_retrans(struct sock *sk)
+{
+	struct mptcp_sock *msk = mptcp_sk(sk);
+	struct mptcp_subflow_context *subflow;
+	struct mptcp_data_frag *dfrag;
+	bool need_retrans;
+	u64 retrans_seq;
+	int err, len;
 
-	msk->bytes_retrans += len;
-	dfrag->already_sent = max(dfrag->already_sent, len);
+	mptcp_data_lock(sk);
+	__mptcp_clean_una_wakeup(sk);
+	retrans_seq = msk->snd_una;
+	dfrag = mptcp_rtx_head(sk);
+	need_retrans = !!dfrag;
+	mptcp_data_unlock(sk);
+	if (!dfrag)
+		goto check_data_fin;
 
-	/* With csum enabled retransmission can send new data. */
-	if (after64(dfrag->already_sent + dfrag->data_seq, msk->snd_nxt))
-		WRITE_ONCE(msk->snd_nxt, dfrag->already_sent + dfrag->data_seq);
+	for (;;) {
+		bool already_retrans;
+		u64 sent_seq;
+
+		/* The default scheduler will kick "stale" logic, that in
+		 * turn can process incoming acks and clean the RTX queue;
+		 * ensure that the current dfrag will still be around
+		 * afterwards.
+		 */
+		get_page(dfrag->page);
+		err = mptcp_sched_get_retrans(msk);
+		if (err) {
+			put_page(dfrag->page);
+			break;
+		}
+
+		/* Incoming acks can have moved retrans sequence after
+		 * the current dfrag, if so try to start again from RTX head.
+		 */
+		mptcp_data_lock(sk);
+		already_retrans = !before64(msk->snd_una, dfrag->data_seq +
+					    dfrag->already_sent);
+		put_page(dfrag->page);
+		if (already_retrans) {
+			__mptcp_clean_una_wakeup(sk);
+			retrans_seq = msk->snd_una;
+			dfrag = mptcp_rtx_head(sk);
+			need_retrans = !!dfrag;
+		} else if (after64(msk->snd_una, retrans_seq)) {
+			retrans_seq = msk->snd_una;
+		}
+		mptcp_data_unlock(sk);
+
+		/* `already_sent` can be 0 for `dfrag` belonging to the RTX
+		 *  queue due to __mptcp_retransmit_pending_data().
+		 */
+		if (!dfrag || !dfrag->already_sent)
+			break;
+
+		/* Can fail only in case of fallback. */
+		len = __mptcp_push_retrans(sk, dfrag, retrans_seq);
+		if (len < 0)
+			goto clear_scheduled;
+
+		retrans_seq += len;
+		msk->bytes_retrans += len;
+		dfrag->already_sent = max_t(u16, dfrag->already_sent,
+					    retrans_seq - dfrag->data_seq);
+
+		/* With csum enabled retransmission can send new data. */
+		sent_seq = dfrag->already_sent + dfrag->data_seq;
+		if (after64(sent_seq, msk->snd_nxt))
+			WRITE_ONCE(msk->snd_nxt, sent_seq);
+
+		/* Attempt the next fragment only if the current one is
+		 * completely retransmitted.
+		 */
+		if (before64(retrans_seq, dfrag->data_seq + dfrag->data_len))
+			break;
+
+		dfrag = list_is_last(&dfrag->list, &msk->rtx_queue) ?
+				NULL : list_next_entry(dfrag, list);
+		if (!dfrag)
+			break;
+	}
+
+	/* Attempt data-fin retransmission only when the RTX queue is empty. */
+	if (!need_retrans) {
+check_data_fin:
+		if (mptcp_data_fin_enabled(msk)) {
+			struct inet_connection_sock *icsk = inet_csk(sk);
+
+			WRITE_ONCE(icsk->icsk_retransmits,
+				   icsk->icsk_retransmits + 1);
+			mptcp_set_datafin_timeout(sk);
+			mptcp_send_ack(msk);
+			goto reset_timer;
+		}
+
+		if (!mptcp_send_head(sk))
+			goto clear_scheduled;
+	}
 
 reset_timer:
 	mptcp_check_and_set_pending(sk);
@@ -3670,12 +3787,12 @@ static void mptcp_release_cb(struct sock *sk)
 	__must_hold(&sk->sk_lock.slock)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
+	u32 moved = 0;
 
 	for (;;) {
 		unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED);
 		struct list_head join_list, skbs;
 		bool spool_bl;
-		u32 moved;
 
 		spool_bl = mptcp_can_spool_backlog(sk, &skbs);
 		if (!flags && !spool_bl)
@@ -3708,9 +3825,9 @@ static void mptcp_release_cb(struct sock *sk)
 
 		cond_resched();
 		spin_lock_bh(&sk->sk_lock.slock);
-		if (spool_bl)
-			mptcp_backlog_spooled(sk, moved, &skbs);
 	}
+	if (moved)
+		WRITE_ONCE(msk->backlog_len, msk->backlog_len - moved);
 
 	if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags))
 		__mptcp_clean_una_wakeup(sk);

3/2 2026/07/25 19:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8022
							output: 21
							thoughts: 498
						

Thoughts:
**MPTCP Memory Management and Retransmission Enhancements - Time to Fuzz!**

Okay, so I've got a patch here that's making some pretty significant changes to the MPTCP core, specifically around memory management and retransmissions. It looks like we're adding new SNMP MIB items – `BacklogDrop`, `RcvPruned`, `OfoPruned` – to give us better visibility into how MPTCP is handling memory pressure. More importantly, this patch introduces actual memory limit checks at several points. I'm seeing `mptcp_over_limit` that drops packets when we exceed the limit, and `mptcp_prune_ofo_queue`, which gets rid of the out-of-order queue if we exceed the limit too. It's also making adjustments in the `__mptcp_add_backlog` and `__mptcp_retrans` functions to handle these new constraints.

This is a pretty fundamental shift in how the protocol functions, and because it directly impacts core logic with memory handling, I'm thinking this is definitely fuzz-worthy. 

Now, let's nail down what functions to focus on. Looks like we've got a whole list of modified functions, most of them static. Let's see...

Modified functions:
*   `mptcp_incoming_options`
*   `mptcp_prune_ofo_queue` (static)
*   `__mptcp_move_skb` (static)
*   `__mptcp_add_backlog` (static)
*   `__mptcp_move_skbs_from_subflow` (static)
*   `mptcp_move_skbs` (static)
*   `__mptcp_push_retrans` (static)
*   `__mptcp_retrans` (static)
*   `mptcp_release_cb` (static)

Hang on, `mptcp_incoming_options` is *non-static*, that's good news. That's a great place to start. I'll need to figure out what other non-static functions interact with these, but `mptcp_incoming_options` is a key candidate. I should also check if the static nature of something like `mptcp_release_cb` is a barrier; not that I expect it to be, but it's worth checking.

Okay, I'm going to dig into `net/mptcp/protocol.c` to look for those non-static functions that call any of these modified static ones. That's where the interesting fuzzing entry points likely lie.



4/2 2026/07/25 19:44 tool grepper
0m Args:
{
  "Expression": "mptcp_incoming_options"
}

Results:
{
  "Output": "include/net/mptcp.h=156=int mptcp_established_options(struct sock *sk, struct sk_buff *skb,\n--\ninclude/net/mptcp.h-158-\t\t\t      struct mptcp_out_options *opts);\ninclude/net/mptcp.h:159:bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb);\ninclude/net/mptcp.h-160-\n--\ninclude/net/mptcp.h=266=static inline bool mptcp_synack_options(const struct request_sock *req,\n--\ninclude/net/mptcp.h-272-\ninclude/net/mptcp.h:273:static inline bool mptcp_incoming_options(struct sock *sk,\ninclude/net/mptcp.h-274-\t\t\t\t\t  struct sk_buff *skb)\n--\nnet/ipv4/tcp_input.c=4884=void tcp_reset(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/tcp_input.c-4890-\t/* mptcp can't tell us to ignore reset pkts,\nnet/ipv4/tcp_input.c:4891:\t * so just ignore the return value of mptcp_incoming_options().\nnet/ipv4/tcp_input.c-4892-\t */\nnet/ipv4/tcp_input.c-4893-\tif (sk_is_mptcp(sk))\nnet/ipv4/tcp_input.c:4894:\t\tmptcp_incoming_options(sk, skb);\nnet/ipv4/tcp_input.c-4895-\n--\nnet/ipv4/tcp_input.c=5607=static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/tcp_input.c-5616-\t */\nnet/ipv4/tcp_input.c:5617:\tif (sk_is_mptcp(sk) \u0026\u0026 !mptcp_incoming_options(sk, skb)) {\nnet/ipv4/tcp_input.c-5618-\t\t__kfree_skb(skb);\n--\nnet/ipv4/tcp_input.c=7152=tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)\n--\nnet/ipv4/tcp_input.c-7379-\t\t\t */\nnet/ipv4/tcp_input.c:7380:\t\t\tif (sk_is_mptcp(sk) \u0026\u0026 !mptcp_incoming_options(sk, skb))\nnet/ipv4/tcp_input.c-7381-\t\t\t\tgoto discard;\n--\nnet/mptcp/options.c=1053=static void ack_update_msk(struct mptcp_sock *msk,\n--\nnet/mptcp/options.c-1078-\nnet/mptcp/options.c:1079:\t/* this assumes mptcp_incoming_options() is invoked after tcp_ack() */\nnet/mptcp/options.c-1080-\tif (after64(msk-\u003ewnd_end, snd_nxt))\n--\nnet/mptcp/options.c=1130=static bool mptcp_over_limit(struct sock *sk, struct sock *ssk,\n--\nnet/mptcp/options.c-1154- */\nnet/mptcp/options.c:1155:bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)\nnet/mptcp/options.c-1156-{\n"
}

5/2 2026/07/25 19:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 10067
							output: 21
							thoughts: 54
						

Thoughts:
**Analyzing the Multpath TCP Incoming Options Handling**

Okay, so I'm diving into how MPTCP incoming options are handled. It looks like `mptcp_incoming_options` is the function responsible, and it's being called from two key places within the TCP stack: `tcp_data_queue` and `tcp_rcv_state_process`. I need to understand the control flow here, to make sure it is working the way I intend.

Now, to get a better handle on the situation, I'll need to double-check my understanding of a couple of core functions. Specifically, I'll review `__mptcp_retrans` and `mptcp_release_cb`. They're probably crucial for understanding how retransmission and connection release play into this option processing, given where `mptcp_incoming_options` is sitting within the bigger picture. Understanding those is key to debugging and implementing any new feature in this area. Time to dig in...



6/2 2026/07/25 19:44 tool grepper
0m Args:
{
  "Expression": "__mptcp_retrans"
}

Results:
{
  "Output": "net/mptcp/pm.c=1063=static void mptcp_pm_subflows_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)\n--\nnet/mptcp/pm.c-1084-\t\t\t\tsubflow-\u003estale = 1;\nnet/mptcp/pm.c:1085:\t\t\t\t__mptcp_retransmit_pending_data(sk);\nnet/mptcp/pm.c-1086-\t\t\t\tMPTCP_INC_STATS(net, MPTCP_MIB_SUBFLOWSTALE);\n--\nnet/mptcp/protocol.c=2495=struct sock *mptcp_subflow_get_retrans(struct mptcp_sock *msk)\n--\nnet/mptcp/protocol.c-2530-\nnet/mptcp/protocol.c:2531:bool __mptcp_retransmit_pending_data(struct sock *sk)\nnet/mptcp/protocol.c-2532-{\n--\nnet/mptcp/protocol.c=2615=static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,\n--\nnet/mptcp/protocol.c-2664-\nnet/mptcp/protocol.c:2665:\tneed_push = (flags \u0026 MPTCP_CF_PUSH) \u0026\u0026 __mptcp_retransmit_pending_data(sk);\nnet/mptcp/protocol.c-2666-\tif (!dispose_it) {\n--\nnet/mptcp/protocol.c=2835=static int __mptcp_push_retrans(struct sock *sk, struct mptcp_data_frag *dfrag,\n--\nnet/mptcp/protocol.c-2896-\nnet/mptcp/protocol.c:2897:static void __mptcp_retrans(struct sock *sk)\nnet/mptcp/protocol.c-2898-{\n--\nnet/mptcp/protocol.c-2948-\t\t/* `already_sent` can be 0 for `dfrag` belonging to the RTX\nnet/mptcp/protocol.c:2949:\t\t *  queue due to __mptcp_retransmit_pending_data().\nnet/mptcp/protocol.c-2950-\t\t */\n--\nnet/mptcp/protocol.c=3106=static void mptcp_worker(struct work_struct *work)\n--\nnet/mptcp/protocol.c-3143-\tif (test_and_clear_bit(MPTCP_WORK_RTX, \u0026msk-\u003eflags))\nnet/mptcp/protocol.c:3144:\t\t__mptcp_retrans(sk);\nnet/mptcp/protocol.c-3145-\n--\nnet/mptcp/protocol.c=3786=static void mptcp_release_cb(struct sock *sk)\n--\nnet/mptcp/protocol.c-3818-\t\tif (flags \u0026 BIT(MPTCP_RETRANSMIT))\nnet/mptcp/protocol.c:3819:\t\t\t__mptcp_retrans(sk);\nnet/mptcp/protocol.c-3820-\t\tif (spool_bl \u0026\u0026 __mptcp_move_skbs(sk, \u0026skbs, \u0026moved)) {\n--\nnet/mptcp/protocol.h=808=void __mptcp_subflow_fully_established(struct mptcp_sock *msk,\n--\nnet/mptcp/protocol.h-810-\t\t\t\t       const struct mptcp_options_received *mp_opt);\nnet/mptcp/protocol.h:811:bool __mptcp_retransmit_pending_data(struct sock *sk);\nnet/mptcp/protocol.h-812-void mptcp_check_and_set_pending(struct sock *sk);\n"
}

7/2 2026/07/25 19:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 11340
							output: 21
							thoughts: 102
						

Thoughts:
**Analyzing the Multipath TCP Retransmission Process**

Okay, so I'm digging into how MPTCP handles retransmissions, and it looks like `__mptcp_retrans` is the key function. It's called from two places: `mptcp_worker` and `mptcp_release_cb`. Now, that `mptcp_release_cb` is ringing a bell. Ah, right, that's the release callback for MPTCP sockets!

Interesting... it's registered as `sk->sk_prot->release_cb`. I'll have to keep that association in mind. Need to understand the relationship between releasing the socket and retransmissions. Let's delve into the code for `mptcp_release_cb` in `net/mptcp/protocol.c` to see how it all fits together. This gives me a good starting point to dig through the code.



8/2 2026/07/25 19:44 tool grepper
0m Args:
{
  "Expression": "mptcp_release_cb"
}

Results:
{
  "Output": "net/mptcp/protocol.c=3773=void __mptcp_check_push(struct sock *sk, struct sock *ssk)\n--\nnet/mptcp/protocol.c-3785-/* processes deferred events and flush wmem */\nnet/mptcp/protocol.c:3786:static void mptcp_release_cb(struct sock *sk)\nnet/mptcp/protocol.c-3787-\t__must_hold(\u0026sk-\u003esk_lock.slock)\n--\nnet/mptcp/protocol.c=4189=static struct proto mptcp_prot = {\n--\nnet/mptcp/protocol.c-4202-\t.recvmsg\t= mptcp_recvmsg,\nnet/mptcp/protocol.c:4203:\t.release_cb\t= mptcp_release_cb,\nnet/mptcp/protocol.c-4204-\t.hash\t\t= mptcp_hash,\n"
}

9/2 2026/07/25 19:44 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 11917
							output: 19
							thoughts: 325
						

Thoughts:
**Patch Analysis & Fuzzing Strategy**

Okay, so I've been digging into this patch, and here's what I'm thinking. This `mptcp_release_cb` is the core callback for releasing sockets, and this patch has clearly made some key changes. They're tracking 'moved' and adjusting `msk->backlog_len` within it. Interesting. On top of that, `mptcp_incoming_options` is now checking for `mptcp_over_limit`, and `__mptcp_move_skb` is calling `mptcp_prune_ofo_queue`. Finally, the modification of `__mptcp_add_backlog` is checking the `msk->backlog_len > limit`, while the `__mptcp_retrans` function has been modified to retransmit multiple fragments.

Given the scope of these modifications, this is definitely worth fuzzing. I need to identify the key entry points. From a cursory glance, `mptcp_incoming_options` and `mptcp_worker` which then calls `__mptcp_retrans` seem like the obvious candidates. And, of course, that modified `mptcp_release_cb`, though it's marked as static. Hmm... it's a function pointer target from `release_sock`, so that changes things. Is that a good focus symbol? The fact that it's static gives me pause, but it's *definitely* a function pointer so it's a solid target.

Let's see: `mptcp_incoming_options` *is* non-static, which is good. That's a good place to start. Now, let me just double-check, is there *any* other non-static function impacted by the changes? `mptcp_recvmsg` isn't modified so that's out. Is `mptcp_worker` static? Yes, it is. Alright, back to `mptcp_incoming_options` and `mptcp_release_cb` as the primary focus, then.



10/2 2026/07/25 19:45 tool grepper
0m Args:
{
  "Expression": "mptcp_worker"
}

Results:
{
  "Output": "net/mptcp/protocol.c=1073=bool mptcp_schedule_work(struct sock *sk)\n--\nnet/mptcp/protocol.c-1077-\nnet/mptcp/protocol.c:1078:\t/* Get a reference on this socket, mptcp_worker() will release it.\nnet/mptcp/protocol.c:1079:\t * As mptcp_worker() might complete before us, we can not avoid\nnet/mptcp/protocol.c-1080-\t * a sock_hold()/sock_put() if schedule_work() returns false.\n--\nnet/mptcp/protocol.c=2615=static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,\n--\nnet/mptcp/protocol.c-2650-\t    (sock_flag(sk, SOCK_DEAD) || sock_flag(ssk, SOCK_DEAD))) {\nnet/mptcp/protocol.c:2651:\t\t/* ensure later check in mptcp_worker() will dispose the msk */\nnet/mptcp/protocol.c-2652-\t\tsock_set_flag(sk, SOCK_DEAD);\n--\nnet/mptcp/protocol.c=2782=static void mptcp_check_fastclose(struct mptcp_sock *msk)\n--\nnet/mptcp/protocol.c-2822-\nnet/mptcp/protocol.c:2823:\t/* the calling mptcp_worker will properly destroy the socket */\nnet/mptcp/protocol.c-2824-\tif (sock_flag(sk, SOCK_DEAD))\n--\nnet/mptcp/protocol.c=3070=static void mptcp_do_fastclose(struct sock *sk)\n--\nnet/mptcp/protocol.c-3105-\nnet/mptcp/protocol.c:3106:static void mptcp_worker(struct work_struct *work)\nnet/mptcp/protocol.c-3107-{\n--\nnet/mptcp/protocol.c=3155=static void __mptcp_init_sock(struct sock *sk)\n--\nnet/mptcp/protocol.c-3162-\tINIT_LIST_HEAD(\u0026msk-\u003ebacklog_list);\nnet/mptcp/protocol.c:3163:\tINIT_WORK(\u0026msk-\u003ework, mptcp_worker);\nnet/mptcp/protocol.c-3164-\tmsk-\u003eout_of_order_queue = RB_ROOT;\n"
}

11/2 2026/07/25 19:45 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 13366
							output: 23
							thoughts: 82
						

Thoughts:
**Analyzing MPTCP Data Structures**

Okay, so `mptcp_worker` is definitely static, that's clear. But I'm now digging deeper, and the question is, what about `mptcp_incoming_options`? Ah, that's non-static, so it's likely more widely accessible and potentially modified in various contexts. Good to keep in mind. Let's check `mptcp_established_options`, it looks like this one isn't modified which simplifies things somewhat. `mptcp_rcv_space_adjust` doesn't seem to be modified either, interesting. Since I am examining the potential for concurrency issues, I think I need to dig deeper into any call sites to `__mptcp_add_backlog`.



12/2 2026/07/25 19:45 tool grepper
0m Args:
{
  "Expression": "__mptcp_add_backlog"
}

Results:
{
  "Output": "net/mptcp/protocol.c=716=static void mptcp_dss_corruption(struct mptcp_sock *msk, struct sock *ssk)\n--\nnet/mptcp/protocol.c-723-\nnet/mptcp/protocol.c:724:static void __mptcp_add_backlog(struct sock *sk,\nnet/mptcp/protocol.c-725-\t\t\t\tstruct mptcp_subflow_context *subflow,\n--\nnet/mptcp/protocol.c=777=static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,\n--\nnet/mptcp/protocol.c-824-\t\t\t} else {\nnet/mptcp/protocol.c:825:\t\t\t\t__mptcp_add_backlog(sk, subflow, skb);\nnet/mptcp/protocol.c-826-\t\t\t}\n"
}

13/2 2026/07/25 19:45 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 13883
							output: 28
							thoughts: 28
						

Thoughts:
Okay, here's my interpretation of that:

**My Perspective on `__mptcp_move_skbs_from_subflow` and `mptcp_data_ready`**

Right, so I'm thinking about the data flow within Multipath TCP, and how we handle incoming data. `mptcp_data_ready`, that's the trigger, right? Something arrives, something signals that data is available on a subflow. Now, that's where `__mptcp_move_skbs_from_subflow` comes in. It's like the workhorse of the operation.

Essentially, I see `mptcp_data_ready` as the notification, the "Hey, there's work to be done!" signal. Then, `__mptcp_move_skbs_from_subflow` steps up and actually does the heavy lifting: taking the packets (the `skbs`) that are ready on a specific subflow and getting them where they need to go within the Multipath TCP connection. It's the mechanism, the concrete action taken to integrate the incoming data from a specific subflow into the larger picture of the MPTCP connection. So it's not a standalone function, it's inextricably linked to the event, the readiness for the packets and the actions that follow.



14/2 2026/07/25 19:45 tool grepper
0m Args:
{
  "Expression": "__mptcp_move_skbs_from_subflow"
}

Results:
{
  "Output": "net/mptcp/protocol.c=724=static void __mptcp_add_backlog(struct sock *sk,\n--\nnet/mptcp/protocol.c-776-\nnet/mptcp/protocol.c:777:static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,\nnet/mptcp/protocol.c-778-\t\t\t\t\t   struct sock *ssk, bool own_msk)\n--\nnet/mptcp/protocol.c=941=static bool move_skbs_to_msk(struct mptcp_sock *msk, struct sock *ssk)\n--\nnet/mptcp/protocol.c-945-\nnet/mptcp/protocol.c:946:\tmoved = __mptcp_move_skbs_from_subflow(msk, ssk, true);\nnet/mptcp/protocol.c-947-\t__mptcp_ofo_queue(msk);\n--\nnet/mptcp/protocol.c=987=void mptcp_data_ready(struct sock *sk, struct sock *ssk)\n--\nnet/mptcp/protocol.c-1005-\t} else {\nnet/mptcp/protocol.c:1006:\t\t__mptcp_move_skbs_from_subflow(msk, ssk, false);\nnet/mptcp/protocol.c-1007-\t}\n"
}

15/2 2026/07/25 19:45 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 14594
							output: 21
							thoughts: 82
						

Thoughts:
**Focusing on Key MPTCP Functions**

Okay, so I'm looking at this `mptcp_data_ready` function. The fact that it's *not* static is immediately interesting. That means it's potentially accessible outside its immediate scope, which makes it a good candidate for deeper investigation. Both `mptcp_data_ready` and `mptcp_incoming_options` have piqued my interest.

I need to confirm if `mptcp_data_ready` is, in fact, non-static. If it's not internal to a specific module, I want to see how it's being used across the codebase. I need to determine if it's exported and used elsewhere. Let's see if it's being accessed in other files within the project. That's where I need to start digging.



16/2 2026/07/25 19:45 tool grepper
0m Args:
{
  "Expression": "mptcp_data_ready"
}

Results:
{
  "Output": "net/mptcp/protocol.c=961=static void mptcp_rcv_rtt_update(struct mptcp_sock *msk,\n--\nnet/mptcp/protocol.c-986-\nnet/mptcp/protocol.c:987:void mptcp_data_ready(struct sock *sk, struct sock *ssk)\nnet/mptcp/protocol.c-988-{\n--\nnet/mptcp/protocol.h=956=static inline u64 mptcp_stamp(void)\n--\nnet/mptcp/protocol.h-960-\nnet/mptcp/protocol.h:961:void mptcp_data_ready(struct sock *sk, struct sock *ssk);\nnet/mptcp/protocol.h-962-bool mptcp_finish_join(struct sock *sk);\n--\nnet/mptcp/subflow.c=1506=static void subflow_data_ready(struct sock *sk)\n--\nnet/mptcp/subflow.c-1530-\tif (mptcp_subflow_data_available(sk)) {\nnet/mptcp/subflow.c:1531:\t\tmptcp_data_ready(parent, sk);\nnet/mptcp/subflow.c-1532-\n--\nnet/mptcp/subflow.c=1874=static void subflow_state_change(struct sock *sk)\n--\nnet/mptcp/subflow.c-1885-\tif (mptcp_subflow_data_available(sk))\nnet/mptcp/subflow.c:1886:\t\tmptcp_data_ready(parent, sk);\nnet/mptcp/subflow.c-1887-\telse if (unlikely(sk-\u003esk_err))\n"
}

17/2 2026/07/25 19:45 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15350
							output: 22
							thoughts: 108
						

Thoughts:
**Analyzing Data Readiness in Multipath TCP**

Okay, so I'm digging into how data readiness is handled in Multipath TCP. Specifically, I see `mptcp_data_ready` is called from two key functions: `subflow_data_ready` and `subflow_state_change`. My immediate thought is, are there *any* other entry points? I need to be comprehensive here.

Let me think… what about `mptcp_recvmsg`? That's a crucial function for receiving data, and I recall some recent modifications to `mptcp_move_skbs`. Ah, right, `mptcp_recvmsg` *does* call `mptcp_move_skbs`. That's important. Given the modification, I need to see if this is an impact point.

Okay, let's back up. Where else is `mptcp_move_skbs` called from? I need to trace *all* the callers of `mptcp_move_skbs` now to fully understand the scope of the change and its implications on data readiness and, potentially, the performance of the core functionality. This will provide a broader picture.



18/2 2026/07/25 19:45 tool grepper
0m Args:
{
  "Expression": "mptcp_move_skbs"
}

Results:
{
  "Output": "net/mptcp/protocol.c=724=static void __mptcp_add_backlog(struct sock *sk,\n--\nnet/mptcp/protocol.c-776-\nnet/mptcp/protocol.c:777:static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,\nnet/mptcp/protocol.c-778-\t\t\t\t\t   struct sock *ssk, bool own_msk)\n--\nnet/mptcp/protocol.c=941=static bool move_skbs_to_msk(struct mptcp_sock *msk, struct sock *ssk)\n--\nnet/mptcp/protocol.c-945-\nnet/mptcp/protocol.c:946:\tmoved = __mptcp_move_skbs_from_subflow(msk, ssk, true);\nnet/mptcp/protocol.c-947-\t__mptcp_ofo_queue(msk);\n--\nnet/mptcp/protocol.c=987=void mptcp_data_ready(struct sock *sk, struct sock *ssk)\n--\nnet/mptcp/protocol.c-1005-\t} else {\nnet/mptcp/protocol.c:1006:\t\t__mptcp_move_skbs_from_subflow(msk, ssk, false);\nnet/mptcp/protocol.c-1007-\t}\n--\nnet/mptcp/protocol.c=2210=static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied)\n--\nnet/mptcp/protocol.c-2263-\nnet/mptcp/protocol.c:2264:static bool __mptcp_move_skbs(struct sock *sk, struct list_head *skbs, u32 *delta)\nnet/mptcp/protocol.c-2265-{\n--\nnet/mptcp/protocol.c=2288=static bool mptcp_can_spool_backlog(struct sock *sk, struct list_head *skbs)\n--\nnet/mptcp/protocol.c-2305-\nnet/mptcp/protocol.c:2306:static bool mptcp_move_skbs(struct sock *sk)\nnet/mptcp/protocol.c-2307-{\n--\nnet/mptcp/protocol.c-2315-\t\tmptcp_data_unlock(sk);\nnet/mptcp/protocol.c:2316:\t\tenqueued |= __mptcp_move_skbs(sk, \u0026skbs, \u0026moved);\nnet/mptcp/protocol.c-2317-\n--\nnet/mptcp/protocol.c=2350=static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,\n--\nnet/mptcp/protocol.c-2393-\nnet/mptcp/protocol.c:2394:\t\tif (!list_empty(\u0026msk-\u003ebacklog_list) \u0026\u0026 mptcp_move_skbs(sk))\nnet/mptcp/protocol.c-2395-\t\t\tcontinue;\n--\nnet/mptcp/protocol.c=3786=static void mptcp_release_cb(struct sock *sk)\n--\nnet/mptcp/protocol.c-3819-\t\t\t__mptcp_retrans(sk);\nnet/mptcp/protocol.c:3820:\t\tif (spool_bl \u0026\u0026 __mptcp_move_skbs(sk, \u0026skbs, \u0026moved)) {\nnet/mptcp/protocol.c-3821-\t\t\t/* notify ack seq update */\n--\nnet/mptcp/protocol.c=4078=static int mptcp_ioctl(struct sock *sk, int cmd, int *karg)\n--\nnet/mptcp/protocol.c-4088-\t\tlock_sock(sk);\nnet/mptcp/protocol.c:4089:\t\tif (mptcp_move_skbs(sk))\nnet/mptcp/protocol.c-4090-\t\t\tmptcp_cleanup_rbuf(msk, 0);\n--\nnet/mptcp/protocol.c=4495=static struct sk_buff *mptcp_recv_skb(struct sock *sk, u32 *off)\n--\nnet/mptcp/protocol.c-4501-\tif (!list_empty(\u0026msk-\u003ebacklog_list))\nnet/mptcp/protocol.c:4502:\t\tmptcp_move_skbs(sk);\nnet/mptcp/protocol.c-4503-\n"
}

19/2 2026/07/25 19:45 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 16919
							output: 21
							thoughts: 125
						

Thoughts:
Okay, let's break this down.

**Diving into the MPTCP Data Flow**

Right, so I'm looking at the multi-path TCP implementation and trying to understand how data moves around. It seems like `mptcp_recvmsg` and `mptcp_ioctl` are key entry points, both of which eventually call `mptcp_move_skbs`. That `mptcp_recvmsg` function looks like a particularly good place to focus on as a starting point.

Now, I also see that `__mptcp_retrans` is triggered, and it's called from both `mptcp_worker` and `mptcp_release_cb`. I'll want to remember this since retransmissions are critical. `mptcp_worker` itself is a workqueue function, that's important to remember in tracing the path. Now the question is, what triggers `mptcp_worker`? I need to find the non-static functions to see how the workqueue is scheduled and executed.

Ah, here's `mptcp_schedule_work` which seems to be non-static. This could be a critical point of entry and orchestration for MPTCP operations. This is a good lead!



20/2 2026/07/25 19:45 tool grepper
0m Args:
{
  "Expression": "mptcp_schedule_work"
}

Results:
{
  "Output": "net/mptcp/options.c=1155=bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)\n--\nnet/mptcp/options.c-1193-\t\t\tWRITE_ONCE(msk-\u003ercv_fastclose, true);\nnet/mptcp/options.c:1194:\t\t\tmptcp_schedule_work((struct sock *)msk);\nnet/mptcp/options.c-1195-\t\t\tMPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSERX);\n--\nnet/mptcp/options.c-1250-\t\t    mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64))\nnet/mptcp/options.c:1251:\t\t\tmptcp_schedule_work((struct sock *)msk);\nnet/mptcp/options.c-1252-\n--\nnet/mptcp/pm.c=592=static bool mptcp_pm_schedule_work(struct mptcp_sock *msk,\n--\nnet/mptcp/pm.c-600-\tmsk-\u003epm.status |= BIT(new_status);\nnet/mptcp/pm.c:601:\tmptcp_schedule_work((struct sock *)msk);\nnet/mptcp/pm.c-602-\treturn true;\n--\nnet/mptcp/protocol.c=941=static bool move_skbs_to_msk(struct mptcp_sock *msk, struct sock *ssk)\n--\nnet/mptcp/protocol.c-956-\tif (mptcp_pending_data_fin(sk, NULL))\nnet/mptcp/protocol.c:957:\t\tmptcp_schedule_work(sk);\nnet/mptcp/protocol.c-958-\treturn moved;\n--\nnet/mptcp/protocol.c=1061=static void mptcp_reset_rtx_timer(struct sock *sk)\n--\nnet/mptcp/protocol.c-1072-\nnet/mptcp/protocol.c:1073:bool mptcp_schedule_work(struct sock *sk)\nnet/mptcp/protocol.c-1074-{\n--\nnet/mptcp/protocol.c=1137=static void __mptcp_clean_una(struct sock *sk)\n--\nnet/mptcp/protocol.c-1192-\tif (mptcp_pending_data_fin_ack(sk))\nnet/mptcp/protocol.c:1193:\t\tmptcp_schedule_work(sk);\nnet/mptcp/protocol.c-1194-}\n--\nnet/mptcp/protocol.c=1793=static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool first)\n--\nnet/mptcp/protocol.c-1855-\t\t    msk-\u003esnd_nxt + 1 == msk-\u003ewrite_seq)\nnet/mptcp/protocol.c:1856:\t\t\tmptcp_schedule_work(sk);\nnet/mptcp/protocol.c-1857-\t}\n--\nnet/mptcp/protocol.c=2462=static void mptcp_retransmit_timer(struct timer_list *t)\n--\nnet/mptcp/protocol.c-2470-\t\tif (!test_and_set_bit(MPTCP_WORK_RTX, \u0026msk-\u003eflags))\nnet/mptcp/protocol.c:2471:\t\t\tmptcp_schedule_work(sk);\nnet/mptcp/protocol.c-2472-\t} else {\n--\nnet/mptcp/protocol.c=2480=static void mptcp_tout_timer(struct timer_list *t)\n--\nnet/mptcp/protocol.c-2485-\nnet/mptcp/protocol.c:2486:\tmptcp_schedule_work(sk);\nnet/mptcp/protocol.c-2487-\tsock_put(sk);\n--\nnet/mptcp/protocol.c=3256=void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)\n--\nnet/mptcp/protocol.c-3277-\t\t\tWRITE_ONCE(mptcp_sk(sk)-\u003esnd_una, mptcp_sk(sk)-\u003esnd_nxt);\nnet/mptcp/protocol.c:3278:\t\t\tmptcp_schedule_work(sk);\nnet/mptcp/protocol.c-3279-\t\t} else {\n--\nnet/mptcp/protocol.h=962=bool mptcp_finish_join(struct sock *sk);\nnet/mptcp/protocol.h:963:bool mptcp_schedule_work(struct sock *sk);\nnet/mptcp/protocol.h-964-int mptcp_setsockopt(struct sock *sk, int level, int optname,\n--\nnet/mptcp/subflow.c=430=void mptcp_subflow_reset(struct sock *ssk)\n--\nnet/mptcp/subflow.c-446-\tif (!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, \u0026mptcp_sk(sk)-\u003eflags))\nnet/mptcp/subflow.c:447:\t\tmptcp_schedule_work(sk);\nnet/mptcp/subflow.c-448-\n--\nnet/mptcp/subflow.c=1109=static enum mapping_status get_mapping_status(struct sock *ssk,\n--\nnet/mptcp/subflow.c-1175-\t\t\tif (updated)\nnet/mptcp/subflow.c:1176:\t\t\t\tmptcp_schedule_work((struct sock *)msk);\nnet/mptcp/subflow.c-1177-\n--\nnet/mptcp/subflow.c=1289=static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ssk)\n--\nnet/mptcp/subflow.c-1302-\tif (!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, \u0026msk-\u003eflags))\nnet/mptcp/subflow.c:1303:\t\tmptcp_schedule_work(sk);\nnet/mptcp/subflow.c-1304-\n--\nnet/mptcp/subflow.c-1311-\t\t\t\t      subflow-\u003emap_data_len, true))\nnet/mptcp/subflow.c:1312:\t\tmptcp_schedule_work(sk);\nnet/mptcp/subflow.c-1313-}\n--\nnet/mptcp/subflow.c=2004=static void subflow_ulp_release(struct sock *ssk)\n--\nnet/mptcp/subflow.c-2025-\t\t\t\t\t\t  \u0026mptcp_sk(sk)-\u003eflags))\nnet/mptcp/subflow.c:2026:\t\t\tmptcp_schedule_work(sk);\nnet/mptcp/subflow.c-2027-\t\tsock_put(sk);\n"
}

21/2 2026/07/25 19:45 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 19188
							output: 18
							thoughts: 81
						

Thoughts:
Okay, let's dive into this. Here's how I'm thinking about navigating this kernel module:

**Investigating MPTCP Entry Points and Configuration**

Right, so `mptcp_incoming_options`, `mptcp_data_ready`, and `mptcp_recvmsg`... these feel like the obvious starting points for understanding the entry points of this MPTCP functionality. I need to get a handle on how these functions are hooked into the networking stack. Before I dig too deeply into the code, I need to make sure I'm not missing some critical configuration requirement. Let's see if there are any specific kernel `CONFIG` options that must be enabled for this MPTCP feature to be active.

Since the code is clearly in `net/mptcp/`, that simplifies the search. I'll check the associated Kconfig files – either the one directly in `net/mptcp/Kconfig`, or failing that, I'll broaden the search to the main `net/Kconfig` file. That's usually where the more high-level configurations are defined. I'm expecting to find some dependencies or flags that control the compilation and activation of this MPTCP functionality.



22/2 2026/07/25 19:46 tool grepper
0m Args:
{
  "Expression": "config 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"
}

23/2 2026/07/25 19:46 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 19768
							output: 34
							thoughts: 39
						

Thoughts:
Okay, let's break this down.

**MPTCP Configuration Dependencies**

Alright, so I see `MPTCP` is the configuration option we're dealing with. My immediate thought is, what's its foundation? A quick mental scan tells me that `MPTCP` relies on the `INET` configuration option. Let's make sure I'm correct and take a deeper look at the dependencies. I know the Kconfig file for `MPTCP` should have the answers, so I'll jump into `net/mptcp/Kconfig` to check out those dependencies and confirm my initial assessment.



24/2 2026/07/25 19:46 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"
}

25/2 2026/07/25 19:46 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 20218
							output: 20
							thoughts: 542
						

Thoughts:
**MPTCP Configuration and Core Logic Review**

Okay, so I'm focusing on the configuration and key logic points for MultiPath TCP (MPTCP). The central configuration element is clearly `MPTCP`, which I'll add to the `EnableConfigs`. I don't think I need to bring in `MPTCP_IPV6` just yet, as `MPTCP` itself should be the core enabler.

Let me just quickly confirm that `MPTCP` is a boolean and not a tristate, and yes, it's a bool, so just enabling it is enough.

Now, let's nail down the key functions. I've got a shortlist:

*   `mptcp_incoming_options`: This calls `mptcp_over_limit`.
*   `mptcp_data_ready`: Which calls `__mptcp_move_skbs_from_subflow`. That in turn calls `__mptcp_add_backlog` and `__mptcp_move_skb`, and finally `mptcp_prune_ofo_queue`.
*   `mptcp_recvmsg`: This function is linked to `mptcp_move_skbs` which in turn calls `__mptcp_move_skbs`.

I should check the `__mptcp_retrans` function. It looks like it's called by `mptcp_release_cb` and `mptcp_worker`. `mptcp_release_cb` is the release callback for the socket, triggered when the socket lock is released. And `mptcp_worker` is a workqueue function. Is there anything outside of MPTCP calling that `mptcp_release_cb`? I see `release_sock` calls it. This is a core networking function, not specific to MPTCP, so these three functions are still the key ones.

Just to be absolutely sure, I'll quickly verify the export status of the focus functions. `mptcp_incoming_options` is in `net/mptcp/options.c` and is indeed exported in `include/net/mptcp.h`. Great. And `mptcp_data_ready` is in `net/mptcp/protocol.c` and is exported in `net/mptcp/protocol.h`. Now, `mptcp_recvmsg`... Wait, I need to confirm if it's static.



26/2 2026/07/25 19:46 tool grepper
0m Args:
{
  "Expression": "mptcp_recvmsg"
}

Results:
{
  "Output": "net/mptcp/protocol.c=2112=static void mptcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb)\n--\nnet/mptcp/protocol.c-2122-\nnet/mptcp/protocol.c:2123:static int __mptcp_recvmsg_mskq(struct sock *sk, struct msghdr *msg,\nnet/mptcp/protocol.c-2124-\t\t\t\tsize_t len, int flags, int copied_total,\n--\nnet/mptcp/protocol.c=2329=static unsigned int mptcp_inq_hint(const struct sock *sk)\n--\nnet/mptcp/protocol.c-2349-\nnet/mptcp/protocol.c:2350:static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,\nnet/mptcp/protocol.c-2351-\t\t\t int flags)\n--\nnet/mptcp/protocol.c-2382-\nnet/mptcp/protocol.c:2383:\t\tbytes_read = __mptcp_recvmsg_mskq(sk, msg, len - copied, flags,\nnet/mptcp/protocol.c-2384-\t\t\t\t\t\t  copied, \u0026tss, \u0026cmsg_flags,\n--\nnet/mptcp/protocol.c=4189=static struct proto mptcp_prot = {\n--\nnet/mptcp/protocol.c-4201-\t.ioctl\t\t= mptcp_ioctl,\nnet/mptcp/protocol.c:4202:\t.recvmsg\t= mptcp_recvmsg,\nnet/mptcp/protocol.c-4203-\t.release_cb\t= mptcp_release_cb,\n"
}

27/2 2026/07/25 19:46 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 21777
							output: 51
							thoughts: 89
						

Thoughts:
**Digging into the MPTCP Code**

Right, so `mptcp_recvmsg` is declared as `static`. That immediately limits its direct usability, unfortunately. My goal is to find a function, ideally non-static, that either calls `mptcp_recvmsg` or is somehow directly related to it within the MultiPath TCP implementation. Since it's registered in `mptcp_prot`, my thinking is to investigate `net/mptcp/protocol.c` first. I'll need to look through the non-static functions in that file, as those are the entry points I'm likely after. This feels like the most logical next step to understand its interaction within the MPTCP architecture. Let's see what we can find!



28/2 2026/07/25 19:46 tool grepper
0m Args:
{
  "Expression": "^[a-zA-Z_][a-zA-Z0-9_]* mptcp_",
  "PathPrefix": "net/mptcp/protocol.c"
}

Results:
{
  "Output": "net/mptcp/protocol.c=961=static void mptcp_rcv_rtt_update(struct mptcp_sock *msk,\n--\nnet/mptcp/protocol.c-986-\nnet/mptcp/protocol.c:987:void mptcp_data_ready(struct sock *sk, struct sock *ssk)\nnet/mptcp/protocol.c-988-{\n--\nnet/mptcp/protocol.c=1061=static void mptcp_reset_rtx_timer(struct sock *sk)\n--\nnet/mptcp/protocol.c-1072-\nnet/mptcp/protocol.c:1073:bool mptcp_schedule_work(struct sock *sk)\nnet/mptcp/protocol.c-1074-{\n--\nnet/mptcp/protocol.c=1237=mptcp_carve_data_frag(const struct mptcp_sock *msk, struct page_frag *pfrag,\n--\nnet/mptcp/protocol.c-1254-\nnet/mptcp/protocol.c:1255:struct mptcp_sendmsg_info {\nnet/mptcp/protocol.c-1256-\tint mss_now;\n--\nnet/mptcp/protocol.c=1528=struct subflow_send_info {\n--\nnet/mptcp/protocol.c-1532-\nnet/mptcp/protocol.c:1533:void mptcp_subflow_set_active(struct mptcp_subflow_context *subflow)\nnet/mptcp/protocol.c-1534-{\n--\nnet/mptcp/protocol.c-1541-\nnet/mptcp/protocol.c:1542:bool mptcp_subflow_active(struct mptcp_subflow_context *subflow)\nnet/mptcp/protocol.c-1543-{\n--\nnet/mptcp/protocol.c=1645=static void mptcp_update_post_push(struct mptcp_sock *msk,\n--\nnet/mptcp/protocol.c-1671-\nnet/mptcp/protocol.c:1672:void mptcp_check_and_set_pending(struct sock *sk)\nnet/mptcp/protocol.c-1673-{\n--\nnet/mptcp/protocol.c=2615=static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,\n--\nnet/mptcp/protocol.c-2720-\nnet/mptcp/protocol.c:2721:void mptcp_close_ssk(struct sock *sk, struct sock *ssk,\nnet/mptcp/protocol.c-2722-\t\t     struct mptcp_subflow_context *subflow)\n--\nnet/mptcp/protocol.c=2897=static void __mptcp_retrans(struct sock *sk)\n--\nnet/mptcp/protocol.c-3016- */\nnet/mptcp/protocol.c:3017:void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout)\nnet/mptcp/protocol.c-3018-{\n--\nnet/mptcp/protocol.c=3238=static void __mptcp_clear_xmit(struct sock *sk)\n--\nnet/mptcp/protocol.c-3247-\nnet/mptcp/protocol.c:3248:void mptcp_cancel_work(struct sock *sk)\nnet/mptcp/protocol.c-3249-{\n--\nnet/mptcp/protocol.c-3255-\nnet/mptcp/protocol.c:3256:void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)\nnet/mptcp/protocol.c-3257-{\n--\nnet/mptcp/protocol.c-3290-\nnet/mptcp/protocol.c:3291:void mptcp_set_state(struct sock *sk, int state)\nnet/mptcp/protocol.c-3292-{\n--\nnet/mptcp/protocol.c=3852=static void schedule_3rdack_retransmission(struct sock *ssk)\n--\nnet/mptcp/protocol.c-3873-\nnet/mptcp/protocol.c:3874:void mptcp_subflow_process_delegated(struct sock *ssk, long status)\nnet/mptcp/protocol.c-3875-{\n--\nnet/mptcp/protocol.c=3913=static int mptcp_get_port(struct sock *sk, unsigned short snum)\n--\nnet/mptcp/protocol.c-3923-\nnet/mptcp/protocol.c:3924:void mptcp_finish_connect(struct sock *ssk)\nnet/mptcp/protocol.c-3925-{\n--\nnet/mptcp/protocol.c-3947-\nnet/mptcp/protocol.c:3948:void mptcp_sock_graft(struct sock *sk, struct socket *parent)\nnet/mptcp/protocol.c-3949-{\n--\nnet/mptcp/protocol.c=3959=static void mptcp_sock_check_graft(struct sock *sk, struct sock *ssk)\n--\nnet/mptcp/protocol.c-3972-\nnet/mptcp/protocol.c:3973:bool mptcp_finish_join(struct sock *ssk)\nnet/mptcp/protocol.c-3974-{\n"
}

29/2 2026/07/25 19:46 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 23545
							output: 25
							thoughts: 729
						

Thoughts:
**Focus Symbol Selection for MPTCP Receive and Retransmission Paths**

Okay, so I'm thinking about the most effective focus symbols for fuzzing this MPTCP code. Since `mptcp_data_ready` and `mptcp_incoming_options` are non-static, my initial gut feeling is that they are good starting points for the receive path modifications. I also looked at `mptcp_subflow_process_delegated` but found it wasn't modified. That leaves me leaning towards `mptcp_incoming_options` and `mptcp_data_ready` to cover the receive path.

But wait, I need to consider the retransmission path! `__mptcp_retrans` is triggered by `mptcp_worker` and `mptcp_release_cb`. I needed to think about a non-static function that triggers retransmission. `mptcp_schedule_work` leads to `mptcp_worker`. However, `mptcp_release_cb` is called synchronously when the socket lock is released, which is done by `release_sock(sk)`. That's a core networking function, and probably not ideal as a focus symbol.

Coming back to the receive path, fuzzing `mptcp_incoming_options` and `mptcp_data_ready` sounds solid, but what about `mptcp_recvmsg`? It *is* the `recvmsg` handler for MPTCP, but it's static. The instructions say to prefer non-static API entrypoints. However, it *is* an API entrypoint, despite the static keyword. I'm torn, but ultimately, `mptcp_incoming_options` and `mptcp_data_ready` are directly related to the code changes, and non-static, so I'll prioritize them.

Let's dig deeper into `mptcp_incoming_options`. Yes, it's non-static, and *is* directly modified! Checking the `net/mptcp/options.c` code, it's pretty clear that `mptcp_incoming_options` contains the key check: `return !mptcp_over_limit(subflow->conn, sk, skb);`. It's a perfect focus symbol.

Now for `mptcp_data_ready`. It calls `__mptcp_move_skbs_from_subflow`, which, in turn, calls `__mptcp_add_backlog` and `__mptcp_move_skb`. Both of these functions are modified in this patch. So, `mptcp_data_ready` is also a perfect focus symbol, especially when considering the modifications made in the patch.

I will set aside other focus symbols such as `mptcp_worker`, since it is static. I will look for other non-static functions for the retransmission part. What about `mptcp_check_and_set_pending`? That's another avenue to investigate, but for now, I'm confident in prioritizing `mptcp_incoming_options` and `mptcp_data_ready` as the key focus symbols.



30/2 2026/07/25 19:46 tool grepper
0m Args:
{
  "Expression": "mptcp_check_and_set_pending"
}

Results:
{
  "Output": "net/mptcp/protocol.c=1645=static void mptcp_update_post_push(struct mptcp_sock *msk,\n--\nnet/mptcp/protocol.c-1671-\nnet/mptcp/protocol.c:1672:void mptcp_check_and_set_pending(struct sock *sk)\nnet/mptcp/protocol.c-1673-{\n--\nnet/mptcp/protocol.c=2897=static void __mptcp_retrans(struct sock *sk)\n--\nnet/mptcp/protocol.c-2998-reset_timer:\nnet/mptcp/protocol.c:2999:\tmptcp_check_and_set_pending(sk);\nnet/mptcp/protocol.c-3000-\n--\nnet/mptcp/protocol.h=811=bool __mptcp_retransmit_pending_data(struct sock *sk);\nnet/mptcp/protocol.h:812:void mptcp_check_and_set_pending(struct sock *sk);\nnet/mptcp/protocol.h-813-void __mptcp_push_pending(struct sock *sk, unsigned int flags);\n--\nnet/mptcp/sockopt.c=660=static int __mptcp_setsockopt_sol_tcp_cork(struct mptcp_sock *msk, int val)\n--\nnet/mptcp/sockopt.c-674-\tif (!val)\nnet/mptcp/sockopt.c:675:\t\tmptcp_check_and_set_pending(sk);\nnet/mptcp/sockopt.c-676-\n--\nnet/mptcp/sockopt.c=680=static int __mptcp_setsockopt_sol_tcp_nodelay(struct mptcp_sock *msk, int val)\n--\nnet/mptcp/sockopt.c-694-\tif (val)\nnet/mptcp/sockopt.c:695:\t\tmptcp_check_and_set_pending(sk);\nnet/mptcp/sockopt.c-696-\treturn 0;\n"
}

31/2 2026/07/25 19:46 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 25553
							output: 25
							thoughts: 105
						

Thoughts:
Okay, let me break this down.

**Analyzing MPTCP Retransmission Logic**

Right, so I'm tracing the flow here. It looks like `mptcp_check_and_set_pending` is *called* from `__mptcp_retrans`, not the other way around. That's good to know, essential for understanding the timing. But what about that pesky `mptcp_retransmit_timer`? It's static, so that's a different path, needs a separate look, but the immediate calling path from the retransmit logic is clear. Then I see `mptcp_pm_subflows_chk_stale`, that calls `__mptcp_retransmit_pending_data` and that's the one I need to focus on. Wait, `__mptcp_retransmit_pending_data` is *non-static*! Okay, that's crucial. Knowing it's non-static means it's accessible from other modules, something I'll need to keep in mind when I map the dependencies. I need to note where that's called from, now.



32/2 2026/07/25 19:46 tool grepper
0m Args:
{
  "Expression": "__mptcp_retransmit_pending_data"
}

Results:
{
  "Output": "net/mptcp/pm.c=1063=static void mptcp_pm_subflows_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)\n--\nnet/mptcp/pm.c-1084-\t\t\t\tsubflow-\u003estale = 1;\nnet/mptcp/pm.c:1085:\t\t\t\t__mptcp_retransmit_pending_data(sk);\nnet/mptcp/pm.c-1086-\t\t\t\tMPTCP_INC_STATS(net, MPTCP_MIB_SUBFLOWSTALE);\n--\nnet/mptcp/protocol.c=2495=struct sock *mptcp_subflow_get_retrans(struct mptcp_sock *msk)\n--\nnet/mptcp/protocol.c-2530-\nnet/mptcp/protocol.c:2531:bool __mptcp_retransmit_pending_data(struct sock *sk)\nnet/mptcp/protocol.c-2532-{\n--\nnet/mptcp/protocol.c=2615=static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,\n--\nnet/mptcp/protocol.c-2664-\nnet/mptcp/protocol.c:2665:\tneed_push = (flags \u0026 MPTCP_CF_PUSH) \u0026\u0026 __mptcp_retransmit_pending_data(sk);\nnet/mptcp/protocol.c-2666-\tif (!dispose_it) {\n--\nnet/mptcp/protocol.c=2897=static void __mptcp_retrans(struct sock *sk)\n--\nnet/mptcp/protocol.c-2948-\t\t/* `already_sent` can be 0 for `dfrag` belonging to the RTX\nnet/mptcp/protocol.c:2949:\t\t *  queue due to __mptcp_retransmit_pending_data().\nnet/mptcp/protocol.c-2950-\t\t */\n--\nnet/mptcp/protocol.h=808=void __mptcp_subflow_fully_established(struct mptcp_sock *msk,\n--\nnet/mptcp/protocol.h-810-\t\t\t\t       const struct mptcp_options_received *mp_opt);\nnet/mptcp/protocol.h:811:bool __mptcp_retransmit_pending_data(struct sock *sk);\nnet/mptcp/protocol.h-812-void mptcp_check_and_set_pending(struct sock *sk);\n"
}

33/2 2026/07/25 19:46 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 26583
							output: 118
							thoughts: 854
						

Thoughts:
**Analyzing the MPTCP Patch for Fuzzing Opportunities**

Okay, let's break this down. My initial thought was that `__mptcp_retransmit_pending_data` would be interesting, but it's non-static, so the initial assumption was not right, but it doesn't even call `__mptcp_retrans`, which is the function that was actually modified. That's a bit of a curveball. After reviewing all the functions, the code modifies a bunch of functions: `mptcp_incoming_options`, `mptcp_prune_ofo_queue`, `__mptcp_move_skb`, `__mptcp_add_backlog`, `__mptcp_move_skbs_from_subflow`, `mptcp_move_skbs`, `__mptcp_push_retrans`, `__mptcp_retrans`, and `mptcp_release_cb`.

`__mptcp_retrans` is called by `mptcp_worker` and `mptcp_release_cb`. `mptcp_release_cb` is the release callback for the socket, so it's triggered when the socket lock is released. Essentially, any function that locks and unlocks the socket could potentially trigger it. That makes fuzzing `mptcp_recvmsg` via the `recvmsg` syscall or `mptcp_sendmsg` via the `sendmsg` syscall a viable strategy. But looking deeper and tracing calls, I think there are better approaches.

I need to focus on the non-static functions, which are the ones directly exposed to the syscalls or other kernel components. So I want to include `mptcp_incoming_options` and `mptcp_data_ready`. `mptcp_ioctl` looked interesting since it calls `mptcp_move_skbs`, but then I realized it's static. Let's see... `mptcp_recvmsg` is static, too. Okay, so finding any non-static function that calls the static `mptcp_move_skbs` isn't going to get me anywhere. `mptcp_move_skbs` is only called by a bunch of static functions and `mptcp_release_cb`, which, as mentioned, is triggered indirectly. So, it looks like `mptcp_incoming_options` and `mptcp_data_ready` are the best bets as focus symbols.

Let me double-check. Yup, `mptcp_data_ready` is non-static (`void mptcp_data_ready(struct sock *sk, struct sock *ssk)` in `net/mptcp/protocol.c`), and `mptcp_incoming_options` is non-static too (`bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)` in `net/mptcp/options.c`).

So, the patch mainly modifies these functions: `mptcp_incoming_options` (non-static), `mptcp_prune_ofo_queue` (static), `__mptcp_move_skb` (static), `__mptcp_add_backlog` (static), `__mptcp_move_skbs_from_subflow` (static), `mptcp_move_skbs` (static), `__mptcp_push_retrans` (static), `__mptcp_retrans` (static), and `mptcp_release_cb` (static).

So `mptcp_incoming_options` and `mptcp_data_ready` are still the best symbols to concentrate on. Wait, `mptcp_data_ready` actually calls `__mptcp_move_skbs_from_subflow`. Hmm, it's starting to look like these might be the best targets, and the only ones I can really leverage in a targeted way. Let's make sure that's true...

So what config option do I need to enable? Just `MPTCP`, seems straightforward.

**Final assessment:** This patch is worth fuzzing. I should focus on `mptcp_incoming_options` and `mptcp_data_ready`. I will enable the `MPTCP` configuration option. The patch modifies critical MPTCP logic for memory management and retransmissions. Specifically, I'm expecting fuzzing to expose issues around the new memory limit checks which drop packets or prune queues, and the refactoring of retransmission logic. This is core networking code, and any issues here have serious consequences.



34/2 2026/07/25 19:47 tool set-results
0m Args:
{
  "EnableConfigs": [
    "MPTCP"
  ],
  "FocusSymbols": [
    "mptcp_incoming_options",
    "mptcp_data_ready"
  ],
  "Reasoning": "The patch modifies the core MPTCP protocol logic to handle memory constraints and retransmissions. It introduces new memory limit checks that drop packets or prune the out-of-order queue when limits are exceeded, and refactors the retransmission logic to handle multiple fragments. These are functional changes to reachable core networking code.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "MPTCP"
  ],
  "FocusSymbols": [
    "mptcp_incoming_options",
    "mptcp_data_ready"
  ],
  "Reasoning": "The patch modifies the core MPTCP protocol logic to handle memory constraints and retransmissions. It introduces new memory limit checks that drop packets or prune the out-of-order queue when limits are exceeded, and refactors the retransmission logic to handle multiple fragments. These are functional changes to reachable core networking code.",
  "WorthFuzzing": true
}

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)