Re: [PATCH mptcp-net v3] mptcp: pm: fix userspace PM address ID overflow when all IDs are exhausted

"Matthieu Baerts (NGI0)" <[email protected]>
Newsgroups dev.linux.lists.mptcp
Message-ID <178592755221.893374.4684461763598171085.b4-review@b4>
Hi luoqing,

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

Thank you for the new version.

> Fixes: 4638de5aefe5 ("mptcp: handle local addrs announced by userspace PMs")
> Assisted-by: LLM
> Signed-off-by: Qing Luo <[email protected]>

(...)

> Based on your feedback, I will withdraw this patch submission. The core fix
> for the ID overflow is valid, but my patch became muddled with an unnecessary
> and potentially harmful behavioral change.
>
> If you believe the core fix (checking find_next_zero_bit's return value
> against MPTCP_PM_MAX_ADDR_ID) is still worth submitting on its own, I can
> prepare a clean v3 that only contains that fix and removes the needs_id logic
> change. Otherwise, I am happy to let this go.

I'm sorry, this is confusing: this is the v3 with only the (valid) fix,
no?

Do you have issues to send replies to my previous emails? Because
sending your replies here at the end of a patch is unusual, and these
comments are stripped when replying to an existing email.

>
> diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
> index 945aa5afc2dd..7d0e343c35ed 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;
> +		}

The fix looks good to me, but I wonder if it wouldn't make more sense to
check this before allocating 'e', no?

e.g.

	if (!addr_match && !id_match) {
		struct mptcp_pm_addr_entry *e;
		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;
		}

		e = sock_kmemdup(sk, entry, sizeof(*entry), GFP_ATOMIC);
		if (!e) {
			ret = -ENOMEM;
			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;

WDYT?

A bit more code, but we avoid having to handle the free.

-- 
Matthieu Baerts (NGI0) <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.