* [PATCH mptcp-next 0/2] mptcp: pm: fix reachable extra_subflows guards
@ 2026-08-31 9:32 Tao Cui
2026-08-31 9:32 ` [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM Tao Cui
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Tao Cui @ 2026-08-31 9:32 UTC (permalink / raw)
To: mptcp; +Cc: matttbe, geliang, cuitao, cui.tao
From: Tao Cui <cuitao@kylinos.cn>
Hi,
Following up on issue #629, here is a fix series for the two paths
reported against e99c1ca871 ("mptcp: pm: add WARN_ON_ONCE guards
on extra_subflows underflow").
Patch 1 bounds the userspace PM admission at U8_MAX, so the u8 can
no longer be wrapped by a peer establishing more than 255 subflows.
Patch 2 addresses the disconnect() vs MP_JOIN race: as discussed,
the decrement sites now check the msk state first and skip the
accounting when the msk is already in TCP_CLOSE, as the state is set
before mptcp_pm_data_reset() clears the counters, and once the msk
is closed the accounting is not relevant anymore. No new lock is
involved. The guards themselves are downgraded to a clamp with a
rate-limited pr_warn(), as the warn was reachable and turned into a
remotely triggerable panic on panic_on_warn kernels.
Both patches carry a Link: to the issue with the detailed analysis.
Validated with the virtme CI (mptcp selftests), and with a stress
repro comparing the base kernel and the patched one: on the base
kernel the server accepts 256 MP_JOINs and the counter wraps to 0,
with the patches admission stops at 255 and the leftover imbalance
only shows up as a rate-limited warning.
Tao Cui (2):
mptcp: pm: bound extra_subflows admission on userspace PM
mptcp: pm: skip extra_subflows accounting on disconnected msk
net/mptcp/pm.c | 22 +++++++++++++++++++---
net/mptcp/protocol.h | 14 ++++++++++++--
2 files changed, 31 insertions(+), 5 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM 2026-08-31 9:32 [PATCH mptcp-next 0/2] mptcp: pm: fix reachable extra_subflows guards Tao Cui @ 2026-08-31 9:32 ` Tao Cui 2026-09-02 16:39 ` Matthieu Baerts 2026-08-31 9:32 ` [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk Tao Cui 2026-08-31 10:25 ` [PATCH mptcp-next 0/2] mptcp: pm: fix reachable extra_subflows guards MPTCP CI 2 siblings, 1 reply; 13+ messages in thread From: Tao Cui @ 2026-08-31 9:32 UTC (permalink / raw) To: mptcp; +Cc: matttbe, geliang, cuitao, cui.tao From: Tao Cui <cuitao@kylinos.cn> mptcp_pm_allow_new_subflow() increments the u8 extra_subflows counter for every accepted MP_JOIN on sockets using the userspace PM, without any limit. A peer establishing more than 255 live subflows wraps the counter back to 0, which then makes the underflow guards warn on the next subflow close, and permanently corrupts mptcpi_subflows_total reported to userspace. Refuse new MP_JOINs once the counter has reached U8_MAX, so that it cannot wrap anymore. Fixes: e99c1ca89071 ("mptcp: pm: add WARN_ON_ONCE guards on extra_subflows underflow") Link: https://github.com/multipath-tcp/mptcp_net-next/issues/629 Signed-off-by: Tao Cui <cuitao@kylinos.cn> --- net/mptcp/pm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 8b68868255c5..3990f6775723 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -562,10 +562,17 @@ bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk) if (mptcp_pm_is_userspace(msk)) { if (mptcp_userspace_pm_active(msk)) { + bool allow; + + /* extra_subflows is a u8: don't let a peer wrap it + * with more than U8_MAX accepted MP_JOINs + */ spin_lock_bh(&pm->lock); - pm->extra_subflows++; + allow = pm->extra_subflows < U8_MAX; + if (allow) + pm->extra_subflows++; spin_unlock_bh(&pm->lock); - return true; + return allow; } return false; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM 2026-08-31 9:32 ` [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM Tao Cui @ 2026-09-02 16:39 ` Matthieu Baerts 2026-09-03 3:42 ` quanyeyang 2026-09-03 8:55 ` Tao Cui 0 siblings, 2 replies; 13+ messages in thread From: Matthieu Baerts @ 2026-09-02 16:39 UTC (permalink / raw) To: Tao Cui, mptcp; +Cc: geliang, cuitao, Quanye Yang Hi Tao, + cc Quanye On 31/08/2026 11:32, Tao Cui wrote: > From: Tao Cui <cuitao@kylinos.cn> > > mptcp_pm_allow_new_subflow() increments the u8 extra_subflows counter > for every accepted MP_JOIN on sockets using the userspace PM, without > any limit. A peer establishing more than 255 live subflows wraps the > counter back to 0, which then makes the underflow guards warn on the > next subflow close, and permanently corrupts mptcpi_subflows_total > reported to userspace. > > Refuse new MP_JOINs once the counter has reached U8_MAX, so that it > cannot wrap anymore. > > Fixes: e99c1ca89071 ("mptcp: pm: add WARN_ON_ONCE guards on extra_subflows underflow") > Link: https://github.com/multipath-tcp/mptcp_net-next/issues/629 Do you have a GitHub account? Just to know if we can assign this task to you (or just leave a message in the comment section). > Signed-off-by: Tao Cui <cuitao@kylinos.cn> > --- > net/mptcp/pm.c | 11 +++++++++-- > 1 file changed, 9 insertions(+), 2 deletions(-) > > diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c > index 8b68868255c5..3990f6775723 100644 > --- a/net/mptcp/pm.c > +++ b/net/mptcp/pm.c > @@ -562,10 +562,17 @@ bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk) > > if (mptcp_pm_is_userspace(msk)) { > if (mptcp_userspace_pm_active(msk)) { > + bool allow; "ret" could be re-used here. > + > + /* extra_subflows is a u8: don't let a peer wrap it > + * with more than U8_MAX accepted MP_JOINs > + */ I don't think this comment is needed, "< U8_MAX" is probably clear enough. > spin_lock_bh(&pm->lock); > - pm->extra_subflows++; > + allow = pm->extra_subflows < U8_MAX; > + if (allow) > + pm->extra_subflows++; > spin_unlock_bh(&pm->lock); > - return true; > + return allow; > } > return false; > } So, at the end, we can re-used the same version as Quanye. Would it be OK for both of you to have a Co-developed-by tag here? Cheers, Matt -- Sponsored by the NGI0 Core fund. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM 2026-09-02 16:39 ` Matthieu Baerts @ 2026-09-03 3:42 ` quanyeyang 2026-09-03 8:57 ` Tao Cui 2026-09-03 8:55 ` Tao Cui 1 sibling, 1 reply; 13+ messages in thread From: quanyeyang @ 2026-09-03 3:42 UTC (permalink / raw) To: Matthieu Baerts; +Cc: Tao Cui, mptcp, geliang, cuitao Hi Matt, Tao, On 02/09/2026 18:36, Matthieu Baerts wrote: > So, at the end, we can re-used the same version as Quanye. Would it be > OK for both of you to have a Co-developed-by tag here? Fine with me. Please reuse `ret` and drop the comment in v2, with Co-developed-by tags for both of us. On 02/09/2026 18:52, Matthieu Baerts wrote: > Maybe a goto could be used here ... to here, not to modify the rest > of the code? > > Would it be OK for both of you if this part of Quanye's patch is > added to Tao's v2 series with Quanye as author? Also fine. Please take the Netlink extra_subflows cap in v2 with me as author, using a goto to the existing error cleanup instead of the else-wrapping I sent. I will not send a competing series. Thanks, Quanye ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM 2026-09-03 3:42 ` quanyeyang @ 2026-09-03 8:57 ` Tao Cui 0 siblings, 0 replies; 13+ messages in thread From: Tao Cui @ 2026-09-03 8:57 UTC (permalink / raw) To: quanyeyang, Matthieu Baerts; +Cc: cui.tao, mptcp, geliang, cuitao Hi Quanye, 在 2026/9/3 11:42, quanyeyang 写道: > Hi Matt, Tao, > > On 02/09/2026 18:36, Matthieu Baerts wrote: >> So, at the end, we can re-used the same version as Quanye. Would it be >> OK for both of you to have a Co-developed-by tag here? > > Fine with me. Please reuse `ret` and drop the comment in v2, with > Co-developed-by tags for both of us. > > On 02/09/2026 18:52, Matthieu Baerts wrote: >> Maybe a goto could be used here ... to here, not to modify the rest >> of the code? >> >> Would it be OK for both of you if this part of Quanye's patch is >> added to Tao's v2 series with Quanye as author? > > Also fine. Please take the Netlink extra_subflows cap in v2 with me > as author, using a goto to the existing error cleanup instead of the > else-wrapping I sent. > > I will not send a competing series. > Thanks for having a look at this too, and for making the coordination easy. You're right that the Netlink path was still open in my series, good catch. I'll take your patch into the v2 series as we just agreed, with you as author of that part. Happy to share this one with you. Thanks, Tao > Thanks, > Quanye ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM 2026-09-02 16:39 ` Matthieu Baerts 2026-09-03 3:42 ` quanyeyang @ 2026-09-03 8:55 ` Tao Cui 2026-09-03 9:13 ` Matthieu Baerts 1 sibling, 1 reply; 13+ messages in thread From: Tao Cui @ 2026-09-03 8:55 UTC (permalink / raw) To: Matthieu Baerts, mptcp; +Cc: cui.tao, geliang, cuitao, Quanye Yang Hi Matt, 在 2026/9/3 00:39, Matthieu Baerts 写道: > Hi Tao, > > + cc Quanye > > On 31/08/2026 11:32, Tao Cui wrote: >> From: Tao Cui <cuitao@kylinos.cn> >> >> mptcp_pm_allow_new_subflow() increments the u8 extra_subflows counter >> for every accepted MP_JOIN on sockets using the userspace PM, without >> any limit. A peer establishing more than 255 live subflows wraps the >> counter back to 0, which then makes the underflow guards warn on the >> next subflow close, and permanently corrupts mptcpi_subflows_total >> reported to userspace. >> >> Refuse new MP_JOINs once the counter has reached U8_MAX, so that it >> cannot wrap anymore. >> >> Fixes: e99c1ca89071 ("mptcp: pm: add WARN_ON_ONCE guards on extra_subflows underflow") >> Link: https://github.com/multipath-tcp/mptcp_net-next/issues/629 > > Do you have a GitHub account? Just to know if we can assign this task to > you (or just leave a message in the comment section). > >> Signed-off-by: Tao Cui <cuitao@kylinos.cn> >> --- >> net/mptcp/pm.c | 11 +++++++++-- >> 1 file changed, 9 insertions(+), 2 deletions(-) >> >> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c >> index 8b68868255c5..3990f6775723 100644 >> --- a/net/mptcp/pm.c >> +++ b/net/mptcp/pm.c >> @@ -562,10 +562,17 @@ bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk) >> >> if (mptcp_pm_is_userspace(msk)) { >> if (mptcp_userspace_pm_active(msk)) { >> + bool allow; > > "ret" could be re-used here. > >> + >> + /* extra_subflows is a u8: don't let a peer wrap it >> + * with more than U8_MAX accepted MP_JOINs >> + */ > > I don't think this comment is needed, "< U8_MAX" is probably clear enough. > >> spin_lock_bh(&pm->lock); >> - pm->extra_subflows++; >> + allow = pm->extra_subflows < U8_MAX; >> + if (allow) >> + pm->extra_subflows++; >> spin_unlock_bh(&pm->lock); >> - return true; >> + return allow; >> } >> return false; >> } > > So, at the end, we can re-used the same version as Quanye. Would it be > OK for both of you to have a Co-developed-by tag here? > Thanks for sorting this out with Quanye. Sounds good to me. I'll send a v2 taking your two comments into account, reusing "ret" and dropping the comment, with Quanye's Netlink part as a separate patch with him as author, and Co-developed-by tags on the admission patch. I'll switch to "Closes:" for the issue as well. About the GitHub account: I have one (sharkct235@gmail.com) but honestly I don't use it much because of the captcha checks, so sorry in advance if I'm slow to react there. I've left a comment on the issue, and I'll try to be better at watching it for this kind of thing. Thanks, Tao > Cheers, > Matt ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM 2026-09-03 8:55 ` Tao Cui @ 2026-09-03 9:13 ` Matthieu Baerts 0 siblings, 0 replies; 13+ messages in thread From: Matthieu Baerts @ 2026-09-03 9:13 UTC (permalink / raw) To: Tao Cui, mptcp; +Cc: geliang, cuitao, Quanye Yang Hi Tao, Thank you for your reply! On 03/09/2026 10:55, Tao Cui wrote: > Hi Matt, > > 在 2026/9/3 00:39, Matthieu Baerts 写道: >> Hi Tao, >> >> + cc Quanye >> >> On 31/08/2026 11:32, Tao Cui wrote: >>> From: Tao Cui <cuitao@kylinos.cn> >>> >>> mptcp_pm_allow_new_subflow() increments the u8 extra_subflows counter >>> for every accepted MP_JOIN on sockets using the userspace PM, without >>> any limit. A peer establishing more than 255 live subflows wraps the >>> counter back to 0, which then makes the underflow guards warn on the >>> next subflow close, and permanently corrupts mptcpi_subflows_total >>> reported to userspace. >>> >>> Refuse new MP_JOINs once the counter has reached U8_MAX, so that it >>> cannot wrap anymore. >>> >>> Fixes: e99c1ca89071 ("mptcp: pm: add WARN_ON_ONCE guards on extra_subflows underflow") >>> Link: https://github.com/multipath-tcp/mptcp_net-next/issues/629 >> >> Do you have a GitHub account? Just to know if we can assign this task to >> you (or just leave a message in the comment section). >> >>> Signed-off-by: Tao Cui <cuitao@kylinos.cn> >>> --- >>> net/mptcp/pm.c | 11 +++++++++-- >>> 1 file changed, 9 insertions(+), 2 deletions(-) >>> >>> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c >>> index 8b68868255c5..3990f6775723 100644 >>> --- a/net/mptcp/pm.c >>> +++ b/net/mptcp/pm.c >>> @@ -562,10 +562,17 @@ bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk) >>> >>> if (mptcp_pm_is_userspace(msk)) { >>> if (mptcp_userspace_pm_active(msk)) { >>> + bool allow; >> >> "ret" could be re-used here. >> >>> + >>> + /* extra_subflows is a u8: don't let a peer wrap it >>> + * with more than U8_MAX accepted MP_JOINs >>> + */ >> >> I don't think this comment is needed, "< U8_MAX" is probably clear enough. >> >>> spin_lock_bh(&pm->lock); >>> - pm->extra_subflows++; >>> + allow = pm->extra_subflows < U8_MAX; >>> + if (allow) >>> + pm->extra_subflows++; >>> spin_unlock_bh(&pm->lock); >>> - return true; >>> + return allow; >>> } >>> return false; >>> } >> >> So, at the end, we can re-used the same version as Quanye. Would it be >> OK for both of you to have a Co-developed-by tag here? >> > > Thanks for sorting this out with Quanye. > > Sounds good to me. I'll send a v2 taking your two comments into > account, reusing "ret" and dropping the comment, with Quanye's > Netlink part as a separate patch with him as author, and > Co-developed-by tags on the admission patch. I'll switch to > "Closes:" for the issue as well. Thanks! Please use "Closes" only for the last patch of the series fixing the issue. You can use "Link" for the others. > About the GitHub account: I have one (sharkct235@gmail.com) but > honestly I don't use it much because of the captcha checks, so > sorry in advance if I'm slow to react there. I've left a comment on > the issue, and I'll try to be better at watching it for this kind > of thing. Thanks! I guess there shouldn't be new comments over there, but we appreciate comments simply saying "I'm going to look at it". Cheers, Matt -- Sponsored by the NGI0 Core fund. ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk 2026-08-31 9:32 [PATCH mptcp-next 0/2] mptcp: pm: fix reachable extra_subflows guards Tao Cui 2026-08-31 9:32 ` [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM Tao Cui @ 2026-08-31 9:32 ` Tao Cui 2026-08-31 10:11 ` sashiko-bot 2026-09-02 16:56 ` Matthieu Baerts 2026-08-31 10:25 ` [PATCH mptcp-next 0/2] mptcp: pm: fix reachable extra_subflows guards MPTCP CI 2 siblings, 2 replies; 13+ messages in thread From: Tao Cui @ 2026-08-31 9:32 UTC (permalink / raw) To: mptcp; +Cc: matttbe, geliang, cuitao, cui.tao From: Tao Cui <cuitao@kylinos.cn> The WARN_ON_ONCE() guards added to the extra_subflows decrement sites turn out to be reachable: mptcp_pm_data_reset() zeroes the counter with only the msk socket lock held, while an MP_JOIN subflow can still sit in msk->join_list, its reference already accounted by mptcp_pm_allow_new_subflow() under pm->lock. If the socket gets disconnected(AF_UNSPEC) in that window, mptcp_pm_data_reset() zeroes the counter, and the join list is flushed later at release_sock() time: the leftover subflow then reaches mptcp_pm_subflow_check_next() (or __mptcp_pm_close_subflow() for kernel PM sockets) with the counter already at 0, firing the warning. On panic_on_warn kernels this is a remotely triggerable panic, which is worse than the silent wrap the guards replaced. Skip the PM accounting when the msk is already in TCP_CLOSE: in the scenario above the state is set before the counters are cleared, and once the msk is closed the accounting is not relevant anymore. Keep a clamp and a rate-limited pr_warn() on the decrement sites instead, to leave a trace of any imbalance we would still not know about. Fixes: e99c1ca89071 ("mptcp: pm: add WARN_ON_ONCE guards on extra_subflows underflow") Link: https://github.com/multipath-tcp/mptcp_net-next/issues/629 Suggested-by: Matthieu Baerts <matttbe@kernel.org> Signed-off-by: Tao Cui <cuitao@kylinos.cn> --- net/mptcp/pm.c | 11 ++++++++++- net/mptcp/protocol.h | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 3990f6775723..1760f4c51b62 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -676,9 +676,18 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk, update_subflows = subflow->request_join || subflow->mp_join; if (mptcp_pm_is_userspace(msk)) { if (update_subflows) { + /* The PM counters have already been cleared if the + * msk got disconnected while this subflow was still + * queued in the join list + */ + if (inet_sk_state_load(sk) == TCP_CLOSE) + return; spin_lock_bh(&pm->lock); - if (!WARN_ON_ONCE(pm->extra_subflows == 0)) + if (likely(pm->extra_subflows)) pm->extra_subflows--; + else + pr_warn_ratelimited("extra_subflows underflow, msk=%p\n", + msk); spin_unlock_bh(&pm->lock); } return; diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 06a107d4e839..f5dbafaf4551 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -1252,8 +1252,18 @@ u8 mptcp_pm_get_limit_extra_subflows(const struct mptcp_sock *msk); /* called under PM lock */ static inline void __mptcp_pm_close_subflow(struct mptcp_sock *msk) { - if (!WARN_ON_ONCE(msk->pm.extra_subflows == 0) && - --msk->pm.extra_subflows < mptcp_pm_get_limit_extra_subflows(msk)) + /* The PM counters have already been cleared if the msk got + * disconnected while this subflow was still queued in the + * join list + */ + if (inet_sk_state_load((struct sock *)msk) == TCP_CLOSE) + return; + + if (unlikely(msk->pm.extra_subflows == 0)) { + pr_warn_ratelimited("extra_subflows underflow, msk=%p\n", msk); + return; + } + if (--msk->pm.extra_subflows < mptcp_pm_get_limit_extra_subflows(msk)) WRITE_ONCE(msk->pm.accept_subflow, true); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk 2026-08-31 9:32 ` [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk Tao Cui @ 2026-08-31 10:11 ` sashiko-bot 2026-08-31 13:00 ` Tao Cui 2026-09-02 16:56 ` Matthieu Baerts 1 sibling, 1 reply; 13+ messages in thread From: sashiko-bot @ 2026-08-31 10:11 UTC (permalink / raw) To: Tao Cui; +Cc: mptcp Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] Subflows in `join_list` can be leaked due to unsynchronized zeroing of `cb_flags` in `mptcp_disconnect`. - [High] Data race on `pm->reset` and `pm->rm_list_*` fields due to missing `pm->lock` in `mptcp_pm_data_reset()`. -- commit 179deded54d27540d6b26de1228c24065e1fa9d4 Author: Tao Cui <cuitao@kylinos.cn> mptcp: pm: skip extra_subflows accounting on disconnected msk This commit addresses a WARN_ON_ONCE crash related to extra_subflows underflow by skipping the PM accounting when the mptcp socket is in the TCP_CLOSE state. It replaces the warnings with rate-limited prints and avoids modifying the counters for disconnected sockets. Link: https://github.com/multipath-tcp/mptcp_net-next/issues/629 > diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c > index b10895606542a..60276eb1ef384 100644 > --- a/net/mptcp/pm.c > +++ b/net/mptcp/pm.c > @@ -676,9 +676,18 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk, > update_subflows = subflow->request_join || subflow->mp_join; > if (mptcp_pm_is_userspace(msk)) { > if (update_subflows) { > + /* The PM counters have already been cleared if the > + * msk got disconnected while this subflow was still > + * queued in the join list > + */ > + if (inet_sk_state_load(sk) == TCP_CLOSE) > + return; [Severity: High] This is a pre-existing issue, but does mptcp_disconnect() leak subflows when zeroing cb_flags non-atomically? If a concurrent mptcp_finish_join() receives an MP_JOIN ACK for a subflow while the parent socket is being disconnected, it can hit the sock_owned_by_user(parent) branch. The subflow is added to msk->join_list and MPTCP_FLUSH_JOIN_LIST is set in msk->cb_flags while holding the parent's data lock. Simultaneously, mptcp_disconnect() executes msk->cb_flags = 0 without holding the mptcp_data_lock, erasing the MPTCP_FLUSH_JOIN_LIST flag: net/mptcp/protocol.c:mptcp_disconnect() { ... msk->cb_flags = 0; ... } When the lock is released, release_sock() invokes mptcp_release_cb(), but since the flag was erased, it skips the flush: net/mptcp/protocol.c:mptcp_release_cb() { ... if (flags & BIT(MPTCP_FLUSH_JOIN_LIST)) __mptcp_flush_join_list(sk, &join_list); ... } Can this lead to the sockets in join_list being completely leaked when mptcp_destroy_common() later iterates only over conn_list? [Severity: High] This is a pre-existing issue, but is there a data race on pm->reset and pm->rm_list_* fields when mptcp_pm_data_reset() is called during disconnect? When mptcp_disconnect() sets sk->sk_state to TCP_CLOSE, it calls mptcp_pm_data_reset(msk), which modifies PM structures without acquiring pm->lock: net/mptcp/pm.c:mptcp_pm_data_reset() { ... memset(&pm->reset, 0, sizeof(pm->reset)); pm->rm_list_tx.nr = 0; pm->rm_list_rx.nr = 0; ... } At the same time, subflow receive paths can process incoming MP_JOIN or RM_ADDR packets in BH context, holding only pm->lock and lock_sock(ssk) rather than lock_sock(msk). For example: net/mptcp/pm.c:mptcp_pm_allow_new_subflow() { ... spin_lock_bh(&pm->lock); if (READ_ONCE(pm->accept_subflow)) { ret = pm->extra_subflows < limit_extra_subflows; ... } Could this unprotected memset in mptcp_pm_data_reset() cause torn writes and corrupted PM state when racing with readers and writers that only hold pm->lock? [ ... ] -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831093206.689827-1-cui.tao@linux.dev?part=2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk 2026-08-31 10:11 ` sashiko-bot @ 2026-08-31 13:00 ` Tao Cui 2026-09-02 16:32 ` Matthieu Baerts 0 siblings, 1 reply; 13+ messages in thread From: Tao Cui @ 2026-08-31 13:00 UTC (permalink / raw) To: sashiko-reviews; +Cc: cui.tao, mptcp Hi, Thanks for the review. 在 2026/8/31 18:11, sashiko-bot@kernel.org 写道: > Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: > > Pre-existing issues: > - [High] Subflows in `join_list` can be leaked due to unsynchronized zeroing of `cb_flags` in `mptcp_disconnect`. > - [High] Data race on `pm->reset` and `pm->rm_list_*` fields due to missing `pm->lock` in `mptcp_pm_data_reset()`. Both findings are pre-existing issues rather than regressions from this series, but I had a look at them: For the join_list leak, I agree it is real. When an MP_JOIN is processed while the parent socket is being disconnected, the subflow is queued in msk->join_list and MPTCP_FLUSH_JOIN_LIST is set under the data lock, but mptcp_disconnect() then clears msk->cb_flags with a plain write. The flag is lost, mptcp_release_cb() never flushes the list, and since mptcp_destroy_common() only iterates conn_list, those subflow sockets are leaked. The plain write also drops flags that were already pending before the disconnect, so taking the data lock around it is not enough. What I have in mind is to keep the flush-related bits across the disconnect and let release_sock() process the join list as originally intended, or to drain it explicitly in the disconnect path, checking the lock nesting commented in mptcp_destroy_common(). For the pm->reset data race, the lasting effect is the counter imbalance this series now clamps and traces, and the other fields are discarded on a closed socket anyway. The direct fix is to take pm->lock around the reset in mptcp_pm_data_reset(), after checking the lock ordering on all callers. These are two separate bugs with separate Fixes: targets, so I plan to submit them as their own series rather than folding them into this one. Tao > -- > > commit 179deded54d27540d6b26de1228c24065e1fa9d4 > Author: Tao Cui <cuitao@kylinos.cn> > > mptcp: pm: skip extra_subflows accounting on disconnected msk > > This commit addresses a WARN_ON_ONCE crash related to extra_subflows > underflow by skipping the PM accounting when the mptcp socket is in the > TCP_CLOSE state. It replaces the warnings with rate-limited prints and > avoids modifying the counters for disconnected sockets. > > Link: https://github.com/multipath-tcp/mptcp_net-next/issues/629 > >> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c >> index b10895606542a..60276eb1ef384 100644 >> --- a/net/mptcp/pm.c >> +++ b/net/mptcp/pm.c >> @@ -676,9 +676,18 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk, >> update_subflows = subflow->request_join || subflow->mp_join; >> if (mptcp_pm_is_userspace(msk)) { >> if (update_subflows) { >> + /* The PM counters have already been cleared if the >> + * msk got disconnected while this subflow was still >> + * queued in the join list >> + */ >> + if (inet_sk_state_load(sk) == TCP_CLOSE) >> + return; > > [Severity: High] > This is a pre-existing issue, but does mptcp_disconnect() leak subflows when > zeroing cb_flags non-atomically? > > If a concurrent mptcp_finish_join() receives an MP_JOIN ACK for a subflow > while the parent socket is being disconnected, it can hit the > sock_owned_by_user(parent) branch. The subflow is added to msk->join_list > and MPTCP_FLUSH_JOIN_LIST is set in msk->cb_flags while holding the parent's > data lock. > > Simultaneously, mptcp_disconnect() executes msk->cb_flags = 0 without holding > the mptcp_data_lock, erasing the MPTCP_FLUSH_JOIN_LIST flag: > > net/mptcp/protocol.c:mptcp_disconnect() { > ... > msk->cb_flags = 0; > ... > } > > When the lock is released, release_sock() invokes mptcp_release_cb(), but > since the flag was erased, it skips the flush: > > net/mptcp/protocol.c:mptcp_release_cb() { > ... > if (flags & BIT(MPTCP_FLUSH_JOIN_LIST)) > __mptcp_flush_join_list(sk, &join_list); > ... > } > > Can this lead to the sockets in join_list being completely leaked when > mptcp_destroy_common() later iterates only over conn_list? > > [Severity: High] > This is a pre-existing issue, but is there a data race on pm->reset and > pm->rm_list_* fields when mptcp_pm_data_reset() is called during disconnect? > > When mptcp_disconnect() sets sk->sk_state to TCP_CLOSE, it calls > mptcp_pm_data_reset(msk), which modifies PM structures without acquiring > pm->lock: > > net/mptcp/pm.c:mptcp_pm_data_reset() { > ... > memset(&pm->reset, 0, sizeof(pm->reset)); > pm->rm_list_tx.nr = 0; > pm->rm_list_rx.nr = 0; > ... > } > > At the same time, subflow receive paths can process incoming MP_JOIN or > RM_ADDR packets in BH context, holding only pm->lock and lock_sock(ssk) rather > than lock_sock(msk). For example: > > net/mptcp/pm.c:mptcp_pm_allow_new_subflow() { > ... > spin_lock_bh(&pm->lock); > if (READ_ONCE(pm->accept_subflow)) { > ret = pm->extra_subflows < limit_extra_subflows; > ... > } > > Could this unprotected memset in mptcp_pm_data_reset() cause torn writes and > corrupted PM state when racing with readers and writers that only hold > pm->lock? > > [ ... ] > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk 2026-08-31 13:00 ` Tao Cui @ 2026-09-02 16:32 ` Matthieu Baerts 0 siblings, 0 replies; 13+ messages in thread From: Matthieu Baerts @ 2026-09-02 16:32 UTC (permalink / raw) To: Tao Cui, sashiko-reviews; +Cc: mptcp Hi Tao, On 31/08/2026 15:00, Tao Cui wrote: > Hi, > > Thanks for the review. > > 在 2026/8/31 18:11, sashiko-bot@kernel.org 写道: >> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: >> >> Pre-existing issues: >> - [High] Subflows in `join_list` can be leaked due to unsynchronized zeroing of `cb_flags` in `mptcp_disconnect`. >> - [High] Data race on `pm->reset` and `pm->rm_list_*` fields due to missing `pm->lock` in `mptcp_pm_data_reset()`. > > Both findings are pre-existing issues rather > than regressions from this series, but I had a look at them: > > For the join_list leak, I agree it is real. When an MP_JOIN is > processed while the parent socket is being disconnected, the subflow > is queued in msk->join_list and MPTCP_FLUSH_JOIN_LIST is set under > the data lock, but mptcp_disconnect() then clears msk->cb_flags with > a plain write. The flag is lost, mptcp_release_cb() never flushes > the list, and since mptcp_destroy_common() only iterates conn_list, > those subflow sockets are leaked. The plain write also drops flags > that were already pending before the disconnect, so taking the data > lock around it is not enough. What I have in mind is to keep the > flush-related bits across the disconnect and let release_sock() > process the join list as originally intended, or to drain it > explicitly in the disconnect path, checking the lock nesting > commented in mptcp_destroy_common(). > > For the pm->reset data race, the lasting effect is the counter > imbalance this series now clamps and traces, and the other fields > are discarded on a closed socket anyway. The direct fix is to take > pm->lock around the reset in mptcp_pm_data_reset(), after checking > the lock ordering on all callers. > > These are two separate bugs with separate Fixes: targets, so I plan > to submit them as their own series rather than folding them into > this one. Thank you! Yes a different series is better. Cheers, Matt -- Sponsored by the NGI0 Core fund. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk 2026-08-31 9:32 ` [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk Tao Cui 2026-08-31 10:11 ` sashiko-bot @ 2026-09-02 16:56 ` Matthieu Baerts 1 sibling, 0 replies; 13+ messages in thread From: Matthieu Baerts @ 2026-09-02 16:56 UTC (permalink / raw) To: Tao Cui, mptcp; +Cc: geliang, cuitao Hi Tao Cui, On 31/08/2026 11:32, Tao Cui wrote: > From: Tao Cui <cuitao@kylinos.cn> > > The WARN_ON_ONCE() guards added to the extra_subflows decrement sites > turn out to be reachable: > > mptcp_pm_data_reset() zeroes the counter with only the msk socket lock > held, while an MP_JOIN subflow can still sit in msk->join_list, its > reference already accounted by mptcp_pm_allow_new_subflow() under > pm->lock. If the socket gets disconnected(AF_UNSPEC) in that window, > mptcp_pm_data_reset() zeroes the counter, and the join list is flushed > later at release_sock() time: the leftover subflow then reaches > mptcp_pm_subflow_check_next() (or __mptcp_pm_close_subflow() for > kernel PM sockets) with the counter already at 0, firing the warning. > On panic_on_warn kernels this is a remotely triggerable panic, which > is worse than the silent wrap the guards replaced. > > Skip the PM accounting when the msk is already in TCP_CLOSE: in the > scenario above the state is set before the counters are cleared, and > once the msk is closed the accounting is not relevant anymore. Keep a > clamp and a rate-limited pr_warn() on the decrement sites instead, > to leave a trace of any imbalance we would still not know about. > > Fixes: e99c1ca89071 ("mptcp: pm: add WARN_ON_ONCE guards on extra_subflows underflow") > Link: https://github.com/multipath-tcp/mptcp_net-next/issues/629 This patch looks good to me, but could you please use the "Closes" tag for the last patch of the series closing this ticket, please? Cheers, Matt -- Sponsored by the NGI0 Core fund. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH mptcp-next 0/2] mptcp: pm: fix reachable extra_subflows guards 2026-08-31 9:32 [PATCH mptcp-next 0/2] mptcp: pm: fix reachable extra_subflows guards Tao Cui 2026-08-31 9:32 ` [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM Tao Cui 2026-08-31 9:32 ` [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk Tao Cui @ 2026-08-31 10:25 ` MPTCP CI 2 siblings, 0 replies; 13+ messages in thread From: MPTCP CI @ 2026-08-31 10:25 UTC (permalink / raw) To: Tao Cui; +Cc: mptcp Hi Tao, 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): Notice: Call Traces at boot time, rebooted and continued ⚠️ - KVM Validation: debug (only selftest_mptcp_join): Notice: Call Traces at boot time, rebooted and continued ⚠️ - KVM Validation: btf-normal (only bpftest_all): Success! ✅ - KVM Validation: btf-debug (only bpftest_all): Notice: Call Traces at boot time, rebooted and continued - Notice: Call Traces at shutdown time, ignored and continued ⚠️ - Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/33379349810 Initiator: Patchew Applier Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/190a5d9ad47e Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1154350 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) ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-09-03 9:13 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-31 9:32 [PATCH mptcp-next 0/2] mptcp: pm: fix reachable extra_subflows guards Tao Cui 2026-08-31 9:32 ` [PATCH mptcp-next 1/2] mptcp: pm: bound extra_subflows admission on userspace PM Tao Cui 2026-09-02 16:39 ` Matthieu Baerts 2026-09-03 3:42 ` quanyeyang 2026-09-03 8:57 ` Tao Cui 2026-09-03 8:55 ` Tao Cui 2026-09-03 9:13 ` Matthieu Baerts 2026-08-31 9:32 ` [PATCH mptcp-next 2/2] mptcp: pm: skip extra_subflows accounting on disconnected msk Tao Cui 2026-08-31 10:11 ` sashiko-bot 2026-08-31 13:00 ` Tao Cui 2026-09-02 16:32 ` Matthieu Baerts 2026-09-02 16:56 ` Matthieu Baerts 2026-08-31 10:25 ` [PATCH mptcp-next 0/2] mptcp: pm: fix reachable extra_subflows guards MPTCP CI
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).