[PATCH net 4/5] mptcp: fastopen: only mark MPTFO subflows with SYN data

From: Matthieu Baerts (NGI0)

Date: Tue Jul 28 2026 - 13:59:15 EST


From: Wyatt Feng <bronzed_45_vested@xxxxxxxxxx>

Passive TCP Fast Open accepts a valid-cookie SYN even when it carries
no data. In that case the child socket's receive queue is intentionally
left empty.

mptcp_fastopen_subflow_synack_set_params() set is_mptfo before checking
for queued SYN data. That made data-less TFO SYNs hit a WARN and, if
the warning was non-fatal, left stale MPTFO state behind. The stale
flag could later trigger a state-confusion bug in
check_fully_established().

Only mark the subflow as MPTFO after confirming that a SYN-data skb is
present. Return quietly when the receive queue is empty.

Fixes: 36b122baf6a8 ("mptcp: add subflow_v(4,6)_send_synack()")
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Yuan Tan <yuantan098@xxxxxxxxx>
Reported-by: Yifan Wu <yifanwucs@xxxxxxxxx>
Reported-by: Juefei Pu <tomapufckgml@xxxxxxxxx>
Reported-by: Zhengchuan Liang <zcliangcn@xxxxxxxxx>
Reported-by: Xin Liu <bird@xxxxxxxxxx>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Wyatt Feng <bronzed_45_vested@xxxxxxxxxx>
Signed-off-by: Ren Wei <n05ec@xxxxxxxxxx>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@xxxxxxxxxx>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@xxxxxxxxxx>
---
Cc: Dmytro Shytyi <dmytro@xxxxxxxxxx>
Note: a v1 has already been shared alone on the netdev ML:
https://patch.msgid.link/81f26b8fddd59ebb6cecc417fb138d9ff5214e08.1780458440.git.bronzed_45_vested@xxxxxxxxxx
---
net/mptcp/fastopen.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c
index 082c46c0f50e..f717750906ff 100644
--- a/net/mptcp/fastopen.c
+++ b/net/mptcp/fastopen.c
@@ -24,12 +24,13 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subf
sk = subflow->conn;
tp = tcp_sk(ssk);

- subflow->is_mptfo = 1;
-
+ /* A valid TFO cookie does not guarantee SYN data. */
skb = skb_peek(&ssk->sk_receive_queue);
- if (WARN_ON_ONCE(!skb))
+ if (!skb)
return;

+ subflow->is_mptfo = 1;
+
/* dequeue the skb from sk receive queue */
__skb_unlink(skb, &ssk->sk_receive_queue);
skb_ext_reset(skb);

--
2.53.0