FAILED: patch "[PATCH] mptcp: pm: kernel: drop pending ADD_ADDR when removing ID0" failed to apply to 5.15-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 2ac7d6e620764f1fc79eb4edd3610a7a661981ca
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091604-bogus-decent-1706@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2ac7d6e620764f1fc79eb4edd3610a7a661981ca Mon Sep 17 00:00:00 2001
From: Kalpan Jani <[email protected]>
Date: Tue, 8 Sep 2026 16:07:09 +0200
Subject: [PATCH] mptcp: pm: kernel: drop pending ADD_ADDR when removing ID0
The in-kernel MPTCP path manager can leave a stale ADD_ADDR announcement entry alive when removing the id 0 endpoint. This happens because the id 0 removal path does not tear down pending announcements, unlike the non-zero id path.
When the PM later reselects id 0 after adding another signal endpoint, it finds the stale anno_list entry and hits WARN_ON_ONCE(mptcp_pm_is_kernel()) in mptcp_pm_announced_alloc().
Root cause: asymmetry between removal paths.
- Non-zero id path: mptcp_nl_remove_subflow_and_signal_addr() calls mptcp_pm_remove_announced() to clean up.
- Id 0 path: mptcp_nl_remove_id_zero_address() skips cleanup entirely.
Fix by making the id 0 path symmetric: call mptcp_pm_announced_remove() and decrement add_addr_signaled before queuing the RM_ADDR.
Subtle detail: signal endpoints are stored in anno_list with port 0, but msk_local carries the connection's local port. In other words, entries linked to ID0 paths should have port == 0. A follow-up patch will ensure that. mptcp_pm_announced_remove() uses use_port=true for comparison. So clear the port before the lookup.
net/mptcp/pm_kernel.c +8 -0
@@ -1137,6 +1137,8 @@ static int mptcp_nl_remove_id_zero_address(struct net *net,while ((msk =mptcp_token_iter_next (net, &s_slot, &s_num)) !=NULL ) {struct sock *sk = (struct sock *)msk;struct mptcp_addr_info msk_local; +struct mptcp_addr_info anno_addr; +bool announced;if (list_empty (&msk->conn_list) ||mptcp_pm_is_userspace (msk)) goto next;
@@ -1146,7 +1148,13 @@ static int mptcp_nl_remove_id_zero_address(struct net *net, goto next;lock_sock (sk); +/* Drop a possibly pending ADD_ADDR for this address. */ + anno_addr = msk_local; + anno_addr.port =0 ; + announced =mptcp_pm_announced_remove (msk, &anno_addr);spin_lock_bh (&msk->pm.lock); +if (announced) + msk->pm.add_addr_signaled--;mptcp_pm_remove_addr (msk, &list);mptcp_pm_rm_subflow (msk, &list);__mark_subflow_endp_available (msk,0 );
Sasha Levin
maintainerPATCH 1/2 mptcp: pm: uniform announced addresses helpers
From: "Matthieu Baerts (NGI0)" <[email protected]>
[ Upstream commit 7d4dacc8ccca8e40fcb5f2ece9ea3e502da1bd3f ]
Similar to the previous commit, only using the 'add' or 'anno' prefixes is confusing -- generally associated to the action of adding something, or the Latin name for "year" -- and lack of uniformity.
This has been causing issues in the past, e.g. del_add_timer seemed to suggest the goal is to delete a previously added timer.
Instead, use the mptcp_pm_announced_ prefix.
While at it, slightly improves some helpers:
- mptcp_lookup_anno_list_by_saddr: no need to specify what is used to do the lookup: mptcp_pm_announced_lookup.
- mptcp_pm_sport_in_anno_list: it doesn't just compare the port, but the whole address linked to the sublow: mptcp_pm_announced_has_ssk.
- mptcp_pm_alloc_anno_list: it allocates one item of the list, not a whole list: mptcp_pm_announced_alloc.
Backport to 5.15: apply the helper renames to the existing path manager implementations, retaining their types, visibility, locking and behaviour. In particular, rename the existing remove_anno_list_by_saddr() helper to mptcp_pm_announced_remove(); no new functions are introduced. Update the 5.15 destructor in protocol.c as well as all declarations and callers. Drop the userspace path-manager hunks because that implementation is absent.
Move the existing pm_netlink.c to pm_kernel.c and update the MPTCP Makefile so target 2ac7d6e620764f1fc79eb4edd3610a7a661981ca can be cherry-picked without a missing-file conflict. This is only a source-file rename; keep the 5.15 netlink implementation instead of importing the upstream split.
[ sashal: Reduced backport -- upstream 7d4dacc8ccca8 touches 6 file(s), this
backport carries 7. Not backported here:
net/mptcp/pm_userspace.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: 2ac7d6e62076 ("mptcp: pm: kernel: drop pending ADD_ADDR when removing ID0")
---
net/mptcp/Makefile | 2 +-
net/mptcp/options.c | 2 +-
net/mptcp/pm.c | 4 +--
net/mptcp/{pm_netlink.c => pm_kernel.c} | 34 ++++++++++++-------------
net/mptcp/protocol.c | 2 +-
net/mptcp/protocol.h | 12 ++++-----
net/mptcp/subflow.c | 4 +--
7 files changed, 30 insertions(+), 30 deletions(-)
rename net/mptcp/{pm_netlink.c => pm_kernel.c} (98%)net/mptcp/Makefile +1 -1
@@ -2,7 +2,7 @@ obj-$(CONFIG_MPTCP) += mptcp.o mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o pm.o diag.o \ - mib.o pm_netlink.o sockopt.o + mib.o pm_kernel.o sockopt.o obj-$(CONFIG_SYN_COOKIES) += syncookies.o obj-$(CONFIG_INET_MPTCP_DIAG) += mptcp_diag.o
net/mptcp/options.c +1 -1
@@ -1208,7 +1208,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)MPTCP_INC_STATS (sock_net (sk),MPTCP_MIB_ADDADDR ); }else {mptcp_pm_add_addr_echoed (msk, &mp_opt.addr); -mptcp_pm_del_add_timer (msk, &mp_opt.addr, true); +mptcp_pm_announced_del_timer (msk, &mp_opt.addr, true);MPTCP_INC_STATS (sock_net (sk),MPTCP_MIB_ECHOADD ); }
net/mptcp/pm.c +2 -2
@@ -215,7 +215,7 @@ void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,spin_lock_bh (&pm->lock); -if (mptcp_lookup_anno_list_by_saddr (msk, addr) &&READ_ONCE (pm->work_pending)) +if (mptcp_pm_announced_lookup (msk, addr) &&READ_ONCE (pm->work_pending))mptcp_pm_schedule_work (msk,MPTCP_PM_SUBFLOW_ESTABLISHED );spin_unlock_bh (&pm->lock);
@@ -326,7 +326,7 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, const struct sk_buff *skb,* let the PM state machine progress. */ if (skip_add_addr) { -mptcp_pm_del_add_timer (msk, addr, true); +mptcp_pm_announced_del_timer (msk, addr, true);mptcp_pm_subflow_established (msk); }return ret;
net/mptcp/pm_kernel.c renamed from net/mptcp/pm_netlink.c +17 -17
@@ -276,8 +276,8 @@ static void check_work_pending(struct mptcp_sock *msk) }struct mptcp_pm_add_entry * -mptcp_lookup_anno_list_by_saddr (const struct mptcp_sock *msk, -const struct mptcp_addr_info *addr) +mptcp_pm_announced_lookup (const struct mptcp_sock *msk, +const struct mptcp_addr_info *addr) {struct mptcp_pm_add_entry *entry;
@@ -291,7 +291,7 @@ mptcp_lookup_anno_list_by_saddr(const struct mptcp_sock *msk,return NULL ; } -bool mptcp_pm_sport_in_anno_list (struct mptcp_sock *msk,const struct sock *sk) +bool mptcp_pm_announced_has_ssk (struct mptcp_sock *msk,const struct sock *sk) {struct mptcp_pm_add_entry *entry;struct mptcp_addr_info saddr;
@@ -343,7 +343,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)spin_lock_bh (&msk->pm.lock); -/* The cancel path (mptcp_pm_del_add_timer()) can race with this +/* The cancel path (mptcp_pm_announced_del_timer()) can race with this * callback. Once cancel updates retrans_times to MAX, suppress further * retransmissions here. If this callback acquires pm.lock first, one * final transmit attempt is still possible.
@@ -376,8 +376,8 @@ static void mptcp_pm_add_timer(struct timer_list *timer) }struct mptcp_pm_add_entry * -mptcp_pm_del_add_timer (struct mptcp_sock *msk, -const struct mptcp_addr_info *addr,bool check_id) +mptcp_pm_announced_del_timer (struct mptcp_sock *msk, +const struct mptcp_addr_info *addr,bool check_id) {struct mptcp_pm_add_entry *entry;struct sock *sk = (struct sock *)msk;
@@ -386,7 +386,7 @@ mptcp_pm_del_add_timer(struct mptcp_sock *msk,rcu_read_lock ();spin_lock_bh (&msk->pm.lock); - entry =mptcp_lookup_anno_list_by_saddr (msk, addr); + entry =mptcp_pm_announced_lookup (msk, addr);if (entry && (!check_id || entry->addr.id == addr->id)) { entry->retrans_times =ADD_ADDR_RETRANS_MAX ; stop_timer = true;
@@ -409,7 +409,7 @@ mptcp_pm_del_add_timer(struct mptcp_sock *msk,return entry; } -static bool mptcp_pm_alloc_anno_list (struct mptcp_sock *msk, +static bool mptcp_pm_announced_alloc (struct mptcp_sock *msk,const struct mptcp_pm_addr_entry *entry) {struct mptcp_pm_add_entry *add_entry =NULL ;
@@ -419,7 +419,7 @@ static bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,lockdep_assert_held (&msk->pm.lock); -if (mptcp_lookup_anno_list_by_saddr (msk, &entry->addr)) +if (mptcp_pm_announced_lookup (msk, &entry->addr))return false; add_entry =kmalloc (sizeof (*add_entry),GFP_ATOMIC );
@@ -441,7 +441,7 @@ static bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,return true; } -void mptcp_pm_free_anno_list (struct mptcp_sock *msk) +void mptcp_pm_free_announced_list (struct mptcp_sock *msk) {struct mptcp_pm_add_entry *entry, *tmp;struct sock *sk = (struct sock *)msk;
@@ -545,7 +545,7 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)if (msk->pm.add_addr_signaled < add_addr_signal_max) {if (select_signal_address (pernet, msk->pm.add_addr_signaled, &local)) { -if (mptcp_pm_alloc_anno_list (msk, &local)) { +if (mptcp_pm_announced_alloc (msk, &local)) { msk->pm.add_addr_signaled++;mptcp_pm_announce_addr (msk, &local.addr, false);mptcp_pm_nl_addr_send_ack (msk);
@@ -1466,12 +1466,12 @@ int mptcp_pm_get_flags_and_ifindex_by_id(struct net *net, unsigned int id,return 0 ; } -static bool remove_anno_list_by_saddr (struct mptcp_sock *msk, +static bool mptcp_pm_announced_remove (struct mptcp_sock *msk,const struct mptcp_addr_info *addr) {struct mptcp_pm_add_entry *entry; - entry =mptcp_pm_del_add_timer (msk, addr, false); + entry =mptcp_pm_announced_del_timer (msk, addr, false);if (entry) {kfree_rcu (entry, rcu);return true;
@@ -1480,7 +1480,7 @@ static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,return false; } -static bool mptcp_pm_remove_anno_addr (struct mptcp_sock *msk, +static bool mptcp_pm_remove_announced (struct mptcp_sock *msk,const struct mptcp_addr_info *addr,bool force) {
@@ -1489,7 +1489,7 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk, list.ids[list.nr++] = addr->id; - ret =remove_anno_list_by_saddr (msk, addr); + ret =mptcp_pm_announced_remove (msk, addr);if (ret || force) {spin_lock_bh (&msk->pm.lock); msk->pm.add_addr_signaled -= ret;
@@ -1516,7 +1516,7 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,lock_sock (sk); remove_subflow =lookup_subflow_by_saddr (&msk->conn_list, addr); -mptcp_pm_remove_anno_addr (msk, addr, remove_subflow); +mptcp_pm_remove_announced (msk, addr, remove_subflow);if (remove_subflow)mptcp_pm_remove_subflow (msk, &list);release_sock (sk);
@@ -1632,7 +1632,7 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, alist.ids[alist.nr++] = entry->addr.id; slist.ids[slist.nr++] = entry->addr.id; }else if (alist.nr <MPTCP_RM_IDS_MAX && -remove_anno_list_by_saddr (msk, &entry->addr)) { +mptcp_pm_announced_remove (msk, &entry->addr)) { alist.ids[alist.nr++] = entry->addr.id; } }
net/mptcp/protocol.c +1 -1
@@ -3110,7 +3110,7 @@ void mptcp_destroy_common(struct mptcp_sock *msk)skb_rbtree_purge (&msk->out_of_order_queue);mptcp_token_destroy (msk); -mptcp_pm_free_anno_list (msk); +mptcp_pm_free_announced_list (msk); }static void mptcp_destroy (struct sock *sk)
net/mptcp/protocol.h +6 -6
@@ -753,14 +753,14 @@ int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,struct mptcp_addr_info *addr, u8 bkup);void mptcp_pm_mp_fail_received (struct sock *sk,u64 fail_seq); -void mptcp_pm_free_anno_list (struct mptcp_sock *msk); -bool mptcp_pm_sport_in_anno_list (struct mptcp_sock *msk,const struct sock *sk); +void mptcp_pm_free_announced_list (struct mptcp_sock *msk); +bool mptcp_pm_announced_has_ssk (struct mptcp_sock *msk,const struct sock *sk);struct mptcp_pm_add_entry * -mptcp_pm_del_add_timer (struct mptcp_sock *msk, -const struct mptcp_addr_info *addr,bool check_id); +mptcp_pm_announced_del_timer (struct mptcp_sock *msk, +const struct mptcp_addr_info *addr,bool check_id);struct mptcp_pm_add_entry * -mptcp_lookup_anno_list_by_saddr (const struct mptcp_sock *msk, -const struct mptcp_addr_info *addr); +mptcp_pm_announced_lookup (const struct mptcp_sock *msk, +const struct mptcp_addr_info *addr);int mptcp_pm_get_flags_and_ifindex_by_id (struct net *net,unsigned int id,u8 *flags,int *ifindex);
net/mptcp/subflow.c +2 -2
@@ -230,7 +230,7 @@ static int subflow_check_req(struct request_sock *req,pr_debug ("syn inet_sport=%d %d\n" ,ntohs (inet_sk (sk_listener)->inet_sport),ntohs (inet_sk ((struct sock *)subflow_req->msk)->inet_sport)); -if (!mptcp_pm_sport_in_anno_list (subflow_req->msk, sk_listener)) { +if (!mptcp_pm_announced_has_ssk (subflow_req->msk, sk_listener)) {SUBFLOW_REQ_INC_STATS (req,MPTCP_MIB_MISMATCHPORTSYNRX );return -EPERM ; }
@@ -806,7 +806,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,pr_debug ("ack inet_sport=%d %d\n" ,ntohs (inet_sk (sk)->inet_sport),ntohs (inet_sk ((struct sock *)owner)->inet_sport)); -if (!mptcp_pm_sport_in_anno_list (owner, sk)) { +if (!mptcp_pm_announced_has_ssk (owner, sk)) {SUBFLOW_REQ_INC_STATS (req,MPTCP_MIB_MISMATCHPORTACKRX ); goto dispose_child; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 mptcp: pm: kernel: drop pending ADD_ADDR when removing ID0
From: Kalpan Jani <[email protected]>
[ Upstream commit 2ac7d6e620764f1fc79eb4edd3610a7a661981ca ]
The in-kernel MPTCP path manager can leave a stale ADD_ADDR announcement entry alive when removing the id 0 endpoint. This happens because the id 0 removal path does not tear down pending announcements, unlike the non-zero id path.
When the PM later reselects id 0 after adding another signal endpoint, it finds the stale anno_list entry and hits WARN_ON_ONCE(mptcp_pm_is_kernel()) in mptcp_pm_announced_alloc().
Root cause: asymmetry between removal paths.
- Non-zero id path: mptcp_nl_remove_subflow_and_signal_addr() calls mptcp_pm_remove_announced() to clean up.
- Id 0 path: mptcp_nl_remove_id_zero_address() skips cleanup entirely.
Fix by making the id 0 path symmetric: call mptcp_pm_announced_remove() and decrement add_addr_signaled before queuing the RM_ADDR.
Subtle detail: signal endpoints are stored in anno_list with port 0, but msk_local carries the connection's local port. In other words, entries linked to ID0 paths should have port == 0. A follow-up patch will ensure that. mptcp_pm_announced_remove() uses use_port=true for comparison. So clear the port before the lookup.
--- net/mptcp/pm_kernel.c | 8 ++++++++ 1 file changed, 8 insertions(+)
net/mptcp/pm_kernel.c +8 -0
@@ -1548,6 +1548,8 @@ static int mptcp_nl_remove_id_zero_address(struct net *net,while ((msk =mptcp_token_iter_next (net, &s_slot, &s_num)) !=NULL ) {struct sock *sk = (struct sock *)msk;struct mptcp_addr_info msk_local; +struct mptcp_addr_info anno_addr; +bool announced;if (list_empty (&msk->conn_list)) goto next;
@@ -1557,7 +1559,13 @@ static int mptcp_nl_remove_id_zero_address(struct net *net, goto next;lock_sock (sk); +/* Drop a possibly pending ADD_ADDR for this address. */ + anno_addr = msk_local; + anno_addr.port =0 ; + announced =mptcp_pm_announced_remove (msk, &anno_addr);spin_lock_bh (&msk->pm.lock); +if (announced) + msk->pm.add_addr_signaled--;mptcp_pm_remove_addr (msk, &list);mptcp_pm_nl_rm_subflow_received (msk, &list);spin_unlock_bh (&msk->pm.lock);
Signature · 1 line
2.53.0