[PATCH v2 MPTCP-net] pm: userspace: fix address ID overflow when all IDs exhausted
luoqing <[email protected]> Tue, 4 Aug 2026 10:23:49 +0800
| Newsgroups | dev.linux.lists.mptcp |
|---|---|
| Message-ID | <[email protected]> |
From: Qing Luo <[email protected]> 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. Store the find_next_zero_bit() result in a temporary unsigned int, check against MPTCP_PM_MAX_ADDR_ID, and return -ENOSPC if all IDs are truly exhausted. Properly free the allocated entry with sock_kfree_s() on error. Also modify the CSF (subflow create) handler to pass !entry.addr.id as the needs_id parameter. When no local ID is provided by user-space (entry.addr.id == 0), this triggers auto-allocation instead of silently using the reserved ID 0. Fixes: 4638de5aefe5 ("mptcp: handle local addrs announced by userspace PMs") Assisted-by: LLM # review Signed-off-by: Qing Luo <[email protected]> --- net/mptcp/pm_userspace.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c index 945aa5afc2dd..ada7d6cef625 100644 --- a/net/mptcp/pm_userspace.c +++ b/net/mptcp/pm_userspace.c @@ -74,10 +74,17 @@ 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); + if (!e->addr.id && needs_id) { + unsigned int id = find_next_zero_bit(id_bitmap, + MPTCP_PM_MAX_ADDR_ID + 1, + 1); + if (id > MPTCP_PM_MAX_ADDR_ID) { + sock_kfree_s(sk, e, sizeof(*e)); + ret = -ENOSPC; + goto append_err; + } + 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; @@ -400,7 +407,8 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info) goto create_err; } - err = mptcp_userspace_pm_append_new_local_addr(msk, &entry, false); + err = mptcp_userspace_pm_append_new_local_addr(msk, &entry, + !entry.addr.id); if (err < 0) { NL_SET_ERR_MSG_ATTR(info->extack, laddr, "did not match address and id"); -- 2.25.1