[PATCH mptcp-net v3] mptcp: pm: fix data race in add_addr timer callback

luoqing <[email protected]> Wed, 22 Jul 2026 17:13:11 +0800
Newsgroups dev.linux.lists.mptcp
Message-ID <[email protected]>
From: Qing Luo <[email protected]>

The timer callback reads entry->retrans_times outside pm.lock to decide
whether to call mptcp_pm_subflow_established(). Since
mptcp_pm_announced_del_timer() can concurrently set retrans_times =
ADD_ADDR_RETRANS_MAX under pm.lock, a race condition exists.

Use a local 'completed' flag set inside pm.lock when retrans_times
reaches ADD_ADDR_RETRANS_MAX. This ensures that
mptcp_pm_subflow_established() is only called when the retransmission
naturally exhausts.

Fixes: 348d5c1dec60 ("mptcp: move to next addr when timeout")
Signed-off-by: Qing Luo <[email protected]>
---
 net/mptcp/pm.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 6afd39aea110..f93fefbb727e 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -380,6 +380,7 @@ static void mptcp_pm_add_addr_timer(struct timer_list *timer)
 	struct mptcp_sock *msk = entry->sock;
 	struct sock *sk = (struct sock *)msk;
 	unsigned int timeout = 0;
+	bool completed = false;
 
 	pr_debug("msk=%p\n", msk);
 
@@ -414,12 +415,14 @@ static void mptcp_pm_add_addr_timer(struct timer_list *timer)
 
 	if (entry->retrans_times < ADD_ADDR_RETRANS_MAX)
 		timeout <<= entry->retrans_times;
-	else
+	else {
 		timeout = 0;
+		completed = true;
+	}
 
 	spin_unlock_bh(&msk->pm.lock);
 
-	if (entry->retrans_times == ADD_ADDR_RETRANS_MAX)
+	if (completed)
 		mptcp_pm_subflow_established(msk);
 
 out:
-- 
2.25.1