From nobody Fri Oct 2 12:21:09 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE71C3CE0A7; Sat, 1 Aug 2026 10:13:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785579219; cv=none; b=LzXQSbKaxXkAZQa2vJdxQjeiJccgvotblE/JVu/bG7TkSMyYznZtOIhYlTn/i0R7jC5Af4jj8IcFeH4uXMwE2B3m3G1N6jv3M50tC46Mo/jERwtWbXz/+bMPbckbLSEfjXTYruwvGb7tADt4uKY7dva3Y7nMYt5PTkORpsRX+3Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785579219; c=relaxed/simple; bh=IqMXI8NhYburQh1nzeTmZB+ld7JGn3K9qjh3OyDNXoY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=A+be5FoTS8ZhGtwl2N7R00Gq6NMEe4pLp01SINm/3WxUYCxVmsrcoarLfIv3FtIjtiD7pF62AbGPMNOp6hCuhMfHufjaSPn9nayihJFWs1T9kEmdiijD4kDHd9KU8gvPufeFTyKteR4PENWZmUoofYSx73JZlQOYzfK89726Z7g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gtUHUqYP; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gtUHUqYP" Received: by smtp.kernel.org (Postfix) with ESMTPS id 48C6FC2BCB3; Sat, 1 Aug 2026 10:13:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1785579219; bh=IqMXI8NhYburQh1nzeTmZB+ld7JGn3K9qjh3OyDNXoY=; h=From:Date:Subject:To:Cc:Reply-To:From; b=gtUHUqYP0hJvLD5RNYxhfJAyW2ZW22DI62APpZUAItlNhI9j/p65Cm+QBK3JNT8GI 5EBmVKynOA4vPsrDGZFHUv9HLTzleWgdN9Px5uuM0neouMyobo+RXNC2Zjea899oB/ Q3fCYq0YjihZZxQ8S67d/ytaK07aVHvEPpvsEurQge9Lcxkb/CyMKvnMHlZYxe3MiT G8YlFM8/ZIplRvC3WncxJdj5BZ/xG5BdJejUS0oMjHEZSndDyX4vQajNv+sYFDml3i ZM3FN31VI+uHjHSGo7JwxCwV1sUrI3v3ugI1tqtNePKo7iV4EtVJkWGYw2vPLUFOIZ xbrraYdACFm+A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24D61C55175; Sat, 1 Aug 2026 10:13:39 +0000 (UTC) From: quanyeyang via B4 Relay Date: Sat, 01 Aug 2026 18:13:27 +0800 Subject: [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260801-fix-rhashtable-bucket-lockdep-v1-1-15a0f8ae094c@gmail.com> X-B4-Tracking: v=1; b=H4sIAAAAAAAC/yXMQQrCMBBG4auUWTuQBirqVcRFJv01Y0tbMqkIp Xc36vJbvLeRISuMLs1GGS81naeK9tBQTGF6gLWvJu/80Z1cy3d9c07BUgkygmWNAwqPcxx6LHz u4LsgECBQfSwZNfj9r7e/bZUnYvlOad8/HEMS6oEAAAA= X-Change-ID: 20260801-fix-rhashtable-bucket-lockdep-95e25abebeea To: Thomas Graf , Herbert Xu , Andrew Morton , NeilBrown , "David S. Miller" Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, syzbot+ef8d17bae14efb960935@syzkaller.appspotmail.com, quanyeyang X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1785579217; l=5881; i=quanyemostima@gmail.com; s=20260801; h=from:subject:message-id; bh=0N4OOkfbxgTWIlbrzMgCyEmTGY5MHduBeX6XyueQ9Ow=; b=5FW6wSL57G2tayTV0jw3QcforpkXT48l0JX2ga8p+vaewOc3qrA+2IBZW11fClCH8IY/JcQE/ suzz/d2hzz6CiYFrOm/a/tF8xHAUNW/m3LDm8Ku3pPK/TIGHWfY69Zd X-Developer-Key: i=quanyemostima@gmail.com; a=ed25519; pk=9L9FrcvzMgxPaBRU6XV0EnqTgjDqVO596rQKSZ9qZoY= X-Endpoint-Received: by B4 Relay for quanyemostima@gmail.com/20260801 with auth_id=905 X-Original-From: quanyeyang Reply-To: quanyemostima@gmail.com From: quanyeyang All bucket tables currently share a single lockdep class. This makes lockdep conflate bucket locks from unrelated rhashtable instances. A BPF program attached to lock_release can expose this when pidfs inserts a pid. The tracepoint runs before lockdep removes the pidfs bucket lock from the task's held-lock stack. Deleting an element from a BPF RHASH map then acquires a bucket lock belonging to a different rhashtable. Since both tables use the same class, lockdep reports possible recursive locking. Declare a separate bucket lock class key at each rhashtable_init() and rhltable_init() call site, alongside the mutex class key. Store the bucket key in struct rhashtable so tables created during resize keep using the same class. A targeted reproducer triggers the warning reliably before this change. After the change, the nested BPF RHASH deletion still executes, but lockdep no longer reports recursive locking. Fixes: 149212f07856 ("rhashtable: add lockdep tracking to bucket bit-spin-l= ocks.") Reported-by: syzbot+ef8d17bae14efb960935@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3Def8d17bae14efb960935 Assisted-by: Cursor:GPT-5.6 Sol Signed-off-by: quanyeyang --- include/linux/rhashtable-types.h | 20 ++++++++++++++------ lib/rhashtable.c | 19 +++++++++++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-ty= pes.h index 57c11ec9dc64..4dea91a49ec8 100644 --- a/include/linux/rhashtable-types.h +++ b/include/linux/rhashtable-types.h @@ -82,6 +82,7 @@ struct rhashtable_params { * @mutex: Mutex to protect current/future table swapping * @lock: Spin lock to protect walker list * @nelems: Number of elements in table + * @bucket_lock_key: Per-init-site lockdep class for bucket bit-locks */ struct rhashtable { struct bucket_table __rcu *tbl; @@ -94,6 +95,7 @@ struct rhashtable { struct mutex mutex; spinlock_t lock; atomic_t nelems; + struct lock_class_key *bucket_lock_key; #ifdef CONFIG_MEM_ALLOC_PROFILING struct alloc_tag *alloc_tag; #endif @@ -138,23 +140,29 @@ struct rhashtable_iter { =20 int __rhashtable_init_noprof(struct rhashtable *ht, const struct rhashtable_params *params, - struct lock_class_key *key); + struct lock_class_key *mutex_key, + struct lock_class_key *bucket_key); #define rhashtable_init_noprof(ht, params) \ ({ \ - static struct lock_class_key __key; \ + static struct lock_class_key __mutex_key; \ + static struct lock_class_key __bucket_key; \ \ - __rhashtable_init_noprof(ht, params, &__key); \ + __rhashtable_init_noprof(ht, params, &__mutex_key, \ + &__bucket_key); \ }) #define rhashtable_init(...) alloc_hooks(rhashtable_init_noprof(__VA_ARGS_= _)) =20 int __rhltable_init_noprof(struct rhltable *hlt, const struct rhashtable_params *params, - struct lock_class_key *key); + struct lock_class_key *mutex_key, + struct lock_class_key *bucket_key); #define rhltable_init_noprof(hlt, params) \ ({ \ - static struct lock_class_key __key; \ + static struct lock_class_key __mutex_key; \ + static struct lock_class_key __bucket_key; \ \ - __rhltable_init_noprof(hlt, params, &__key); \ + __rhltable_init_noprof(hlt, params, &__mutex_key, \ + &__bucket_key); \ }) #define rhltable_init(...) alloc_hooks(rhltable_init_noprof(__VA_ARGS__)) =20 diff --git a/lib/rhashtable.c b/lib/rhashtable.c index d459bef245f4..e047ad912f0e 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -189,7 +189,6 @@ static struct bucket_table *bucket_table_alloc(struct r= hashtable *ht, struct bucket_table *tbl =3D NULL; size_t size; int i; - static struct lock_class_key __key; =20 tbl =3D alloc_hooks_tag(ht->alloc_tag, kvmalloc_node_align_noprof(struct_size(tbl, buckets, nbuckets), @@ -205,7 +204,12 @@ static struct bucket_table *bucket_table_alloc(struct = rhashtable *ht, if (tbl =3D=3D NULL) return NULL; =20 - lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", &__key, 0); + /* + * Keep all bucket tables belonging to the same rhashtable in the + * per-init-site lock class, including tables created during resize. + */ + lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", + ht->bucket_lock_key, 0); =20 tbl->size =3D size; =20 @@ -1162,7 +1166,8 @@ static u32 rhashtable_jhash2(const void *key, u32 len= gth, u32 seed) */ int __rhashtable_init_noprof(struct rhashtable *ht, const struct rhashtable_params *params, - struct lock_class_key *key) + struct lock_class_key *mutex_key, + struct lock_class_key *bucket_key) { struct bucket_table *tbl; size_t size; @@ -1172,7 +1177,8 @@ int __rhashtable_init_noprof(struct rhashtable *ht, return -EINVAL; =20 memset(ht, 0, sizeof(*ht)); - mutex_init_with_key(&ht->mutex, key); + mutex_init_with_key(&ht->mutex, mutex_key); + ht->bucket_lock_key =3D bucket_key; spin_lock_init(&ht->lock); memcpy(&ht->p, params, sizeof(*params)); =20 @@ -1237,11 +1243,12 @@ EXPORT_SYMBOL_GPL(__rhashtable_init_noprof); */ int __rhltable_init_noprof(struct rhltable *hlt, const struct rhashtable_params *params, - struct lock_class_key *key) + struct lock_class_key *mutex_key, + struct lock_class_key *bucket_key) { int err; =20 - err =3D __rhashtable_init_noprof(&hlt->ht, params, key); + err =3D __rhashtable_init_noprof(&hlt->ht, params, mutex_key, bucket_key); hlt->ht.rhlist =3D true; return err; } --- base-commit: 0131b508c0e2489eac6e121135988f6eeb716f19 change-id: 20260801-fix-rhashtable-bucket-lockdep-95e25abebeea Best regards, -- =20 quanyeyang