mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net v3 1/4] net: mptcp: take token lookup references with acquire ordering
       [not found] <20261114130927.91839-1-2122295973@qq.com>
@ 2026-11-14 13:09 ` Hang Nan
  2026-11-14 13:09 ` [PATCH net v3 2/4] net: core: take the reuseport migration reference " Hang Nan
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 4+ messages in thread
From: Hang Nan @ 2026-11-14 13:09 UTC (permalink / raw)
  To: netdev
  Cc: mptcp, matttbe, martineau, geliang, davem, edumazet, kuba,
	pabeni, horms, kuniyu, willemb, linux-kernel, stable, 2122295973

mptcp_token_get_sock() and mptcp_token_iter_next() take a reference on a
socket found on an RCU-protected hash chain and then re-read state to
decide whether that socket is the one they were looking for.  The
re-validation is only meaningful if it is ordered after the reference
acquisition.

The sockets come from mptcp_prot.slab, which is SLAB_TYPESAFE_BY_RCU, so
the memory a reader still points at can be freed and reallocated as a new
mptcp socket while the reader is between the chain walk and the
increment.  The new owner publishes itself in sock_init_data_uid() with

	smp_wmb();
	refcount_set(&sk->sk_refcnt, 1);

and initialises the rest of the socket only afterwards.  A reader whose
increment does not carry acquire ordering can have the re-read of
msk->token and sock_net(sk) satisfied before the increment, that is
against the old object's contents, while the increment itself succeeds on
the new one.  The lookup would then hand back a socket that belongs to a
different connection, or one that is not initialised yet.

refcount_inc_not_zero() has not provided that ordering since
commit fb041bb7c0a9 ("locking/refcount: Consolidate implementations of refcount_t"),
which removed the ordering the previous atomic_add_unless() based
implementation gave; refcount.h names this exact case as the reason the
acquire variants exist.

commit 5b5d8f351dd9 ("net: restore refcount ordering for lockless socket access")
restored the ordering for the IPv4/IPv6 established lookups,
inet_twsk_purge() and bpf_sk_assign().  These two mptcp sites have the
same shape and are converted as well.  There is no behaviour change on
strongly ordered CPUs.

Fixes: 2c5ebd001d4f ("mptcp: refactor token container")
Fixes: 96d890daad05 ("mptcp: add msk interations helper")
Cc: stable@vger.kernel.org
Signed-off-by: Hang Nan <2122295973@qq.com>
---
 net/mptcp/token.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/mptcp/token.c b/net/mptcp/token.c
index e0f2823f92ef..3429b43a9f7c 100644
--- a/net/mptcp/token.c
+++ b/net/mptcp/token.c
@@ -309,7 +309,7 @@ struct mptcp_sock *mptcp_token_get_sock(struct net *net, u32 token)
 		    !net_eq(sock_net(sk), net))
 			continue;
 
-		if (!refcount_inc_not_zero(&sk->sk_refcnt))
+		if (!refcount_inc_not_zero_acquire(&sk->sk_refcnt))
 			goto not_found;
 
 		if (READ_ONCE(msk->token) != token ||
@@ -370,7 +370,7 @@ struct mptcp_sock *mptcp_token_iter_next(const struct net *net, long *s_slot,
 			if (num <= *s_num)
 				continue;
 
-			if (!refcount_inc_not_zero(&sk->sk_refcnt))
+			if (!refcount_inc_not_zero_acquire(&sk->sk_refcnt))
 				continue;
 
 			if (!net_eq(sock_net(sk), net)) {
-- 
2.47.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH net v3 2/4] net: core: take the reuseport migration reference with acquire ordering
       [not found] <20261114130927.91839-1-2122295973@qq.com>
  2026-11-14 13:09 ` [PATCH net v3 1/4] net: mptcp: take token lookup references with acquire ordering Hang Nan
@ 2026-11-14 13:09 ` Hang Nan
  2026-11-14 13:09 ` [PATCH net v3 3/4] net: mptcp: reject token 0 in mptcp_token_get_sock() Hang Nan
  2026-11-14 13:09 ` [PATCH net v3 4/4] net: mptcp: verify the token slot in mptcp_token_iter_next() Hang Nan
  3 siblings, 0 replies; 4+ messages in thread
From: Hang Nan @ 2026-11-14 13:09 UTC (permalink / raw)
  To: netdev
  Cc: mptcp, matttbe, martineau, geliang, davem, edumazet, kuba,
	pabeni, horms, kuniyu, willemb, linux-kernel, stable, 2122295973

reuseport_migrate_sock() returns a listener with a reference held, and
every caller immediately reads that listener: tcp_v4_rcv() and
tcp_v6_rcv() pass it to tcp_filter() and tcp_check_req(), and the
request-socket paths clone its state.  A listener removed from the
reuseport group concurrently with that lookup must not be observed in a
half-torn-down state after the reference was successfully taken.

refcount_inc_not_zero() lost its acquire ordering in commit fb041bb7c0a9
("locking/refcount: Consolidate implementations of refcount_t"), so these
subsequent reads are not ordered against the reference acquisition.  Use
refcount_inc_not_zero_acquire(), as was done for the established-socket
lookups, inet_twsk_purge() and bpf_sk_assign() in commit 5b5d8f351dd9
("net: restore refcount ordering for lockless socket access").

No behaviour change on strongly ordered architectures.

Fixes: 1cd62c21572c ("tcp: Add reuseport_migrate_sock() to select a new listener.")
Cc: stable@vger.kernel.org
Signed-off-by: Hang Nan <2122295973@qq.com>
---
 net/core/sock_reuseport.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
index b9e5648fa4c5..56230aa55a3e 100644
--- a/net/core/sock_reuseport.c
+++ b/net/core/sock_reuseport.c
@@ -667,7 +667,8 @@ struct sock *reuseport_migrate_sock(struct sock *sk,
 	if (!nsk)
 		nsk = reuseport_select_sock_by_hash(reuse, hash, socks);
 
-	if (IS_ERR_OR_NULL(nsk) || unlikely(!refcount_inc_not_zero(&nsk->sk_refcnt))) {
+	if (IS_ERR_OR_NULL(nsk) ||
+	    unlikely(!refcount_inc_not_zero_acquire(&nsk->sk_refcnt))) {
 		nsk = NULL;
 		goto failure;
 	}
-- 
2.47.3



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH net v3 3/4] net: mptcp: reject token 0 in mptcp_token_get_sock()
       [not found] <20261114130927.91839-1-2122295973@qq.com>
  2026-11-14 13:09 ` [PATCH net v3 1/4] net: mptcp: take token lookup references with acquire ordering Hang Nan
  2026-11-14 13:09 ` [PATCH net v3 2/4] net: core: take the reuseport migration reference " Hang Nan
@ 2026-11-14 13:09 ` Hang Nan
  2026-11-14 13:09 ` [PATCH net v3 4/4] net: mptcp: verify the token slot in mptcp_token_iter_next() Hang Nan
  3 siblings, 0 replies; 4+ messages in thread
From: Hang Nan @ 2026-11-14 13:09 UTC (permalink / raw)
  To: netdev
  Cc: mptcp, matttbe, martineau, geliang, davem, edumazet, kuba,
	pabeni, horms, kuniyu, willemb, linux-kernel, stable, 2122295973

Token 0 is never assigned to a connection: __token_bucket_busy() treats
it as busy.  It is, however, the value mptcp_token_destroy() stores into a
socket that is being torn down, and the value a freshly allocated msk
holds until it is hashed.

Both validations in mptcp_token_get_sock() compare the socket's token
with the requested one, so for a request for token 0 they cannot tell a
match apart from a socket whose token has just been cleared.  With
SLAB_TYPESAFE_BY_RCU the same is true for a socket whose memory has
already been reused by a new msk that has not been hashed yet.

The token comes from the wire: mptcp_parse_option() copies the MP_JOIN
SYN token without validating it.  A lookup for token 0 can therefore
return a dying or half-initialised msk, which subflow_token_join_request()
then hands to mptcp_pm_get_local_id() and, when the subflow uses a
different source port, to mptcp_pm_announced_has_ssk(), which walks
msk->pm.anno_list.  That list is only initialised later, from
mptcp_pm_data_init().

Reject token 0 before walking the chain.

Fixes: 2c5ebd001d4f ("mptcp: refactor token container")
Cc: stable@vger.kernel.org
Signed-off-by: Hang Nan <2122295973@qq.com>
---
 net/mptcp/token.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/mptcp/token.c b/net/mptcp/token.c
index 3429b43a9f7c..8a603fc8dc05 100644
--- a/net/mptcp/token.c
+++ b/net/mptcp/token.c
@@ -299,6 +299,10 @@ struct mptcp_sock *mptcp_token_get_sock(struct net *net, u32 token)
 	struct mptcp_sock *msk;
 	struct sock *sk;
 
+	/* Token 0 is never assigned, but is what a torn down socket holds. */
+	if (!token)
+		return NULL;
+
 	rcu_read_lock();
 	bucket = token_bucket(token);
 
-- 
2.47.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH net v3 4/4] net: mptcp: verify the token slot in mptcp_token_iter_next()
       [not found] <20261114130927.91839-1-2122295973@qq.com>
                   ` (2 preceding siblings ...)
  2026-11-14 13:09 ` [PATCH net v3 3/4] net: mptcp: reject token 0 in mptcp_token_get_sock() Hang Nan
@ 2026-11-14 13:09 ` Hang Nan
  3 siblings, 0 replies; 4+ messages in thread
From: Hang Nan @ 2026-11-14 13:09 UTC (permalink / raw)
  To: netdev
  Cc: mptcp, matttbe, martineau, geliang, davem, edumazet, kuba,
	pabeni, horms, kuniyu, willemb, linux-kernel, stable, 2122295973

mptcp_token_iter_next() takes a reference on a socket found on the chain
of the slot it is walking and then re-checks only net_eq().  A socket
that was freed and whose memory has been reused by a new msk in the same
network namespace passes that check while it is still zeroed, and the
callers - mptcp_diag and the userspace path manager - then use mptcp_pm
state that has not been initialised yet.

The token of a socket on a chain always hashes to the slot being walked,
and token 0 is never assigned, so re-read the token after the acquisition
and drop the socket unless it is non-zero and still maps to this slot.

Fixes: 96d890daad05 ("mptcp: add msk interations helper")
Cc: stable@vger.kernel.org
Signed-off-by: Hang Nan <2122295973@qq.com>
---
 net/mptcp/token.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/mptcp/token.c b/net/mptcp/token.c
index 8a603fc8dc05..48470d6e751d 100644
--- a/net/mptcp/token.c
+++ b/net/mptcp/token.c
@@ -355,6 +355,7 @@ struct mptcp_sock *mptcp_token_iter_next(const struct net *net, long *s_slot,
 	struct mptcp_sock *ret = NULL;
 	struct hlist_nulls_node *pos;
 	int slot, num = 0;
+	u32 token;
 
 	for (slot = *s_slot; slot <= token_mask; *s_num = 0, slot++) {
 		struct token_bucket *bucket = &token_hash[slot];
@@ -377,7 +378,9 @@ struct mptcp_sock *mptcp_token_iter_next(const struct net *net, long *s_slot,
 			if (!refcount_inc_not_zero_acquire(&sk->sk_refcnt))
 				continue;
 
-			if (!net_eq(sock_net(sk), net)) {
+			token = READ_ONCE(mptcp_sk(sk)->token);
+			if (!token || (token & token_mask) != slot ||
+			    !net_eq(sock_net(sk), net)) {
 				sock_put(sk);
 				continue;
 			}
-- 
2.47.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-11-14 13:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20261114130927.91839-1-2122295973@qq.com>
2026-11-14 13:09 ` [PATCH net v3 1/4] net: mptcp: take token lookup references with acquire ordering Hang Nan
2026-11-14 13:09 ` [PATCH net v3 2/4] net: core: take the reuseport migration reference " Hang Nan
2026-11-14 13:09 ` [PATCH net v3 3/4] net: mptcp: reject token 0 in mptcp_token_get_sock() Hang Nan
2026-11-14 13:09 ` [PATCH net v3 4/4] net: mptcp: verify the token slot in mptcp_token_iter_next() Hang Nan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®