From: Li Xiasong <lixiasong1@huawei.com>
This series fixes a potential use-after-free in MPTCP ADD_ADDR timer
teardown.
The ADD_ADDR retransmission timer callback may re-arm itself on the
sock_owned_by_user() path. During final teardown, this can race with
timer cancellation and leave a timer pending after the entry is removed
and freed.
Using sk_stop_timer_sync() is not sufficient for this case because it
waits for a running callback but does not permanently disable the timer.
This series does two things:
1. Add sk_shutdown_timer_sync() to socket timer helpers.
It wraps timer_shutdown_sync() and preserves sk reference accounting
semantics by dropping a socket reference when a pending timer is
removed.
2. Switch MPTCP ADD_ADDR final teardown paths to
sk_shutdown_timer_sync(), so the timer cannot be re-armed once
teardown starts.
Reported scenario:
Link: https://github.com/multipath-tcp/mptcp_net-next/issues/623
Li Xiasong (2):
net: add sk_shutdown_timer_sync() helper
mptcp: use sk_shutdown_timer_sync() for add_addr timer teardown
include/net/sock.h | 5 +++++
net/core/sock.c | 7 +++++++
net/mptcp/pm.c | 4 ++--
3 files changed, 14 insertions(+), 2 deletions(-)
--
2.43.0
Hi Li,
Thank you for your modifications, that's great!
Our CI did some validations and here is its report:
- KVM Validation: normal (except selftest_mptcp_join): Success! ✅
- KVM Validation: normal (only selftest_mptcp_join): Success! ✅
- KVM Validation: debug (except selftest_mptcp_join): Unstable: 1 failed test(s): selftest_diag ⚠️
- KVM Validation: debug (only selftest_mptcp_join): Success! ✅
- KVM Validation: btf-normal (only bpftest_all): Success! ✅
- KVM Validation: btf-debug (only bpftest_all): Success! ✅
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/26490120648
Initiator: Matthieu Baerts (NGI0)
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/f75fedf58a6b
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1100863
If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:
$ cd [kernel source code]
$ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
--pull always mptcp/mptcp-upstream-virtme-docker:latest \
auto-normal
For more details:
https://github.com/multipath-tcp/mptcp-upstream-virtme-docker
Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)
Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)
Hi Li,
Great work on this patch series! Your approach of creating sk_shutdown_timer_sync()
helper is the right pattern.
I noticed one additional issue: in mptcp_pm_free_anno_list(), the timer_done check
is unsynchronized:
if (!entry->timer_done) // Data race: no lock protecting this read
sk_stop_timer_sync(sk, &entry->add_timer);
This is a classic data race. Your patch keeps it as-is, but I think we should
also fix it by removing this check entirely and always calling timer_shutdown_sync().
Would you be open to adding this improvement to your patch? The benefit:
- Eliminates the data race
- Simplifies the code (unconditional shutdown)
- timer_shutdown_sync() is idempotent anyway
I'd be happy to:
1. Test the updated patch
2. Help refine the implementation
3. Co-author if you'd like
What do you think?
Cheers,
Kalpan Jani
kalpan.jani@mpiricsoftware.com
Hi Matt, Hi Kalpan, Thank you for your review and suggestion. The main reason I have been hesitating to send a v2 is that, after re-checking the code paths more carefully, I am no longer sure that the original issue reported by Sashiko can actually happen in this add_addr timer path. My current understanding is that both sk_stop_timer_sync() and sk_shutdown_timer_sync() synchronously stop the timer: if the callback is running, they wait for it to finish, and if the callback re-arms the timer before returning, the pending timer is then deleted before the helper returns. So for this specific add_addr timer, I do not currently see a path where teardown completes and a re-armed timer is still left behind afterward. That is why I have not sent a v2 based on sk_shutdown_timer_sync() so far. That said, I think tightening this teardown path could still be useful for robustness and could help avoid similar issues after future changes. On 6/4/2026 3:19 PM, Kalpan Jani wrote: > Hi Li, > > Great work on this patch series! Your approach of creating sk_shutdown_timer_sync() > helper is the right pattern. > > I noticed one additional issue: in mptcp_pm_free_anno_list(), the timer_done check > is unsynchronized: > > if (!entry->timer_done) // Data race: no lock protecting this read > sk_stop_timer_sync(sk, &entry->add_timer); > > This is a classic data race. Your patch keeps it as-is, but I think we should > also fix it by removing this check entirely and always calling timer_shutdown_sync(). > > Would you be open to adding this improvement to your patch? The benefit: > - Eliminates the data race > - Simplifies the code (unconditional shutdown) > - timer_shutdown_sync() is idempotent anyway > Yes, I think this would be a good direction if timer_done can be removed safely. I agree that it would avoid the unsynchronized timer_done check and simplify the teardown path. Before removing timer_done, I would like to better understand the original scenario for which it was introduced. Matt, if I am understanding it correctly, timer_done was added to avoid the case where the socket reference held by the timer becomes the last one, and then sock_put() from the timer callback triggers socket destruction, which in turn reaches sk_stop_timer_sync() for the same timer. If that understanding is correct, my concern is that removing timer_done without addressing that original case might re-introduce the self-wait issue during teardown from the timer callback path. So overall, I agree with Kalpan's suggestion if timer_done is indeed no longer needed for that last-reference case. I would just like to clarify that point first before sending a new version. > I'd be happy to: > 1. Test the updated patch > 2. Help refine the implementation > 3. Co-author if you'd like > > What do you think? > Thanks a lot for the offer, I really appreciate it. Thanks, Li Xiasong
© 2016 - 2026 Red Hat, Inc.