Skip to contentSkip to conversation

FAILED: patch "[PATCH] mptcp: pm: userspace: fix address ID overflow" failed to apply to 6.1-stable tree

PATCH New [email protected] 2 participants 6 messages Sep 16 – Sep 17

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.1-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-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x f9f0068e8813d8c10d016b030fc3a320d0b6767c
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091628-sevenfold-cursive-c662@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From f9f0068e8813d8c10d016b030fc3a320d0b6767c Mon Sep 17 00:00:00 2001
From: Qing Luo <[email protected]>
Date: Tue, 8 Sep 2026 16:07:13 +0200
Subject: [PATCH] mptcp: pm: userspace: fix address ID overflow

When all MPTCP address IDs (1-255) are exhausted in the userspace PM, find_next_zero_bit() returns MPTCP_PM_MAX_ADDR_ID + 1 (256). This value overflows when stored in the u8 field e->addr.id, resulting in ID 0 being stored and the entry being incorrectly added to the list.

ID 0 is reserved for the initial connection in MPTCP, so this overflow can cause address conflicts.

Note: the in-kernel PM already has an 'endpoints == MPTCP_PM_MAX_ADDR_ID' check in mptcp_pm_nl_append_new_local_addr() that returns -ERANGE before reaching find_next_zero_bit(), preventing this overflow. So this fix only addresses the userspace PM path.

Check the find_next_zero_bit() result against MPTCP_PM_MAX_ADDR_ID and return -ENOSPC if all IDs are truly exhausted. Move the ID allocation check before the memory allocation so that the error path does not need to free the allocated entry.

net/mptcp/pm_userspace.c +14 -4
index b94fbb483bf9..fab16d953dbf 100644
@@ -69,6 +69,19 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 	}
 
 	if (!addr_match && !id_match) {
+		unsigned int id;
+
+		if (!entry->addr.id && needs_id) {
+			id = find_next_zero_bit(id_bitmap,
+						MPTCP_PM_MAX_ADDR_ID + 1, 1);
+			if (id > MPTCP_PM_MAX_ADDR_ID) {
+				ret = -ENOSPC;
+				goto append_err;
+			}
+		} else {
+			id = entry->addr.id;
+		}
+
 		/* Memory for the entry is allocated from the
 		 * sock option buffer.
 		 */
@@ -78,10 +91,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 			goto append_err;
 		}
 
-		if (!e->addr.id && needs_id)
-			e->addr.id = find_next_zero_bit(id_bitmap,
-							MPTCP_PM_MAX_ADDR_ID + 1,
-							1);
+		e->addr.id = id;
 		list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
 		msk->pm.local_addr_used++;
 		ret = e->addr.id;
maintainer
#1 lore raw

PATCH 1/5 mptcp: userspace pm: use a single point of exit

From: Matthieu Baerts <[email protected]>

[ Upstream commit 40c71f763f87b68fe43199c1702220c91afed288 ]

Like in all other functions in this file, a single point of exit is used when extra operations are needed: unlock, decrement refcount, etc.

There is no functional change for the moment but it is better to do the same here to make sure all cleanups are done in case of intermediate errors.

Stable-dep-of: f9f0068e8813 ("mptcp: pm: userspace: fix address ID overflow")

---
 net/mptcp/pm_userspace.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
net/mptcp/pm_userspace.c +3 -2
index 52ab9a3f070a8..129ae1fef054e 100644
@@ -77,8 +77,8 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 		 */
 		e = sock_kmalloc(sk, sizeof(*e), GFP_ATOMIC);
 		if (!e) {
-			spin_unlock_bh(&msk->pm.lock);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto append_err;
 		}
 
 		*e = *entry;
@@ -93,6 +93,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 		ret = entry->addr.id;
 	}
 
+append_err:
 	spin_unlock_bh(&msk->pm.lock);
 	return ret;
 }
Signature · 1 line
2.53.0
maintainer
#2 lore raw

PATCH 2/5 mptcp: pm: drop match in userspace_pm_append_new_local_addr

From: Geliang Tang <[email protected]>

[ Upstream commit 640e3d69d0bc70d7d3de34800a1640793262bd08 ]

The variable 'match' in mptcp_userspace_pm_append_new_local_addr() is a redundant one, and this patch drops it.

No need to define 'match' as 'struct mptcp_pm_addr_entry *' type. In this function, it's only used to check whether it's NULL. It can be defined as a Boolean one.

Also other variables 'addr_match' and 'id_match' make 'match' a redundant one, which can be replaced by directly checking 'addr_match && id_match'.

Stable-dep-of: f9f0068e8813 ("mptcp: pm: userspace: fix address ID overflow")

---
 net/mptcp/pm_userspace.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)
net/mptcp/pm_userspace.c +3 -8
index 129ae1fef054e..e203b7f878a90 100644
@@ -43,7 +43,6 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 						    bool needs_id)
 {
 	DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
-	struct mptcp_pm_addr_entry *match = NULL;
 	struct sock *sk = (struct sock *)msk;
 	struct mptcp_pm_addr_entry *e;
 	bool addr_match = false;
@@ -62,16 +61,12 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 		if (addr_match && entry->addr.id == 0 && needs_id)
 			entry->addr.id = e->addr.id;
 		id_match = (e->addr.id == entry->addr.id);
-		if (addr_match && id_match) {
-			match = e;
+		if (addr_match || id_match)
 			break;
-		} else if (addr_match || id_match) {
-			break;
-		}
 		__set_bit(e->addr.id, id_bitmap);
 	}
 
-	if (!match && !addr_match && !id_match) {
+	if (!addr_match && !id_match) {
 		/* Memory for the entry is allocated from the
 		 * sock option buffer.
 		 */
@@ -89,7 +84,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 		list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
 		msk->pm.local_addr_used++;
 		ret = e->addr.id;
-	} else if (match) {
+	} else if (addr_match && id_match) {
 		ret = entry->addr.id;
 	}
 
Signature · 1 line
2.53.0
maintainer
#3 lore raw

PATCH 3/5 sock: add sock_kmemdup helper

In reply to Sasha Levin

From: Geliang Tang <[email protected]>

[ Upstream commit 456cc675b6d4cadd4872a477d8976ff56eef4b6f ]

This patch adds the sock version of kmemdup() helper, named sock_kmemdup(), to duplicate the input "src" memory block using the socket's option memory buffer.

Stable-dep-of: f9f0068e8813 ("mptcp: pm: userspace: fix address ID overflow")

---
 include/net/sock.h |  2 ++
 net/core/sock.c    | 16 ++++++++++++++++
 2 files changed, 18 insertions(+)
include/net/sock.h +2 -0
index 9fe621f985740..d195cddb8559b 100644
@@ -1977,6 +1977,8 @@ static inline struct sk_buff *sock_alloc_send_skb(struct sock *sk,
 }
 
 void *sock_kmalloc(struct sock *sk, int size, gfp_t priority);
+void *sock_kmemdup(struct sock *sk, const void *src,
+		   int size, gfp_t priority);
 void sock_kfree_s(struct sock *sk, void *mem, int size);
 void sock_kzfree_s(struct sock *sk, void *mem, int size);
 void sk_send_sigurg(struct sock *sk);
net/core/sock.c +16 -0
index 2a701e0b052b7..7ad32254506ec 100644
@@ -2670,6 +2670,22 @@ void *sock_kmalloc(struct sock *sk, int size, gfp_t priority)
 }
 EXPORT_SYMBOL(sock_kmalloc);
 
+/*
+ * Duplicate the input "src" memory block using the socket's
+ * option memory buffer.
+ */
+void *sock_kmemdup(struct sock *sk, const void *src,
+		   int size, gfp_t priority)
+{
+	void *mem;
+
+	mem = sock_kmalloc(sk, size, priority);
+	if (mem)
+		memcpy(mem, src, size);
+	return mem;
+}
+EXPORT_SYMBOL(sock_kmemdup);
+
 /* Free an option memory block. Note, we actually want the inline
  * here as this allows gcc to detect the nullify and fold away the
  * condition entirely.
Signature · 1 line
2.53.0
maintainer
#4 lore raw

PATCH 4/5 mptcp: use sock_kmemdup for address entry

In reply to Sasha Levin

From: Geliang Tang <[email protected]>

[ Upstream commit 52f83c0b5f857dbe24f66fc9a7f035523e9ffbc9 ]

Instead of using sock_kmalloc() to allocate an address entry "e" and then immediately duplicate the input "entry" to it, the newly added sock_kmemdup() helper can be used in mptcp_userspace_pm_append_new_local_addr() to simplify the code.

More importantly, the code "*e = *entry;" that assigns "entry" to "e" is not easy to implemented in BPF if we use the same code to implement an append_new_local_addr() helper of a BFP path manager. This patch avoids this type of memory assignment operation.

Stable-dep-of: f9f0068e8813 ("mptcp: pm: userspace: fix address ID overflow")

---
 net/mptcp/pm_userspace.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
net/mptcp/pm_userspace.c +1 -2
index e203b7f878a90..1bc270276db46 100644
@@ -70,13 +70,12 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 		/* Memory for the entry is allocated from the
 		 * sock option buffer.
 		 */
-		e = sock_kmalloc(sk, sizeof(*e), GFP_ATOMIC);
+		e = sock_kmemdup(sk, entry, sizeof(*entry), GFP_ATOMIC);
 		if (!e) {
 			ret = -ENOMEM;
 			goto append_err;
 		}
 
-		*e = *entry;
 		if (!e->addr.id && needs_id)
 			e->addr.id = find_next_zero_bit(id_bitmap,
 							MPTCP_PM_MAX_ADDR_ID + 1,
Signature · 1 line
2.53.0
maintainer
#5 lore raw

PATCH 5/5 mptcp: pm: userspace: fix address ID overflow

In reply to Sasha Levin

From: Qing Luo <[email protected]>

[ Upstream commit f9f0068e8813d8c10d016b030fc3a320d0b6767c ]

When all MPTCP address IDs (1-255) are exhausted in the userspace PM, find_next_zero_bit() returns MPTCP_PM_MAX_ADDR_ID + 1 (256). This value overflows when stored in the u8 field e->addr.id, resulting in ID 0 being stored and the entry being incorrectly added to the list.

ID 0 is reserved for the initial connection in MPTCP, so this overflow can cause address conflicts.

Note: the in-kernel PM already has an 'endpoints == MPTCP_PM_MAX_ADDR_ID' check in mptcp_pm_nl_append_new_local_addr() that returns -ERANGE before reaching find_next_zero_bit(), preventing this overflow. So this fix only addresses the userspace PM path.

Check the find_next_zero_bit() result against MPTCP_PM_MAX_ADDR_ID and return -ENOSPC if all IDs are truly exhausted. Move the ID allocation check before the memory allocation so that the error path does not need to free the allocated entry.

---
 net/mptcp/pm_userspace.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)
net/mptcp/pm_userspace.c +14 -4
index 1bc270276db46..a455303d2ed64 100644
@@ -67,6 +67,19 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 	}
 
 	if (!addr_match && !id_match) {
+		unsigned int id;
+
+		if (!entry->addr.id && needs_id) {
+			id = find_next_zero_bit(id_bitmap,
+						MPTCP_PM_MAX_ADDR_ID + 1, 1);
+			if (id > MPTCP_PM_MAX_ADDR_ID) {
+				ret = -ENOSPC;
+				goto append_err;
+			}
+		} else {
+			id = entry->addr.id;
+		}
+
 		/* Memory for the entry is allocated from the
 		 * sock option buffer.
 		 */
@@ -76,10 +89,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
 			goto append_err;
 		}
 
-		if (!e->addr.id && needs_id)
-			e->addr.id = find_next_zero_bit(id_bitmap,
-							MPTCP_PM_MAX_ADDR_ID + 1,
-							1);
+		e->addr.id = id;
 		list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
 		msk->pm.local_addr_used++;
 		ret = e->addr.id;
Signature · 1 line
2.53.0