[PATCH net 2/5] mptcp: pm: fix data race in add_addr timer callback

From: Matthieu Baerts (NGI0)

Date: Tue Jul 28 2026 - 13:48:25 EST


From: Qing Luo <luoqing@xxxxxxxxxx>

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.

I discovered this issue while studying the code. AI tools helped me to
verify the issue can potentially happen under race conditions.

Use a local 'retransmit' flag set inside pm.lock to capture whether
retransmission is still possible. This ensures that
mptcp_pm_subflow_established() is only called when the retransmission
naturally exhausts.

Fixes: 348d5c1dec60 ("mptcp: move to next addr when timeout")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Qing Luo <luoqing@xxxxxxxxxx>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@xxxxxxxxxx>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@xxxxxxxxxx>
---
net/mptcp/pm.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 6afd39aea110..c71dcf887683 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 retransmit;

pr_debug("msk=%p\n", msk);

@@ -412,14 +413,15 @@ static void mptcp_pm_add_addr_timer(struct timer_list *timer)
entry->retrans_times++;
}

- if (entry->retrans_times < ADD_ADDR_RETRANS_MAX)
+ retransmit = entry->retrans_times < ADD_ADDR_RETRANS_MAX;
+ if (retransmit)
timeout <<= entry->retrans_times;
else
timeout = 0;

spin_unlock_bh(&msk->pm.lock);

- if (entry->retrans_times == ADD_ADDR_RETRANS_MAX)
+ if (!retransmit)
mptcp_pm_subflow_established(msk);

out:

--
2.53.0