[PATCH net v4] mptcp: do not use Fast Open on MP_JOIN subflows
flat view
WARM1d
From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Date: 2026-10-30 22:03:58
Also in:
lkml, mptcp, stable
Subsystem:
networking [general], networking [mptcp], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthieu Baerts, Mat Martineau, Linus Torvalds
From: Yilin Zhang <redacted> tcp_fastopen_create_child() hands the SYN packet itself to subflow_syn_recv_sock(). For an MP_JOIN request this takes the fatal fallback: the cloned child is destroyed and handed back with drop_req flagged, but tcp_fastopen_create_child() does not check the flag and queues it, so accept() can expose the freed child. MP_JOIN cannot use Fast Open: data on a subflow requires the completed HMAC exchange (RFC 8684, sec. 3.2). Refuse it (only the TFO path passes a SYN skb here) and let tcp_conn_request() fall back to the regular MP_JOIN handshake; also strip the Fast Open cookie from MP_JOIN SYN/ACKs. Fixes: 90bf45134d55 ("mptcp: add new sock flag to deal with join subflows") Cc: <redacted> Reported-by: Kimi Security Team <redacted> Suggested-by: Jiayuan Chen <jiayuan.chen@linux.dev> Suggested-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Yilin Zhang <redacted> [ Moving code to avoid clearing TS and consolidating checks. ] Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> --- Note: I'm taking over this series because the v3 got lost a bit, the v4 only contains minor modifications, no need to delay this fix any longer. v4: - Disable TFO without clearing tstamp_ok. - Moving SYN check inside the existing MPJ section. - Check for SYN only. (Paolo) v3: - https://lore.kernel.org/20260920061904.3575780-1-yilinzhang@moonshot.ai (local) v2: - https://lore.kernel.org/20260903094010.4066892-1-yilinzhang@moonshot.ai (local) v1: - https://lore.kernel.org/20260902121247.3248539-1-yilinzhang@moonshot.ai (local) --- net/mptcp/subflow.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 78e886b20258..00677fb3efcd 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c@@ -379,6 +379,10 @@ static void subflow_prep_synack(const struct sock *sk, struct request_sock *req, struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct inet_request_sock *ireq = inet_rsk(req); + /* MP_JOIN cannot use TFO, do not send a cookie in the SYN/ACK */ + if (foc && mptcp_subflow_rsk(req)->mp_join) + foc->len = -1; + /* clear tstamp_ok, as needed depending on cookie */ if (foc && foc->len > -1) ireq->tstamp_ok = 0;
@@ -887,6 +891,13 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, fallback = true; } else if (subflow_req->mp_join) { + /* a SYN skb here comes from TFO, which MP_JOIN cannot use: just + * fall back to the regular path. + */ + if ((TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_ACK)) == + TCPHDR_SYN) + return NULL; + mptcp_get_options(skb, &mp_opt); if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK)) fallback = true;
--- base-commit: d8a4f4c59da52b7c31ae337243b8473a19a3f819 change-id: 20261030-mptcp-tfo-mpj-55fedc3189fc Best regards, -- Matthieu Baerts (NGI0) [off-list ref]