Re: [PATCH net v2 1/1] mptcp: fix request ownership when cloning reqsk

Matthieu Baerts <[email protected]> Thu, 30 Jul 2026 20:03:35 +0200
Newsgroups dev.linux.lists.mptcp,org.kernel.vger.netdev
Organization NGI0 Core
Message-ID <[email protected]>
Hi Ren, Ruide,

On 13/05/2026 11:37, Paolo Abeni wrote:
> On 5/10/26 4:14 PM, Ren Wei wrote:
>> From: Ruide Cao <[email protected]>
>>
>> TCP request migration clones pending request sockets with
>> inet_reqsk_clone(). For MPTCP MP_JOIN requests this raw-copies
>> subflow_req->msk, but the cloned request does not take a new reference.
>>
>> Both the original and the cloned request can later drop the same msk in
>> subflow_req_destructor(), and a migrated request may keep a dangling msk
>> pointer after the original owner has already been released.
>>
>> MP_CAPABLE requests have a similar ownership issue for token_node. The
>> original request is hashed in the token table, and inet_reqsk_clone()
>> raw-copies the hlist pointers into the clone. The clone must not inherit
>> that hashed state on migration failure, and the token ownership must move
>> only after the new req has actually replaced the old one in the ehash.
>>
>> Fix both cases while keeping the change local to MPTCP and the TCP
>> migration path: grab a reference for cloned subflow requests that carry an
>> msk, clear any raw-copied token hash state from the clone, and move the
>> hashed token request ownership only after migration succeeds.

(...)

>> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
>> index e961936b6be7..578471bb8a2b 100644
>> --- a/net/ipv4/inet_connection_sock.c
>> +++ b/net/ipv4/inet_connection_sock.c

(...)

>> @@ -1115,6 +1121,8 @@ static void reqsk_timer_handler(struct timer_list *t)
>>  			goto no_ownership;
>>  		}
>>  
>> +		if (rsk_is_mptcp(oreq))
>> +			mptcp_subflow_reqsk_migrated(oreq, nreq);
> 
> Sashiko says:
> 
> ---
> Can this sequence trigger a race condition with network RX processing?
> In reqsk_timer_handler(), nreq is inserted into the global ehash table
> via inet_ehash_insert() right before this block. The ehash lock is
> immediately dropped, making nreq globally visible to concurrent network
> RX softirq processing.
> However, the MPTCP token state is not migrated to nreq until the call to
> mptcp_subflow_reqsk_migrated(oreq, nreq).
> If a concurrent RX thread processes an incoming ACK for the connection
> in this narrow window, it could find nreq in the ehash table,
> successfully process it, and invoke mptcp_token_accept(nreq).
> Inside mptcp_token_accept(), __token_lookup_req() searches the token
> bucket and finds oreq, because the timer thread hasn't moved the token yet.
> The code then asserts ownership:
> mptcp_token_accept()
> 	pos = __token_lookup_req(bucket, req->token);
> 	if (!WARN_ON_ONCE(pos != req))
> 		hlist_nulls_del_init_rcu(&req->token_node);
> Since pos is oreq and req is nreq, would this fail the assertion and
> trigger a kernel warning?
> If the calls were reordered so that mptcp_subflow_reqsk_migrated()
> happens before inet_ehash_insert(), could that merely shift the race? If
> a concurrent ACK is already processing oreq, it might call
> mptcp_token_accept(oreq) after the token was moved to nreq, triggering
> the same warning, since the ehash table and the token bucket are
> protected by different locks and the updates are non-atomic.
> Could a remote attacker time ACKs to hit this window during a listener
> migration, potentially leading to a denial of service on systems
> configured to panic on warnings?
> ---
> 
> I _think_ the above race could/should be solved squashing
> mptcp_subflow_reqsk_migrated() into mptcp_subflow_reqsk_clone() and
> adjusting  mptcp_token_destroy_request() and mptcp_token_accept() to
> deal with already removed token, checking (again) for unhased token_node
> under the bucket lock.
> 
> The latter will require a little more work, returning a success status
> to the caller - mptcp_sk_clone_init() - and make the latter fail on
> mptcp_token_accept() failures.
> 
> The above would also make the fix more encapsulated into the mptcp code.

I was checking old patches tracked on our MPTCP Patchwork, and noticed
this one is marked as "Changes Requested". I don't think a v3 has been
posted: are you still working on a v3 addressing Paolo's comments? Or
did I miss the v3 because it had a different name?

Cheers,
Matt
-- 
Sponsored by the NGI0 Core fund.