]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mptcp: pm: fix data race in add_addr timer callback
authorQing Luo <luoqing@kylinos.cn>
Mon, 3 Aug 2026 16:16:36 +0000 (18:16 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 6 Aug 2026 15:46:23 +0000 (08:46 -0700)
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 when the lock is taken. This allows to
call mptcp_pm_subflow_established() accordingly, and not depending on
the situation that can be different when checked outside the pm.lock.

Fixes: 348d5c1dec60 ("mptcp: move to next addr when timeout")
Cc: stable@vger.kernel.org
Signed-off-by: Qing Luo <luoqing@kylinos.cn>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20260803-net-mptcp-misc-fixes-7-2-rc6-v2-4-b8f496d71664@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/mptcp/pm.c

index 6afd39aea110a26678bc8f01d15423bf20303c76..c71dcf887683c9068e60d23b128f209177a5a79d 100644 (file)
@@ -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: