Re: [PATCH] mptcp: pm: Fix address ID overflow when all IDs are exhausted

Matthieu Baerts <[email protected]> Wed, 15 Jul 2026 11:10:43 +0200
Newsgroups dev.linux.lists.mptcp
Message-ID <178410664361.3802972.16804879942885801851.b4-review@b4>
Hi,

Thank you for this patch. Here is a very quick review done in between
tasks.

(-people who were in Cc: no need to add them when sending only to the
MPTCP ML.)

Also, please use a prefix: mptcp-net for fixes, mptcp-next for features.

The CI reported a few issues at build time, please check that.

> When all MPTCP address IDs (1-255) are exhausted, 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.

Are you sure? With the in-kernel PM? Do you have a reproducer?

> ID 0 has special meaning in MPTCP (it's reserved for the initial connection),
> so this overflow can cause confusion and incorrect behavior, including
> unintentional ID 0 reuse or address conflicts.

A fix should have a Fixes tag, please add one.

Also, if you were assisted by a tool, please add the Assisted-by tag.

> Signed-off-by: luoqing <[email protected]>

For "legal" reasons, you are supposed to put your full name. Having only
one "word" for your full name, without capital letters looks wrong, no?

>
> diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c
> index 331f6fa99014..1bd81c94b971 100644
> --- a/net/mptcp/pm_kernel.c
> +++ b/net/mptcp/pm_kernel.c
> @@ -795,9 +795,14 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
>
>  	if (!entry->addr.id) {
>  find_next:
> -		entry->addr.id = find_next_zero_bit(pernet->id_bitmap,
> -						    MPTCP_PM_MAX_ADDR_ID + 1,
> -						    pernet->next_id);
> +		unsigned int id = find_next_zero_bit(pernet->id_bitmap,
> +						     MPTCP_PM_MAX_ADDR_ID + 1,
> +						     pernet->next_id);
> +		if (id > MPTCP_PM_MAX_ADDR_ID) {
> +			ret = -ENOSPC;
> +			goto out;
> +		}
> +		entry->addr.id = id;
>  		if (!entry->addr.id && pernet->next_id != 1) {

The overflow is a normal case: find_next_zero_bit() will find the next
zero bit from next_id. If there it didn't find any, this block here
restart find_next_zero_bit() but from the beginning.

>  			pernet->next_id = 1;
>  			goto find_next;
> diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
> index ad6ba658e5a5..0a1e835ae049 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,

Do you need to change this line? In case of error, 'e' is dropped.

> -							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;

I didn't check the code, but here, it looks like such check is needed.
But please, provide a test reproducing the issue, e.g. by adding a test
in userspace_pm.sh. (Be careful that such test should also run on older
kernels where the limits are lower, see what is done in pm_netlink.sh)

-- 
Matthieu Baerts (NGI0) <[email protected]>