All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Geliang Tang" <geliang@kernel.org>, mptcp@lists.linux.dev
Subject: Re: [PATCH mptcp-next v2 1/4] mptcp: give MPTCP sockets a distinct lockdep class
Date: Mon, 26 Oct 2026 11:27:02 +0000	[thread overview]
Message-ID: <sashiko-outbox-185097@kernel.org> (raw)
In-Reply-To: <a17b9360df88d22c8ed579f532c41456fc46006e.1793010744.git.tanggeliang@kylinos.cn>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] mptcp: race on sk_lock reinit and unlocked clone with SLAB_TYPESAFE_BY_RCU
--

commit 1535a4c9bef6857111a0222f084ae0666d8e7461
Author: Geliang Tang <geliang@kernel.org>

mptcp: give MPTCP sockets a distinct lockdep class

This commit introduces mptcp_reclassify_socket() to assign distinct lockdep
classes to MPTCP sockets based on address family and kernel vs user socket
type. It calls this helper from mptcp_init_sock() and from
mptcp_sk_clone_init() after switching from sk_clone_lock() to unlocked
sk_clone().

> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index 02a4f479d9d8c..d4f42dfc227e2 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -3267,11 +3267,43 @@ static void mptcp_ca_reset(struct sock *sk)
>  	icsk->icsk_ca_ops = NULL;
>  }
>  
> +/* The subflow socket lock is acquired in a nested to the msk one
> + * in several places, even by the TCP stack: lockdep complains when
> + * both are kernel sockets. Instead of propagating the _nested modifiers
> + * in several places, re-init the lock class for the msk socket to an
> + * mptcp specific one. Separate lock classes are used for kernel and
> + * user sockets to prevent lockdep from conflating their usage patterns.
> + */
> +static struct lock_class_key mptcp_slock_keys[2][2];
> +static struct lock_class_key mptcp_keys[2][2];
> +
> +static void mptcp_reclassify_socket(struct sock *sk)
> +{
> +	bool is_ipv6 = sk->sk_family == AF_INET6;
> +	const char *slock_name, *lock_name;
> +	bool is_kern = !!sk->sk_kern_sock;
> +
> +	if (is_kern) {
> +		slock_name = is_ipv6 ? "kmlock-AF_INET6" : "kmlock-AF_INET";
> +		lock_name = is_ipv6 ? "kmsk_lock-AF_INET6" :
> +				      "kmsk_lock-AF_INET";
> +	} else {
> +		slock_name = is_ipv6 ? "mlock-AF_INET6" : "mlock-AF_INET";
> +		lock_name = is_ipv6 ? "msk_lock-AF_INET6" : "msk_lock-AF_INET";
> +	}
> +
> +	sock_lock_init_class_and_name(sk, slock_name,
> +				      &mptcp_slock_keys[is_kern][is_ipv6],
> +				      lock_name, &mptcp_keys[is_kern][is_ipv6]);
> +}
> +
>  static int mptcp_init_sock(struct sock *sk)
>  {
>  	struct net *net = sock_net(sk);
>  	int ret;
>  
> +	mptcp_reclassify_socket(sk);
> +
>  	__mptcp_init_sock(sk);
>  
>  	if (!mptcp_is_enabled(net))
> @@ -3772,13 +3804,16 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk,
>  				 struct request_sock *req)
>  {
>  	struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
> -	struct sock *nsk = sk_clone_lock(sk, GFP_ATOMIC);
> +	struct sock *nsk = sk_clone(sk, GFP_ATOMIC, false);
>  	struct mptcp_subflow_context *subflow;
>  	struct mptcp_sock *msk;
>  
>  	if (!nsk)
>  		return NULL;
>  
> +	mptcp_reclassify_socket(nsk);
> +
> +	bh_lock_sock(nsk);

[Severity: High]
Can calling mptcp_reclassify_socket() and unlocked sk_clone() race with
lockless RCU readers on SLAB_TYPESAFE_BY_RCU MPTCP sockets?

Both mptcp_prot and mptcp_v6_prot use SLAB_TYPESAFE_BY_RCU, and accepted
MPTCP sockets clear SOCK_RCU_FREE in mptcp_sk_clone_init(), so a closed
mptcp_sock can be immediately recycled from the slab cache while a
concurrent RCU reader in mptcp_token_iter_next() or mptcp_token_get_sock()
is walking bucket->msk_chain:

net/mptcp/token.c:mptcp_token_iter_next() {
	...
	rcu_read_lock();
	sk_nulls_for_each_rcu(sk, pos, &bucket->msk_chain) {
		++num;
		if (!net_eq(sock_net(sk), net))
			continue;

		if (num <= *s_num)
			continue;

		if (!refcount_inc_not_zero(&sk->sk_refcnt))
			continue;
	...
}

Once refcount_inc_not_zero(&sk->sk_refcnt) succeeds on the recycled socket,
callers of mptcp_token_iter_next() (such as mptcp_diag_dump(),
mptcp_nl_remove_subflow_and_signal_addr(), mptcp_nl_remove_id_zero_address(),
mptcp_nl_flush_addrs_list(), and mptcp_nl_set_flags()) immediately call
lock_sock(sk) or lock_sock_fast(sk).

In mptcp_sk_clone_init(), sk_clone_lock() previously initialized newsk's
lock and acquired bh_lock_sock(newsk) before setting newsk->sk_refcnt to 2:

net/core/sock.c:sk_clone() {
	...
	sock_lock_init(newsk);

	if (lock)
		bh_lock_sock(newsk);
	...
	smp_wmb();
	refcount_set(&newsk->sk_refcnt, 2);
}

Holding bh_lock_sock(newsk) before sk_refcnt became non-zero serialized any
concurrent lock_sock() or lock_sock_fast() reader until __mptcp_init_sock()
completed and bh_unlock_sock(nsk) was called.

With sk_clone(sk, GFP_ATOMIC, false), nsk->sk_refcnt becomes 2 while nsk is
unlocked. Can a concurrent RCU reader grab a reference on nsk and call
lock_sock(nsk) or lock_sock_fast(nsk):

1. Concurrently with mptcp_reclassify_socket(nsk) (and similarly in
   mptcp_init_sock() after sock_init_data() has set sk->sk_refcnt to 1),
   where sock_lock_init_class_and_name() zeroes sk_lock.owned and
   re-initializes sk_lock.wq, sk_lock.slock, and the lockdep maps while
   another CPU is acquiring or holding sk_lock?

2. In mptcp_sk_clone_init(), after mptcp_reclassify_socket(nsk) finishes
   and before bh_lock_sock(nsk) is called? If the reader acquires
   lock_sock(nsk) first, it sets nsk->sk_lock.owned = 1 and drops
   nsk->sk_lock.slock, which does not prevent bh_lock_sock(nsk) from
   proceeding into __mptcp_init_sock(nsk) concurrently, and the reader can
   iterate msk->conn_list while it still contains the raw copy of the
   listening socket's list head from sock_copy()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1793010744.git.tanggeliang@kylinos.cn?part=1

  reply	other threads:[~2026-10-26 11:27 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-26 10:35 [PATCH mptcp-next v2 0/4] Add MPTCP support for NBD Geliang Tang
2026-10-26 10:35 ` [PATCH mptcp-next v2 1/4] mptcp: give MPTCP sockets a distinct lockdep class Geliang Tang
2026-10-26 11:27   ` sashiko-bot [this message]
2026-10-26 10:35 ` [PATCH mptcp-next v2 2/4] sock: add set_memalloc protocol callback Geliang Tang
2026-10-26 11:46   ` sashiko-bot
2026-10-26 10:35 ` [PATCH mptcp-next v2 3/4] nbd: allow MPTCP sockets Geliang Tang
2026-10-26 12:14   ` sashiko-bot
2026-10-26 10:35 ` [PATCH mptcp-next v2 4/4] selftests: mptcp: add mptcp nbd tests Geliang Tang
2026-10-26 12:32   ` sashiko-bot
2026-10-26 12:04 ` [PATCH mptcp-next v2 0/4] Add MPTCP support for NBD MPTCP CI
  -- strict thread matches above, loose matches on Subject: below --
2026-10-27 23:46 [PATCH mptcp-next v2 1/4] mptcp: give MPTCP sockets a distinct lockdep class netdev-bot+sashiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-185097@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=geliang@kernel.org \
    --cc=mptcp@lists.linux.dev \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.