mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [syzbot] [bridge?] WARNING: locking bug in match_held_lock
@ 2026-09-13  1:31 syzbot
  2026-09-15  3:40 ` Shin'ichiro Kawasaki
  0 siblings, 1 reply; 8+ messages in thread
From: syzbot @ 2026-09-13  1:31 UTC (permalink / raw)
  To: bridge, davem, edumazet, herbert, horms, idosch, kuba,
	linux-kernel, netdev, pabeni, razor, steffen.klassert,
	syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    a9d7ced84989 Add linux-next specific files for 20260908
git tree:       linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=10880f49580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=17eeb09695a2b3c9
dashboard link: https://syzkaller.appspot.com/bug?extid=4d0e4d2db6dfde01b52f
compiler:       Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8

Unfortunately, I don't have any reproducer for this issue yet.

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/4f470407358e/disk-a9d7ced8.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/858b9d7ba687/vmlinux-a9d7ced8.xz
kernel image: https://storage.googleapis.com/syzbot-assets/ef971d22d75f/bzImage-a9d7ced8.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com

------------[ cut here ]------------
Looking for class "&ht->mutex" with key xfrm_policy_init.__key.84, but found a different class "key" with the same key
WARNING: kernel/locking/lockdep.c:958 at look_up_lock_class+0x8c/0x110 kernel/locking/lockdep.c:955, CPU#1: kworker/1:6/5751
Modules linked in:
CPU: 1 UID: 0 PID: 5751 Comm: kworker/1:6 Tainted: G             L      syzkaller #0 PREEMPT(full) 
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
Workqueue: usb_hub_wq hub_event
RIP: 0010:look_up_lock_class+0x9a/0x110 kernel/locking/lockdep.c:955
Code: 00 00 49 3b 46 18 0f 84 82 00 00 00 49 81 3e d0 44 58 94 74 79 48 8d 3d 44 f2 94 04 49 8b 16 49 8b 76 18 48 8b 8b b8 00 00 00 <67> 48 0f b9 3a eb 5d 90 89 f3 e8 67 0a f4 f8 e8 32 5c be f5 48 c7
RSP: 0018:ffffc90000a38070 EFLAGS: 00010002
RAX: ffffffff8c6bb940 RBX: ffffffff94478508 RCX: ffffffff8c6bb940
RDX: ffffffff9af23440 RSI: ffffffff8c6bb900 RDI: ffffffff907ddb20
RBP: 00000000ffffffff R08: 0000000000000100 R09: 0000000000000004
R10: 0000000000000003 R11: 0000000000000300 R12: 0000000000000246
R13: ffff8880307a8000 R14: ffffffff9af232c8 R15: ffffffff9af23440
FS:  0000000000000000(0000) GS:ffff888124db7000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b3401aff8 CR3: 0000000074540000 CR4: 00000000003526f0
Call Trace:
 <IRQ>
 match_held_lock+0x9a/0x120 kernel/locking/lockdep.c:5364
 __lock_is_held kernel/locking/lockdep.c:5654 [inline]
 lock_is_held_type+0x89/0x150 kernel/locking/lockdep.c:6016
 __rhashtable_lookup include/linux/rhashtable.h:623 [inline]
 rhashtable_lookup include/linux/rhashtable.h:668 [inline]
 xfrm_policy_inexact_lookup_rcu+0x60/0x750 net/xfrm/xfrm_policy.c:2068
 xfrm_policy_lookup_bytype+0xb35/0x1840 net/xfrm/xfrm_policy.c:2193
 xfrm_policy_lookup net/xfrm/xfrm_policy.c:2225 [inline]
 xfrm_bundle_lookup net/xfrm/xfrm_policy.c:3100 [inline]
 xfrm_lookup_with_ifid+0x416/0x1db0 net/xfrm/xfrm_policy.c:3241
 xfrmi_xmit2 net/xfrm/xfrm_interface_core.c:456 [inline]
 xfrmi_xmit+0x72d/0x1b80 net/xfrm/xfrm_interface_core.c:572
 __netdev_start_xmit include/linux/netdevice.h:5433 [inline]
 netdev_start_xmit include/linux/netdevice.h:5442 [inline]
 xmit_one net/core/dev.c:3937 [inline]
 dev_hard_start_xmit+0x2cd/0x830 net/core/dev.c:3953
 __dev_queue_xmit+0x14c0/0x3820 net/core/dev.c:4926
 NF_HOOK_COND include/linux/netfilter.h:314 [inline]
 ip6_output+0x337/0x540 net/ipv6/ip6_output.c:248
 dst_output include/net/dst.h:471 [inline]
 NF_HOOK include/linux/netfilter.h:325 [inline]
 ndisc_send_skb+0xcb2/0x1650 net/ipv6/ndisc.c:513
 addrconf_rs_timer+0x2d2/0x6c0 net/ipv6/addrconf.c:4078
 call_timer_fn+0x18d/0x5f0 kernel/time/timer.c:1748
 expire_timers kernel/time/timer.c:1799 [inline]
 __run_timers kernel/time/timer.c:2374 [inline]
 __run_timer_base+0x652/0x8b0 kernel/time/timer.c:2386
 run_timer_base kernel/time/timer.c:2395 [inline]
 run_timer_softirq+0xb7/0x170 kernel/time/timer.c:2405
 handle_softirqs+0x223/0x840 kernel/softirq.c:645
 __do_softirq kernel/softirq.c:679 [inline]
 invoke_softirq kernel/softirq.c:519 [inline]
 __irq_exit_rcu+0xcb/0x220 kernel/softirq.c:758
 irq_exit_rcu+0x9/0x30 kernel/softirq.c:775
 instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1062 [inline]
 sysvec_apic_timer_interrupt+0xa6/0xc0 arch/x86/kernel/apic/apic.c:1062
 </IRQ>
 <TASK>
 asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:674
RIP: 0010:finish_task_switch+0x413/0xc60 kernel/sched/core.c:5378
Code: 04 00 00 41 c7 84 24 20 0e 00 00 00 00 00 00 0f 1f 44 00 00 49 83 c4 48 4c 89 e7 e8 57 48 55 0a e8 d2 1b 3a 00 fb 4c 8b 65 c8 <49> 8d bc 24 10 17 00 00 48 89 f8 48 c1 e8 03 42 0f b6 04 30 84 c0
RSP: 0018:ffffc900043ad940 EFLAGS: 00000206
RAX: 000000000004ba5f RBX: ffff8880b873cb20 RCX: 8000000000000001
RDX: 0000000000000006 RSI: ffffffff8e47d8da RDI: ffffffff8c6dc080
RBP: ffffc900043ad990 R08: ffffffff907a9cbf R09: 1ffffffff20f5397
R10: dffffc0000000000 R11: fffffbfff20f5398 R12: ffff8880307a8000
R13: ffff8880b873cae8 R14: dffffc0000000000 R15: 1ffff110170e7964
 context_switch kernel/sched/core.c:5530 [inline]
 __schedule+0x17e5/0x5940 kernel/sched/core.c:7295
 preempt_schedule_common+0x7f/0xd0 kernel/sched/core.c:7474
 preempt_schedule_thunk+0x16/0x40 arch/x86/entry/thunk.S:12
 __mutex_lock_common kernel/locking/mutex.c:656 [inline]
 __mutex_lock+0x31b/0x15a0 kernel/locking/mutex.c:821
 clear_eld drivers/gpu/drm/drm_edid.c:5691 [inline]
 update_display_info+0x455/0x9630 drivers/gpu/drm/drm_edid.c:6934
 drm_edid_connector_update+0x9b/0x13d0 drivers/gpu/drm/drm_edid.c:7338
 drm_connector_update_edid_property+0xde/0x140 drivers/gpu/drm/drm_edid.c:7396
 drm_helper_probe_single_connector_modes+0x126b/0x1880 drivers/gpu/drm/drm_probe_helper.c:644
 drm_client_modeset_probe+0x4e8/0x60c0 drivers/gpu/drm/drm_client_modeset.c:869
 __drm_fb_helper_initial_config_and_unlock+0x10e/0x1b50 drivers/gpu/drm/drm_fb_helper.c:1717
 drm_fbdev_client_hotplug+0x16c/0x230 drivers/gpu/drm/clients/drm_fbdev_client.c:66
 drm_client_register+0x16e/0x200 drivers/gpu/drm/drm_client.c:143
 drm_fbdev_client_setup+0x1a0/0x450 drivers/gpu/drm/clients/drm_fbdev_client.c:168
 drm_client_setup+0x107/0x220 drivers/gpu/drm/clients/drm_client_setup.c:46
 udl_usb_probe+0x137/0x150 drivers/gpu/drm/udl/udl_drv.c:105
 usb_probe_interface+0x788/0xe50 drivers/usb/core/driver.c:399
 call_driver_probe drivers/base/dd.c:-1 [inline]
 really_probe+0x254/0xae0 drivers/base/dd.c:706
 __driver_probe_device+0x1e8/0x360 drivers/base/dd.c:868
 driver_probe_device+0x4f/0x240 drivers/base/dd.c:898
 __device_attach_driver+0x270/0x410 drivers/base/dd.c:1026
 bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
 __device_attach+0x2c4/0x450 drivers/base/dd.c:1098
 device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1153
 bus_probe_device+0x12a/0x220 drivers/base/bus.c:620
 device_add+0x7d7/0xb80 drivers/base/core.c:3776
 usb_set_configuration+0x1ad8/0x2180 drivers/usb/core/message.c:2268
 usb_generic_driver_probe+0x8d/0x150 drivers/usb/core/generic.c:250
 usb_probe_device+0x1c3/0x3b0 drivers/usb/core/driver.c:293
 call_driver_probe drivers/base/dd.c:-1 [inline]
 really_probe+0x254/0xae0 drivers/base/dd.c:706
 __driver_probe_device+0x1e8/0x360 drivers/base/dd.c:868
 driver_probe_device+0x4f/0x240 drivers/base/dd.c:898
 __device_attach_driver+0x270/0x410 drivers/base/dd.c:1026
 bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
 __device_attach+0x2c4/0x450 drivers/base/dd.c:1098
 device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1153
 bus_probe_device+0x12a/0x220 drivers/base/bus.c:620
 device_add+0x7d7/0xb80 drivers/base/core.c:3776
 usb_new_device+0x9aa/0x1690 drivers/usb/core/hub.c:2708
 hub_port_connect drivers/usb/core/hub.c:5580 [inline]
 hub_port_connect_change drivers/usb/core/hub.c:5720 [inline]
 port_event drivers/usb/core/hub.c:5884 [inline]
 hub_event+0x28e8/0x4d30 drivers/usb/core/hub.c:5966
 process_one_work kernel/workqueue.c:3407 [inline]
 process_scheduled_works+0xc3d/0x1630 kernel/workqueue.c:3490
 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3571
 kthread+0x38b/0x480 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>
----------------
Code disassembly (best guess):
   0:	00 00                	add    %al,(%rax)
   2:	49 3b 46 18          	cmp    0x18(%r14),%rax
   6:	0f 84 82 00 00 00    	je     0x8e
   c:	49 81 3e d0 44 58 94 	cmpq   $0xffffffff945844d0,(%r14)
  13:	74 79                	je     0x8e
  15:	48 8d 3d 44 f2 94 04 	lea    0x494f244(%rip),%rdi        # 0x494f260
  1c:	49 8b 16             	mov    (%r14),%rdx
  1f:	49 8b 76 18          	mov    0x18(%r14),%rsi
  23:	48 8b 8b b8 00 00 00 	mov    0xb8(%rbx),%rcx
* 2a:	67 48 0f b9 3a       	ud1    (%edx),%rdi <-- trapping instruction
  2f:	eb 5d                	jmp    0x8e
  31:	90                   	nop
  32:	89 f3                	mov    %esi,%ebx
  34:	e8 67 0a f4 f8       	call   0xf8f40aa0
  39:	e8 32 5c be f5       	call   0xf5be5c70
  3e:	48                   	rex.W
  3f:	c7                   	.byte 0xc7


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

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

* Re: [syzbot] [bridge?] WARNING: locking bug in match_held_lock
  2026-09-13  1:31 [syzbot] [bridge?] WARNING: locking bug in match_held_lock syzbot
@ 2026-09-15  3:40 ` Shin'ichiro Kawasaki
  2026-09-15  4:06   ` Eric Dumazet
  0 siblings, 1 reply; 8+ messages in thread
From: Shin'ichiro Kawasaki @ 2026-09-15  3:40 UTC (permalink / raw)
  To: syzbot
  Cc: bridge, davem, edumazet, herbert, horms, idosch, kuba,
	linux-kernel, netdev, pabeni, razor, steffen.klassert,
	syzkaller-bugs, Thomas Graf, linux-crypto

CC+: linux-crypto and rhashtable maintainers,

On Sep 12, 2026 / 18:31, syzbot wrote:
> Hello,
> 
> syzbot found the following issue on:
> 
> HEAD commit:    a9d7ced84989 Add linux-next specific files for 20260908
> git tree:       linux-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=10880f49580000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=17eeb09695a2b3c9
> dashboard link: https://syzkaller.appspot.com/bug?extid=4d0e4d2db6dfde01b52f
> compiler:       Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
> 
> Unfortunately, I don't have any reproducer for this issue yet.
> 
> Downloadable assets:
> disk image: https://storage.googleapis.com/syzbot-assets/4f470407358e/disk-a9d7ced8.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/858b9d7ba687/vmlinux-a9d7ced8.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/ef971d22d75f/bzImage-a9d7ced8.xz
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
> 
> ------------[ cut here ]------------
> Looking for class "&ht->mutex" with key xfrm_policy_init.__key.84, but found a different class "key" with the same key
> WARNING: kernel/locking/lockdep.c:958 at look_up_lock_class+0x8c/0x110 kernel/locking/lockdep.c:955, CPU#1: kworker/1:6/5751
> Modules linked in:
> CPU: 1 UID: 0 PID: 5751 Comm: kworker/1:6 Tainted: G             L      syzkaller #0 PREEMPT(full) 
> Tainted: [L]=SOFTLOCKUP
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
> Workqueue: usb_hub_wq hub_event
> RIP: 0010:look_up_lock_class+0x9a/0x110 kernel/locking/lockdep.c:955
> Code: 00 00 49 3b 46 18 0f 84 82 00 00 00 49 81 3e d0 44 58 94 74 79 48 8d 3d 44 f2 94 04 49 8b 16 49 8b 76 18 48 8b 8b b8 00 00 00 <67> 48 0f b9 3a eb 5d 90 89 f3 e8 67 0a f4 f8 e8 32 5c be f5 48 c7
> RSP: 0018:ffffc90000a38070 EFLAGS: 00010002
> RAX: ffffffff8c6bb940 RBX: ffffffff94478508 RCX: ffffffff8c6bb940
> RDX: ffffffff9af23440 RSI: ffffffff8c6bb900 RDI: ffffffff907ddb20
> RBP: 00000000ffffffff R08: 0000000000000100 R09: 0000000000000004
> R10: 0000000000000003 R11: 0000000000000300 R12: 0000000000000246
> R13: ffff8880307a8000 R14: ffffffff9af232c8 R15: ffffffff9af23440
> FS:  0000000000000000(0000) GS:ffff888124db7000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000001b3401aff8 CR3: 0000000074540000 CR4: 00000000003526f0
> Call Trace:
>  <IRQ>
>  match_held_lock+0x9a/0x120 kernel/locking/lockdep.c:5364
>  __lock_is_held kernel/locking/lockdep.c:5654 [inline]
>  lock_is_held_type+0x89/0x150 kernel/locking/lockdep.c:6016
>  __rhashtable_lookup include/linux/rhashtable.h:623 [inline]
>  rhashtable_lookup include/linux/rhashtable.h:668 [inline]
>  xfrm_policy_inexact_lookup_rcu+0x60/0x750 net/xfrm/xfrm_policy.c:2068
>  xfrm_policy_lookup_bytype+0xb35/0x1840 net/xfrm/xfrm_policy.c:2193
...

FYI, I also observed the WARN at look_up_lock_class() and match_held_lock()
called in the rhashtable_lookup() context [1]. I used the kernel next-20260909.
The WARN was observed during the run of blktests test case block/008 on dm-
flakey device, but this test workload does not look related to the WARN. I tried
to reproduce the WARN by repeating the test workload hundreds of times, and
succeeded only once. The WARN looks rare, but I'm sure the WARN happned.

The call trace that syzbot reported and that I observed look rather different.
The common part across them is the rhashtable_lookup() call. So I think it is
the better to involve rhashtable experts. I took the liberty CC to them.


[1] WARN observed at blktests block/008 for dm-flakey

WARNING: kernel/locking/lockdep.c:955 at look_up_lock_class+0xa8/0x170, CPU#14: kworker/14:1/309662
Modules linked in: dm_flakey iscsi_target_mod tcm_loop target_core_pscsi target_core_file target_core_iblock xfs target_core_user target_core_mod nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject qrtr nft_ct nft_chain_nat ip6table_nat ip6table_mangle ip6table_raw ip6table_security iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle rfkill iptable_raw iptable_security nf_tables ip6table_filter ip6_tables iptable_filter ip_tables irdma ice sunrpc libie_fwlog gnss idpf libeth_xdp libie_pci libie_cp libeth ib_core intel_rapl_msr intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common skx_edac skx_edac_common nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel spi_nor mtd kvm i40e irqbypass iTCO_wdt rapl intel_pmc_bxt vfat ses intel_cstate libie fat intel_uncore libie_adminq enclosure i2c_i801 spi_intel_pci spi_intel i2c_smbus lpc_ich mei_me mei intel_pch_thermal wmi joydev ioatdma acpi_pad
 acpi_power_meter dca fuse dm_multipath zram lz4hc_compress zstd_compress ast drm_client_lib i2c_algo_bit drm_shmem_helper drm_kms_helper nvme drm nvme_core mpi3mr nvme_keyring nvme_auth scsi_transport_sas scsi_dh_alua pkcs8_key_parser scsi_dh_emc scsi_dh_rdac i2c_dev [last unloaded: null_blk]
CPU: 14 UID: 0 PID: 309662 Comm: kworker/14:1 Tainted: G        W           7.3.0-rc2-next-20260909-kts+ #1 PREEMPT(lazy) 
Tainted: [W]=WARN
Hardware name: Supermicro Super Server/X11SPi-TF, BIOS 3.5 05/18/2021
Workqueue: events drm_fb_helper_damage_work [drm_kms_helper]
RIP: 0010:look_up_lock_class+0xa8/0x170
Code: 39 6b 40 75 ed 48 8b 8b b8 00 00 00 49 8b 74 24 18 48 39 f1 74 34 49 8b 14 24 48 81 fa f0 31 7f 9a 74 27 48 8d 3d b8 66 4a 02 <67> 48 0f b9 3a 48 89 d8 48 8b 6c 24 10 4c 8b 64 24 18 48 8b 5c 24
RSP: 0018:ffff888e40108088 EFLAGS: 00010002
RAX: 0000000000000001 RBX: ffffffff9e852a78 RCX: ffffffff97838ae0
RDX: ffffffffc271a2a0 RSI: ffffffff97838a60 RDI: ffffffff997aa470
RBP: ffffffffc271a2a0 R08: 0000000000000001 R09: ffff888133ab3018
R10: 0000000000000004 R11: ffff888e40108360 R12: ffff88812d59e1f8
R13: 0000000000000003 R14: 0000000000000246 R15: 00000000ffffffff
FS:  0000000000000000(0000) GS:ffff888ea59d3000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055dba25b8c90 CR3: 00000002a6911004 CR4: 00000000007726f0
PKRU: 55555554
Call Trace:
 <IRQ>
 match_held_lock+0xdb/0x130
 lock_is_held_type+0xb0/0x180
 nft_rhash_lookup+0x541/0x7e0 [nf_tables]
 ? find_held_lock+0x2b/0x80
 ? __lock_release.isra.0+0x69/0x1a0
 ? lock_release.part.0+0x1c/0x50
 ? __pfx_nft_rhash_lookup+0x10/0x10 [nf_tables]
 nft_set_do_lookup+0x1ac/0x2a0 [nf_tables]
 ? fib_lookup_good_nhc+0x104/0x380
 nft_lookup_eval+0xcc/0x590 [nf_tables]
 ? lock_is_held_type+0xb0/0x180
 nft_do_chain+0x2a9/0x1680 [nf_tables]
 ? __lock_acquire+0x690/0xd00
 ? __pfx_nft_do_chain+0x10/0x10 [nf_tables]
 ? lock_acquire.part.0+0xc8/0x240
 ? find_held_lock+0x2b/0x80
 ? __local_bh_enable_ip+0xb4/0x150
 ? ipt_do_table+0xa10/0x11e0 [ip_tables]
 ? ipt_do_table+0xa15/0x11e0 [ip_tables]
 nft_do_chain_inet+0xdc/0x4a0 [nf_tables]
 ? __pfx_nft_do_chain_inet+0x10/0x10 [nf_tables]
 ? __pfx_ipt_do_table+0x10/0x10 [ip_tables]
 nf_hook_slow+0xbe/0x210
 ? lock_is_held_type+0xb0/0x180
 ip_local_deliver+0x2d0/0x4a0
 ? __pfx_ip_local_deliver+0x10/0x10
 ? __pfx_ip_local_deliver_finish+0x10/0x10
 ? ip_rcv_finish_core+0x75b/0x1470
 ? lock_is_held_type+0xb0/0x180
 ip_list_rcv_finish+0x7f8/0xbb0
 ? ip_sublist_rcv+0x106/0x2f0
 ? __pfx_ip_list_rcv_finish+0x10/0x10
 ? __lock_release.isra.0+0x69/0x1a0
 ip_sublist_rcv+0x8b/0x2f0
 ? __pfx_ip_sublist_rcv+0x10/0x10
 ? __pfx_ip_rcv_finish+0x10/0x10
 ? ip_rcv_core+0x619/0xd00
 ? kasan_save_stack+0x2f/0x50
 ip_list_rcv+0x2dd/0x440
 ? asm_common_interrupt+0x26/0x40
 ? __pfx_ip_list_rcv+0x10/0x10
 ? drm_atomic_helper_commit_planes+0x3bd/0x1040 [drm_kms_helper]
 ? commit_tail+0x204/0x4b0 [drm_kms_helper]
 ? __lock_acquire+0x691/0xd00
 __netif_receive_skb_list_core+0x6bf/0xa10
 ? __pfx___netif_receive_skb_list_core+0x10/0x10
 ? lock_acquire.part.0+0xc8/0x240
 ? netif_receive_skb_list_internal+0x382/0xc90
 ? lock_acquire+0x11a/0x140
 netif_receive_skb_list_internal+0x603/0xc90
 ? dev_gro_receive+0x1e0/0x15f0
 ? __pfx_netif_receive_skb_list_internal+0x10/0x10
 ? napi_build_skb+0x55/0x1e0
 ? i40e_process_skb_fields+0x4a6/0xea0 [i40e]
 ? i40e_clean_rx_irq+0x96f/0x2140 [i40e]
 napi_complete_done+0x1a4/0x900
 ? __pfx_napi_complete_done+0x10/0x10
 i40e_napi_poll+0x408/0xb70 [i40e]
 ? __pfx_i40e_napi_poll+0x10/0x10 [i40e]
 __napi_poll+0x351/0x520
 net_rx_action+0x446/0xc30
 ? __pfx_net_rx_action+0x10/0x10
 ? do_raw_spin_unlock+0x59/0x230
 ? lock_release.part.0+0x1c/0x50
 ? sched_clock_cpu+0x69/0x630
 ? mark_held_locks+0x40/0x70
 handle_softirqs+0x1de/0x830
 ? __pfx_handle_softirqs+0x10/0x10
 ? irqtime_account_irq+0x3e/0x2d0
 __irq_exit_rcu+0x164/0x290
 irq_exit_rcu+0xe/0x20
 common_interrupt+0x85/0xa0
 </IRQ>
 <TASK>
 asm_common_interrupt+0x26/0x40
RIP: 0010:memcpy_toio+0xa3/0x120
Code: 5c e9 d1 59 9f 01 48 85 db 74 ee 40 f6 c5 01 75 49 48 83 fb 01 76 06 40 f6 c5 02 75 29 48 89 d9 48 89 ef 4c 89 e6 48 c1 e9 02 <f3> a5 f6 c3 02 74 02 66 a5 f6 c3 01 74 01 a4 48 83 c4 18 5b 5d 41
RSP: 0018:ffff88811b3a7538 EFLAGS: 00010206
RAX: 0000000000000000 RBX: 0000000000001000 RCX: 00000000000003f0

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

* Re: [syzbot] [bridge?] WARNING: locking bug in match_held_lock
  2026-09-15  3:40 ` Shin'ichiro Kawasaki
@ 2026-09-15  4:06   ` Eric Dumazet
  2026-09-15  6:04     ` [PATCH] rhashtable: Use separate lockdep keys for each lock Herbert Xu
  0 siblings, 1 reply; 8+ messages in thread
From: Eric Dumazet @ 2026-09-15  4:06 UTC (permalink / raw)
  To: Shin'ichiro Kawasaki
  Cc: syzbot, bridge, davem, herbert, horms, idosch, kuba,
	linux-kernel, netdev, pabeni, razor, steffen.klassert,
	syzkaller-bugs, Thomas Graf, linux-crypto

On Mon, Sep 14, 2026 at 8:40 PM Shin'ichiro Kawasaki
<shinichiro.kawasaki@wdc.com> wrote:
>
> CC+: linux-crypto and rhashtable maintainers,
>
> On Sep 12, 2026 / 18:31, syzbot wrote:
> > Hello,
> >
> > syzbot found the following issue on:
> >
> > HEAD commit:    a9d7ced84989 Add linux-next specific files for 20260908
> > git tree:       linux-next
> > console output: https://syzkaller.appspot.com/x/log.txt?x=10880f49580000
> > kernel config:  https://syzkaller.appspot.com/x/.config?x=17eeb09695a2b3c9
> > dashboard link: https://syzkaller.appspot.com/bug?extid=4d0e4d2db6dfde01b52f
> > compiler:       Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
> >
> > Unfortunately, I don't have any reproducer for this issue yet.
> >
> > Downloadable assets:
> > disk image: https://storage.googleapis.com/syzbot-assets/4f470407358e/disk-a9d7ced8.raw.xz
> > vmlinux: https://storage.googleapis.com/syzbot-assets/858b9d7ba687/vmlinux-a9d7ced8.xz
> > kernel image: https://storage.googleapis.com/syzbot-assets/ef971d22d75f/bzImage-a9d7ced8.xz
> >
> > IMPORTANT: if you fix the issue, please add the following tag to the commit:
> > Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
> >
> > ------------[ cut here ]------------
> > Looking for class "&ht->mutex" with key xfrm_policy_init.__key.84, but found a different class "key" with the same key
> > WARNING: kernel/locking/lockdep.c:958 at look_up_lock_class+0x8c/0x110 kernel/locking/lockdep.c:955, CPU#1: kworker/1:6/5751
> > Modules linked in:
> > CPU: 1 UID: 0 PID: 5751 Comm: kworker/1:6 Tainted: G             L      syzkaller #0 PREEMPT(full)
> > Tainted: [L]=SOFTLOCKUP
> > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
> > Workqueue: usb_hub_wq hub_event
> > RIP: 0010:look_up_lock_class+0x9a/0x110 kernel/locking/lockdep.c:955
> > Code: 00 00 49 3b 46 18 0f 84 82 00 00 00 49 81 3e d0 44 58 94 74 79 48 8d 3d 44 f2 94 04 49 8b 16 49 8b 76 18 48 8b 8b b8 00 00 00 <67> 48 0f b9 3a eb 5d 90 89 f3 e8 67 0a f4 f8 e8 32 5c be f5 48 c7
> > RSP: 0018:ffffc90000a38070 EFLAGS: 00010002
> > RAX: ffffffff8c6bb940 RBX: ffffffff94478508 RCX: ffffffff8c6bb940
> > RDX: ffffffff9af23440 RSI: ffffffff8c6bb900 RDI: ffffffff907ddb20
> > RBP: 00000000ffffffff R08: 0000000000000100 R09: 0000000000000004
> > R10: 0000000000000003 R11: 0000000000000300 R12: 0000000000000246
> > R13: ffff8880307a8000 R14: ffffffff9af232c8 R15: ffffffff9af23440
> > FS:  0000000000000000(0000) GS:ffff888124db7000(0000) knlGS:0000000000000000
> > CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > CR2: 0000001b3401aff8 CR3: 0000000074540000 CR4: 00000000003526f0
> > Call Trace:
> >  <IRQ>
> >  match_held_lock+0x9a/0x120 kernel/locking/lockdep.c:5364
> >  __lock_is_held kernel/locking/lockdep.c:5654 [inline]
> >  lock_is_held_type+0x89/0x150 kernel/locking/lockdep.c:6016
> >  __rhashtable_lookup include/linux/rhashtable.h:623 [inline]
> >  rhashtable_lookup include/linux/rhashtable.h:668 [inline]
> >  xfrm_policy_inexact_lookup_rcu+0x60/0x750 net/xfrm/xfrm_policy.c:2068
> >  xfrm_policy_lookup_bytype+0xb35/0x1840 net/xfrm/xfrm_policy.c:2193
> ...
>
> FYI, I also observed the WARN at look_up_lock_class() and match_held_lock()
> called in the rhashtable_lookup() context [1]. I used the kernel next-20260909.
> The WARN was observed during the run of blktests test case block/008 on dm-
> flakey device, but this test workload does not look related to the WARN. I tried
> to reproduce the WARN by repeating the test workload hundreds of times, and
> succeeded only once. The WARN looks rare, but I'm sure the WARN happned.
>
> The call trace that syzbot reported and that I observed look rather different.
> The common part across them is the rhashtable_lookup() call. So I think it is
> the better to involve rhashtable experts. I took the liberty CC to them.
>
>
> [1] WARN observed at blktests block/008 for dm-flakey
>
> WARNING: kernel/locking/lockdep.c:955 at look_up_lock_class+0xa8/0x170, CPU#14: kworker/14:1/309662
> Modules linked in: dm_flakey iscsi_target_mod tcm_loop target_core_pscsi target_core_file target_core_iblock xfs target_core_user target_core_mod nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject qrtr nft_ct nft_chain_nat ip6table_nat ip6table_mangle ip6table_raw ip6table_security iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle rfkill iptable_raw iptable_security nf_tables ip6table_filter ip6_tables iptable_filter ip_tables irdma ice sunrpc libie_fwlog gnss idpf libeth_xdp libie_pci libie_cp libeth ib_core intel_rapl_msr intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common skx_edac skx_edac_common nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel spi_nor mtd kvm i40e irqbypass iTCO_wdt rapl intel_pmc_bxt vfat ses intel_cstate libie fat intel_uncore libie_adminq enclosure i2c_i801 spi_intel_pci spi_intel i2c_smbus lpc_ich mei_me mei intel_pch_thermal wmi joydev ioatdma acpi_pad
>  acpi_power_meter dca fuse dm_multipath zram lz4hc_compress zstd_compress ast drm_client_lib i2c_algo_bit drm_shmem_helper drm_kms_helper nvme drm nvme_core mpi3mr nvme_keyring nvme_auth scsi_transport_sas scsi_dh_alua pkcs8_key_parser scsi_dh_emc scsi_dh_rdac i2c_dev [last unloaded: null_blk]
> CPU: 14 UID: 0 PID: 309662 Comm: kworker/14:1 Tainted: G        W           7.3.0-rc2-next-20260909-kts+ #1 PREEMPT(lazy)
> Tainted: [W]=WARN
> Hardware name: Supermicro Super Server/X11SPi-TF, BIOS 3.5 05/18/2021
> Workqueue: events drm_fb_helper_damage_work [drm_kms_helper]
> RIP: 0010:look_up_lock_class+0xa8/0x170
> Code: 39 6b 40 75 ed 48 8b 8b b8 00 00 00 49 8b 74 24 18 48 39 f1 74 34 49 8b 14 24 48 81 fa f0 31 7f 9a 74 27 48 8d 3d b8 66 4a 02 <67> 48 0f b9 3a 48 89 d8 48 8b 6c 24 10 4c 8b 64 24 18 48 8b 5c 24
> RSP: 0018:ffff888e40108088 EFLAGS: 00010002
> RAX: 0000000000000001 RBX: ffffffff9e852a78 RCX: ffffffff97838ae0
> RDX: ffffffffc271a2a0 RSI: ffffffff97838a60 RDI: ffffffff997aa470
> RBP: ffffffffc271a2a0 R08: 0000000000000001 R09: ffff888133ab3018
> R10: 0000000000000004 R11: ffff888e40108360 R12: ffff88812d59e1f8
> R13: 0000000000000003 R14: 0000000000000246 R15: 00000000ffffffff
> FS:  0000000000000000(0000) GS:ffff888ea59d3000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 000055dba25b8c90 CR3: 00000002a6911004 CR4: 00000000007726f0
> PKRU: 55555554
> Call Trace:
>  <IRQ>
>  match_held_lock+0xdb/0x130
>  lock_is_held_type+0xb0/0x180
>  nft_rhash_lookup+0x541/0x7e0 [nf_tables]
>  ? find_held_lock+0x2b/0x80
>  ? __lock_release.isra.0+0x69/0x1a0
>  ? lock_release.part.0+0x1c/0x50
>  ? __pfx_nft_rhash_lookup+0x10/0x10 [nf_tables]
>  nft_set_do_lookup+0x1ac/0x2a0 [nf_tables]
>  ? fib_lookup_good_nhc+0x104/0x380
>  nft_lookup_eval+0xcc/0x590 [nf_tables]
>  ? lock_is_held_type+0xb0/0x180
>  nft_do_chain+0x2a9/0x1680 [nf_tables]
>  ? __lock_acquire+0x690/0xd00
>  ? __pfx_nft_do_chain+0x10/0x10 [nf_tables]
>  ? lock_acquire.part.0+0xc8/0x240
>  ? find_held_lock+0x2b/0x80
>  ? __local_bh_enable_ip+0xb4/0x150
>  ? ipt_do_table+0xa10/0x11e0 [ip_tables]
>  ? ipt_do_table+0xa15/0x11e0 [ip_tables]
>  nft_do_chain_inet+0xdc/0x4a0 [nf_tables]
>  ? __pfx_nft_do_chain_inet+0x10/0x10 [nf_tables]
>  ? __pfx_ipt_do_table+0x10/0x10 [ip_tables]
>  nf_hook_slow+0xbe/0x210
>  ? lock_is_held_type+0xb0/0x180
>  ip_local_deliver+0x2d0/0x4a0
>  ? __pfx_ip_local_deliver+0x10/0x10
>  ? __pfx_ip_local_deliver_finish+0x10/0x10
>  ? ip_rcv_finish_core+0x75b/0x1470
>  ? lock_is_held_type+0xb0/0x180
>  ip_list_rcv_finish+0x7f8/0xbb0
>  ? ip_sublist_rcv+0x106/0x2f0
>  ? __pfx_ip_list_rcv_finish+0x10/0x10
>  ? __lock_release.isra.0+0x69/0x1a0
>  ip_sublist_rcv+0x8b/0x2f0
>  ? __pfx_ip_sublist_rcv+0x10/0x10
>  ? __pfx_ip_rcv_finish+0x10/0x10
>  ? ip_rcv_core+0x619/0xd00
>  ? kasan_save_stack+0x2f/0x50
>  ip_list_rcv+0x2dd/0x440
>  ? asm_common_interrupt+0x26/0x40
>  ? __pfx_ip_list_rcv+0x10/0x10
>  ? drm_atomic_helper_commit_planes+0x3bd/0x1040 [drm_kms_helper]
>  ? commit_tail+0x204/0x4b0 [drm_kms_helper]
>  ? __lock_acquire+0x691/0xd00
>  __netif_receive_skb_list_core+0x6bf/0xa10
>  ? __pfx___netif_receive_skb_list_core+0x10/0x10
>  ? lock_acquire.part.0+0xc8/0x240
>  ? netif_receive_skb_list_internal+0x382/0xc90
>  ? lock_acquire+0x11a/0x140
>  netif_receive_skb_list_internal+0x603/0xc90
>  ? dev_gro_receive+0x1e0/0x15f0
>  ? __pfx_netif_receive_skb_list_internal+0x10/0x10
>  ? napi_build_skb+0x55/0x1e0
>  ? i40e_process_skb_fields+0x4a6/0xea0 [i40e]
>  ? i40e_clean_rx_irq+0x96f/0x2140 [i40e]
>  napi_complete_done+0x1a4/0x900
>  ? __pfx_napi_complete_done+0x10/0x10
>  i40e_napi_poll+0x408/0xb70 [i40e]
>  ? __pfx_i40e_napi_poll+0x10/0x10 [i40e]
>  __napi_poll+0x351/0x520
>  net_rx_action+0x446/0xc30
>  ? __pfx_net_rx_action+0x10/0x10
>  ? do_raw_spin_unlock+0x59/0x230
>  ? lock_release.part.0+0x1c/0x50
>  ? sched_clock_cpu+0x69/0x630
>  ? mark_held_locks+0x40/0x70
>  handle_softirqs+0x1de/0x830
>  ? __pfx_handle_softirqs+0x10/0x10
>  ? irqtime_account_irq+0x3e/0x2d0
>  __irq_exit_rcu+0x164/0x290
>  irq_exit_rcu+0xe/0x20
>  common_interrupt+0x85/0xa0
>  </IRQ>
>  <TASK>
>  asm_common_interrupt+0x26/0x40
> RIP: 0010:memcpy_toio+0xa3/0x120
> Code: 5c e9 d1 59 9f 01 48 85 db 74 ee 40 f6 c5 01 75 49 48 83 fb 01 76 06 40 f6 c5 02 75 29 48 89 d9 48 89 ef 4c 89 e6 48 c1 e9 02 <f3> a5 f6 c3 02 74 02 66 a5 f6 c3 01 74 01 a4 48 83 c4 18 5b 5d 41
> RSP: 0018:ffff88811b3a7538 EFLAGS: 00010206
> RAX: 0000000000000000 RBX: 0000000000001000 RCX: 00000000000003f0

Try to revert 4333ab90aaae ("rhashtable: use private lockdep class for
all locks.")

Thanks.

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

* [PATCH] rhashtable: Use separate lockdep keys for each lock
  2026-09-15  4:06   ` Eric Dumazet
@ 2026-09-15  6:04     ` Herbert Xu
  2026-09-15 21:06       ` NeilBrown
  2026-09-16  8:00       ` [v2 PATCH] " Herbert Xu
  0 siblings, 2 replies; 8+ messages in thread
From: Herbert Xu @ 2026-09-15  6:04 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Shin'ichiro Kawasaki, syzbot, bridge, davem, horms, idosch,
	kuba, linux-kernel, netdev, pabeni, razor, steffen.klassert,
	syzkaller-bugs, Thomas Graf, linux-crypto, NeilBrown, quanyeyang

On Mon, Sep 14, 2026 at 09:06:49PM -0700, Eric Dumazet wrote:
>
> Try to revert 4333ab90aaae ("rhashtable: use private lockdep class for
> all locks.")

Yes this is indeed buggy.  I know nothing about lockdep but Gemini
reckons that it should use separate keys instead of different
depths which seems fair enough:

---8<---
Use separate lockdep keys for the different types of locks in
rhashtable (mutex, spin lock, and bucket locks).  They are
separate and not normally nested with respect to each other.

Also move the rhashtable_init/rhltable_init kdoc to the header
file as that's where the macros are defined.

Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.")
Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
Assisted-by: Gemini:gemini-3.6-flash
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 0e1b172a4f6c..afbc12ba71f5 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -70,6 +70,14 @@ struct rhashtable_params {
 	rht_obj_cmpfn_t		obj_cmpfn;
 };
 
+struct rhashtable_lockdep_keys {
+#ifdef CONFIG_LOCKDEP
+	struct lock_class_key lock_key;
+	struct lock_class_key mutex_key;
+	struct lock_class_key bucket_key;
+#endif
+};
+
 /**
  * struct rhashtable - Hash table handle
  * @tbl: Bucket table
@@ -141,24 +149,77 @@ struct rhashtable_iter {
 
 int __rhashtable_init_noprof(struct rhashtable *ht,
 		    const struct rhashtable_params *params,
-		    struct lock_class_key *key);
+		    struct rhashtable_lockdep_keys *keys);
 #define rhashtable_init_noprof(ht, params)				\
 ({									\
-	static struct lock_class_key __key;				\
+	static struct rhashtable_lockdep_keys __keys;			\
 									\
-	__rhashtable_init_noprof(ht, params, &__key);			\
+	__rhashtable_init_noprof(ht, params, &__keys);			\
 })
+
+/**
+ * rhashtable_init - initialize a new hash table
+ * @ht:		hash table to be initialized
+ * @params:	configuration parameters
+ *
+ * Initializes a new hash table based on the provided configuration
+ * parameters. A table can be configured either with a variable or
+ * fixed length key:
+ *
+ * Configuration Example 1: Fixed length keys
+ * struct test_obj {
+ *	int			key;
+ *	void *			my_member;
+ *	struct rhash_head	node;
+ * };
+ *
+ * struct rhashtable_params params = {
+ *	.head_offset = offsetof(struct test_obj, node),
+ *	.key_offset = offsetof(struct test_obj, key),
+ *	.key_len = sizeof(int),
+ *	.hashfn = jhash,
+ * };
+ *
+ * Configuration Example 2: Variable length keys
+ * struct test_obj {
+ *	[...]
+ *	struct rhash_head	node;
+ * };
+ *
+ * u32 my_hash_fn(const void *data, u32 len, u32 seed)
+ * {
+ *	struct test_obj *obj = data;
+ *
+ *	return [... hash ...];
+ * }
+ *
+ * struct rhashtable_params params = {
+ *	.head_offset = offsetof(struct test_obj, node),
+ *	.hashfn = jhash,
+ *	.obj_hashfn = my_hash_fn,
+ * };
+ */
 #define rhashtable_init(...)	alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
 
 int __rhltable_init_noprof(struct rhltable *hlt,
 		  const struct rhashtable_params *params,
-		  struct lock_class_key *key);
+		  struct rhashtable_lockdep_keys *keys);
 #define rhltable_init_noprof(hlt, params)				\
 ({									\
-	static struct lock_class_key __key;				\
+	static struct rhashtable_lockdep_keys __keys;			\
 									\
-	__rhltable_init_noprof(hlt, params, &__key);			\
+	__rhltable_init_noprof(hlt, params, &__keys);			\
 })
+
+/**
+ * rhltable_init - initialize a new hash list table
+ * @hlt:	hash list table to be initialized
+ * @params:	configuration parameters
+ *
+ * Initializes a new hash list table.
+ *
+ * See documentation for rhashtable_init.
+ */
 #define rhltable_init(...)	alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
 
 #endif /* _LINUX_RHASHTABLE_TYPES_H */
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 6c5e6d9accba..ec853c1b9af3 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -328,8 +328,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
 
 	local_irq_save(flags);
 	bit_spin_lock(0, (unsigned long *)bucket);
-	/* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */
-	lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_);
+	lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_);
 	return flags;
 }
 
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 5da0e53a8d42..918f15a2ac69 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -432,7 +432,7 @@ static void rht_deferred_worker(struct work_struct *work)
 	int err = 0;
 
 	ht = container_of(work, struct rhashtable, run_work);
-	mutex_lock_nested(&ht->mutex, 1);
+	mutex_lock(&ht->mutex);
 
 	tbl = rht_dereference(ht->tbl, ht);
 	tbl = rhashtable_last_table(ht, tbl);
@@ -1122,51 +1122,9 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
 	return jhash2(key, length, seed);
 }
 
-/**
- * rhashtable_init - initialize a new hash table
- * @ht:		hash table to be initialized
- * @params:	configuration parameters
- *
- * Initializes a new hash table based on the provided configuration
- * parameters. A table can be configured either with a variable or
- * fixed length key:
- *
- * Configuration Example 1: Fixed length keys
- * struct test_obj {
- *	int			key;
- *	void *			my_member;
- *	struct rhash_head	node;
- * };
- *
- * struct rhashtable_params params = {
- *	.head_offset = offsetof(struct test_obj, node),
- *	.key_offset = offsetof(struct test_obj, key),
- *	.key_len = sizeof(int),
- *	.hashfn = jhash,
- * };
- *
- * Configuration Example 2: Variable length keys
- * struct test_obj {
- *	[...]
- *	struct rhash_head	node;
- * };
- *
- * u32 my_hash_fn(const void *data, u32 len, u32 seed)
- * {
- *	struct test_obj *obj = data;
- *
- *	return [... hash ...];
- * }
- *
- * struct rhashtable_params params = {
- *	.head_offset = offsetof(struct test_obj, node),
- *	.hashfn = jhash,
- *	.obj_hashfn = my_hash_fn,
- * };
- */
 int __rhashtable_init_noprof(struct rhashtable *ht,
-		    const struct rhashtable_params *params,
-		    struct lock_class_key *key)
+			     const struct rhashtable_params *params,
+			     struct rhashtable_lockdep_keys *keys)
 {
 	struct bucket_table *tbl;
 	size_t size;
@@ -1176,13 +1134,11 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
 		return -EINVAL;
 
 	memset(ht, 0, sizeof(*ht));
-	/* mutex_lock must use nesting level 1 */
-	mutex_init_with_key(&ht->mutex, key);
+	mutex_init_with_key(&ht->mutex, &keys->mutex_key);
 	spin_lock_init(&ht->lock);
-	/* spin_lock can use nesting level 0 */
-	lockdep_set_class(&ht->lock, key);
+	lockdep_set_class(&ht->lock, &keys->lock_key);
 #ifdef CONFIG_LOCKDEP
-	ht->lockdep_key = key;
+	ht->lockdep_key = &keys->bucket_key;
 #endif
 	memcpy(&ht->p, params, sizeof(*params));
 
@@ -1236,22 +1192,13 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
 }
 EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
 
-/**
- * rhltable_init - initialize a new hash list table
- * @hlt:	hash list table to be initialized
- * @params:	configuration parameters
- *
- * Initializes a new hash list table.
- *
- * See documentation for rhashtable_init.
- */
 int __rhltable_init_noprof(struct rhltable *hlt,
 			   const struct rhashtable_params *params,
-			   struct lock_class_key *key)
+			   struct rhashtable_lockdep_keys *keys)
 {
 	int err;
 
-	err = __rhashtable_init_noprof(&hlt->ht, params, key);
+	err = __rhashtable_init_noprof(&hlt->ht, params, keys);
 	hlt->ht.rhlist = true;
 	return err;
 }
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index 85a615e74591..b767a38a74f9 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
 
 	ht = &rhlt->ht;
 	/* Take the mutex to avoid RCU warning */
-	mutex_lock_nested(&ht->mutex, 1);
+	mutex_lock(&ht->mutex);
 	tbl = rht_dereference(ht->tbl, ht);
 	for (i = 0; i < tbl->size; i++) {
 		struct rhash_head *pos, *next;
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

* Re: [PATCH] rhashtable: Use separate lockdep keys for each lock
  2026-09-15  6:04     ` [PATCH] rhashtable: Use separate lockdep keys for each lock Herbert Xu
@ 2026-09-15 21:06       ` NeilBrown
  2026-09-16  8:00       ` [v2 PATCH] " Herbert Xu
  1 sibling, 0 replies; 8+ messages in thread
From: NeilBrown @ 2026-09-15 21:06 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Eric Dumazet, Shin'ichiro Kawasaki, syzbot, bridge, davem,
	horms, idosch, kuba, linux-kernel, netdev, pabeni, razor,
	steffen.klassert, syzkaller-bugs, Thomas Graf, linux-crypto,
	quanyeyang

On Tue, 15 Sep 2026, Herbert Xu wrote:
> On Mon, Sep 14, 2026 at 09:06:49PM -0700, Eric Dumazet wrote:
> >
> > Try to revert 4333ab90aaae ("rhashtable: use private lockdep class for
> > all locks.")
> 
> Yes this is indeed buggy.  I know nothing about lockdep but Gemini
> reckons that it should use separate keys instead of different
> depths which seems fair enough:
> 
> ---8<---
> Use separate lockdep keys for the different types of locks in
> rhashtable (mutex, spin lock, and bucket locks).  They are
> separate and not normally nested with respect to each other.
> 
> Also move the rhashtable_init/rhltable_init kdoc to the header
> file as that's where the macros are defined.
> 
> Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.")
> Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
> Assisted-by: Gemini:gemini-3.6-flash
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

That's a much better approach - thanks for that.

Reviewed-by: NeilBrown <neil@brown.name>

Thanks,
NeilBrown


> 
> diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
> index 0e1b172a4f6c..afbc12ba71f5 100644
> --- a/include/linux/rhashtable-types.h
> +++ b/include/linux/rhashtable-types.h
> @@ -70,6 +70,14 @@ struct rhashtable_params {
>  	rht_obj_cmpfn_t		obj_cmpfn;
>  };
>  
> +struct rhashtable_lockdep_keys {
> +#ifdef CONFIG_LOCKDEP
> +	struct lock_class_key lock_key;
> +	struct lock_class_key mutex_key;
> +	struct lock_class_key bucket_key;
> +#endif
> +};
> +
>  /**
>   * struct rhashtable - Hash table handle
>   * @tbl: Bucket table
> @@ -141,24 +149,77 @@ struct rhashtable_iter {
>  
>  int __rhashtable_init_noprof(struct rhashtable *ht,
>  		    const struct rhashtable_params *params,
> -		    struct lock_class_key *key);
> +		    struct rhashtable_lockdep_keys *keys);
>  #define rhashtable_init_noprof(ht, params)				\
>  ({									\
> -	static struct lock_class_key __key;				\
> +	static struct rhashtable_lockdep_keys __keys;			\
>  									\
> -	__rhashtable_init_noprof(ht, params, &__key);			\
> +	__rhashtable_init_noprof(ht, params, &__keys);			\
>  })
> +
> +/**
> + * rhashtable_init - initialize a new hash table
> + * @ht:		hash table to be initialized
> + * @params:	configuration parameters
> + *
> + * Initializes a new hash table based on the provided configuration
> + * parameters. A table can be configured either with a variable or
> + * fixed length key:
> + *
> + * Configuration Example 1: Fixed length keys
> + * struct test_obj {
> + *	int			key;
> + *	void *			my_member;
> + *	struct rhash_head	node;
> + * };
> + *
> + * struct rhashtable_params params = {
> + *	.head_offset = offsetof(struct test_obj, node),
> + *	.key_offset = offsetof(struct test_obj, key),
> + *	.key_len = sizeof(int),
> + *	.hashfn = jhash,
> + * };
> + *
> + * Configuration Example 2: Variable length keys
> + * struct test_obj {
> + *	[...]
> + *	struct rhash_head	node;
> + * };
> + *
> + * u32 my_hash_fn(const void *data, u32 len, u32 seed)
> + * {
> + *	struct test_obj *obj = data;
> + *
> + *	return [... hash ...];
> + * }
> + *
> + * struct rhashtable_params params = {
> + *	.head_offset = offsetof(struct test_obj, node),
> + *	.hashfn = jhash,
> + *	.obj_hashfn = my_hash_fn,
> + * };
> + */
>  #define rhashtable_init(...)	alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
>  
>  int __rhltable_init_noprof(struct rhltable *hlt,
>  		  const struct rhashtable_params *params,
> -		  struct lock_class_key *key);
> +		  struct rhashtable_lockdep_keys *keys);
>  #define rhltable_init_noprof(hlt, params)				\
>  ({									\
> -	static struct lock_class_key __key;				\
> +	static struct rhashtable_lockdep_keys __keys;			\
>  									\
> -	__rhltable_init_noprof(hlt, params, &__key);			\
> +	__rhltable_init_noprof(hlt, params, &__keys);			\
>  })
> +
> +/**
> + * rhltable_init - initialize a new hash list table
> + * @hlt:	hash list table to be initialized
> + * @params:	configuration parameters
> + *
> + * Initializes a new hash list table.
> + *
> + * See documentation for rhashtable_init.
> + */
>  #define rhltable_init(...)	alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
>  
>  #endif /* _LINUX_RHASHTABLE_TYPES_H */
> diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
> index 6c5e6d9accba..ec853c1b9af3 100644
> --- a/include/linux/rhashtable.h
> +++ b/include/linux/rhashtable.h
> @@ -328,8 +328,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
>  
>  	local_irq_save(flags);
>  	bit_spin_lock(0, (unsigned long *)bucket);
> -	/* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */
> -	lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_);
> +	lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_);
>  	return flags;
>  }
>  
> diff --git a/lib/rhashtable.c b/lib/rhashtable.c
> index 5da0e53a8d42..918f15a2ac69 100644
> --- a/lib/rhashtable.c
> +++ b/lib/rhashtable.c
> @@ -432,7 +432,7 @@ static void rht_deferred_worker(struct work_struct *work)
>  	int err = 0;
>  
>  	ht = container_of(work, struct rhashtable, run_work);
> -	mutex_lock_nested(&ht->mutex, 1);
> +	mutex_lock(&ht->mutex);
>  
>  	tbl = rht_dereference(ht->tbl, ht);
>  	tbl = rhashtable_last_table(ht, tbl);
> @@ -1122,51 +1122,9 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
>  	return jhash2(key, length, seed);
>  }
>  
> -/**
> - * rhashtable_init - initialize a new hash table
> - * @ht:		hash table to be initialized
> - * @params:	configuration parameters
> - *
> - * Initializes a new hash table based on the provided configuration
> - * parameters. A table can be configured either with a variable or
> - * fixed length key:
> - *
> - * Configuration Example 1: Fixed length keys
> - * struct test_obj {
> - *	int			key;
> - *	void *			my_member;
> - *	struct rhash_head	node;
> - * };
> - *
> - * struct rhashtable_params params = {
> - *	.head_offset = offsetof(struct test_obj, node),
> - *	.key_offset = offsetof(struct test_obj, key),
> - *	.key_len = sizeof(int),
> - *	.hashfn = jhash,
> - * };
> - *
> - * Configuration Example 2: Variable length keys
> - * struct test_obj {
> - *	[...]
> - *	struct rhash_head	node;
> - * };
> - *
> - * u32 my_hash_fn(const void *data, u32 len, u32 seed)
> - * {
> - *	struct test_obj *obj = data;
> - *
> - *	return [... hash ...];
> - * }
> - *
> - * struct rhashtable_params params = {
> - *	.head_offset = offsetof(struct test_obj, node),
> - *	.hashfn = jhash,
> - *	.obj_hashfn = my_hash_fn,
> - * };
> - */
>  int __rhashtable_init_noprof(struct rhashtable *ht,
> -		    const struct rhashtable_params *params,
> -		    struct lock_class_key *key)
> +			     const struct rhashtable_params *params,
> +			     struct rhashtable_lockdep_keys *keys)
>  {
>  	struct bucket_table *tbl;
>  	size_t size;
> @@ -1176,13 +1134,11 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
>  		return -EINVAL;
>  
>  	memset(ht, 0, sizeof(*ht));
> -	/* mutex_lock must use nesting level 1 */
> -	mutex_init_with_key(&ht->mutex, key);
> +	mutex_init_with_key(&ht->mutex, &keys->mutex_key);
>  	spin_lock_init(&ht->lock);
> -	/* spin_lock can use nesting level 0 */
> -	lockdep_set_class(&ht->lock, key);
> +	lockdep_set_class(&ht->lock, &keys->lock_key);
>  #ifdef CONFIG_LOCKDEP
> -	ht->lockdep_key = key;
> +	ht->lockdep_key = &keys->bucket_key;
>  #endif
>  	memcpy(&ht->p, params, sizeof(*params));
>  
> @@ -1236,22 +1192,13 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
>  }
>  EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
>  
> -/**
> - * rhltable_init - initialize a new hash list table
> - * @hlt:	hash list table to be initialized
> - * @params:	configuration parameters
> - *
> - * Initializes a new hash list table.
> - *
> - * See documentation for rhashtable_init.
> - */
>  int __rhltable_init_noprof(struct rhltable *hlt,
>  			   const struct rhashtable_params *params,
> -			   struct lock_class_key *key)
> +			   struct rhashtable_lockdep_keys *keys)
>  {
>  	int err;
>  
> -	err = __rhashtable_init_noprof(&hlt->ht, params, key);
> +	err = __rhashtable_init_noprof(&hlt->ht, params, keys);
>  	hlt->ht.rhlist = true;
>  	return err;
>  }
> diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
> index 85a615e74591..b767a38a74f9 100644
> --- a/lib/test_rhashtable.c
> +++ b/lib/test_rhashtable.c
> @@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
>  
>  	ht = &rhlt->ht;
>  	/* Take the mutex to avoid RCU warning */
> -	mutex_lock_nested(&ht->mutex, 1);
> +	mutex_lock(&ht->mutex);
>  	tbl = rht_dereference(ht->tbl, ht);
>  	for (i = 0; i < tbl->size; i++) {
>  		struct rhash_head *pos, *next;
> -- 
> Email: Herbert Xu <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
> 


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

* [v2 PATCH] rhashtable: Use separate lockdep keys for each lock
  2026-09-15  6:04     ` [PATCH] rhashtable: Use separate lockdep keys for each lock Herbert Xu
  2026-09-15 21:06       ` NeilBrown
@ 2026-09-16  8:00       ` Herbert Xu
  2026-09-16  8:46         ` [v3 " Herbert Xu
  1 sibling, 1 reply; 8+ messages in thread
From: Herbert Xu @ 2026-09-16  8:00 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Shin'ichiro Kawasaki, syzbot, davem, horms, idosch, kuba,
	linux-kernel, pabeni, razor, steffen.klassert, syzkaller-bugs,
	Thomas Graf, linux-crypto, NeilBrown, quanyeyang

v2 fixes the build failure when LOCKDEP is disabled.
 
---8<---
Use separate lockdep keys for the different types of locks in
rhashtable (mutex, spin lock, and bucket locks).  They are
separate and not normally nested with respect to each other.

Also move the rhashtable_init/rhltable_init kdoc to the header
file as that's where the macros are defined.

Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.")
Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
Assisted-by: Gemini:gemini-3.6-flash
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Reviewed-by: NeilBrown <neil@brown.name>

diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 0e1b172a4f6c..3576b8f08aff 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -70,6 +70,12 @@ struct rhashtable_params {
 	rht_obj_cmpfn_t		obj_cmpfn;
 };
 
+struct rhashtable_lockdep_keys {
+	struct lock_class_key lock_key;
+	struct lock_class_key mutex_key;
+	struct lock_class_key bucket_key;
+};
+
 /**
  * struct rhashtable - Hash table handle
  * @tbl: Bucket table
@@ -141,24 +147,77 @@ struct rhashtable_iter {
 
 int __rhashtable_init_noprof(struct rhashtable *ht,
 		    const struct rhashtable_params *params,
-		    struct lock_class_key *key);
+		    struct rhashtable_lockdep_keys *keys);
 #define rhashtable_init_noprof(ht, params)				\
 ({									\
-	static struct lock_class_key __key;				\
+	static struct rhashtable_lockdep_keys __keys;			\
 									\
-	__rhashtable_init_noprof(ht, params, &__key);			\
+	__rhashtable_init_noprof(ht, params, &__keys);			\
 })
+
+/**
+ * rhashtable_init - initialize a new hash table
+ * @ht:		hash table to be initialized
+ * @params:	configuration parameters
+ *
+ * Initializes a new hash table based on the provided configuration
+ * parameters. A table can be configured either with a variable or
+ * fixed length key:
+ *
+ * Configuration Example 1: Fixed length keys
+ * struct test_obj {
+ *	int			key;
+ *	void *			my_member;
+ *	struct rhash_head	node;
+ * };
+ *
+ * struct rhashtable_params params = {
+ *	.head_offset = offsetof(struct test_obj, node),
+ *	.key_offset = offsetof(struct test_obj, key),
+ *	.key_len = sizeof(int),
+ *	.hashfn = jhash,
+ * };
+ *
+ * Configuration Example 2: Variable length keys
+ * struct test_obj {
+ *	[...]
+ *	struct rhash_head	node;
+ * };
+ *
+ * u32 my_hash_fn(const void *data, u32 len, u32 seed)
+ * {
+ *	struct test_obj *obj = data;
+ *
+ *	return [... hash ...];
+ * }
+ *
+ * struct rhashtable_params params = {
+ *	.head_offset = offsetof(struct test_obj, node),
+ *	.hashfn = jhash,
+ *	.obj_hashfn = my_hash_fn,
+ * };
+ */
 #define rhashtable_init(...)	alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
 
 int __rhltable_init_noprof(struct rhltable *hlt,
 		  const struct rhashtable_params *params,
-		  struct lock_class_key *key);
+		  struct rhashtable_lockdep_keys *keys);
 #define rhltable_init_noprof(hlt, params)				\
 ({									\
-	static struct lock_class_key __key;				\
+	static struct rhashtable_lockdep_keys __keys;			\
 									\
-	__rhltable_init_noprof(hlt, params, &__key);			\
+	__rhltable_init_noprof(hlt, params, &__keys);			\
 })
+
+/**
+ * rhltable_init - initialize a new hash list table
+ * @hlt:	hash list table to be initialized
+ * @params:	configuration parameters
+ *
+ * Initializes a new hash list table.
+ *
+ * See documentation for rhashtable_init.
+ */
 #define rhltable_init(...)	alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
 
 #endif /* _LINUX_RHASHTABLE_TYPES_H */
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 6c5e6d9accba..ec853c1b9af3 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -328,8 +328,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
 
 	local_irq_save(flags);
 	bit_spin_lock(0, (unsigned long *)bucket);
-	/* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */
-	lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_);
+	lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_);
 	return flags;
 }
 
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 5da0e53a8d42..918f15a2ac69 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -432,7 +432,7 @@ static void rht_deferred_worker(struct work_struct *work)
 	int err = 0;
 
 	ht = container_of(work, struct rhashtable, run_work);
-	mutex_lock_nested(&ht->mutex, 1);
+	mutex_lock(&ht->mutex);
 
 	tbl = rht_dereference(ht->tbl, ht);
 	tbl = rhashtable_last_table(ht, tbl);
@@ -1122,51 +1122,9 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
 	return jhash2(key, length, seed);
 }
 
-/**
- * rhashtable_init - initialize a new hash table
- * @ht:		hash table to be initialized
- * @params:	configuration parameters
- *
- * Initializes a new hash table based on the provided configuration
- * parameters. A table can be configured either with a variable or
- * fixed length key:
- *
- * Configuration Example 1: Fixed length keys
- * struct test_obj {
- *	int			key;
- *	void *			my_member;
- *	struct rhash_head	node;
- * };
- *
- * struct rhashtable_params params = {
- *	.head_offset = offsetof(struct test_obj, node),
- *	.key_offset = offsetof(struct test_obj, key),
- *	.key_len = sizeof(int),
- *	.hashfn = jhash,
- * };
- *
- * Configuration Example 2: Variable length keys
- * struct test_obj {
- *	[...]
- *	struct rhash_head	node;
- * };
- *
- * u32 my_hash_fn(const void *data, u32 len, u32 seed)
- * {
- *	struct test_obj *obj = data;
- *
- *	return [... hash ...];
- * }
- *
- * struct rhashtable_params params = {
- *	.head_offset = offsetof(struct test_obj, node),
- *	.hashfn = jhash,
- *	.obj_hashfn = my_hash_fn,
- * };
- */
 int __rhashtable_init_noprof(struct rhashtable *ht,
-		    const struct rhashtable_params *params,
-		    struct lock_class_key *key)
+			     const struct rhashtable_params *params,
+			     struct rhashtable_lockdep_keys *keys)
 {
 	struct bucket_table *tbl;
 	size_t size;
@@ -1176,13 +1134,11 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
 		return -EINVAL;
 
 	memset(ht, 0, sizeof(*ht));
-	/* mutex_lock must use nesting level 1 */
-	mutex_init_with_key(&ht->mutex, key);
+	mutex_init_with_key(&ht->mutex, &keys->mutex_key);
 	spin_lock_init(&ht->lock);
-	/* spin_lock can use nesting level 0 */
-	lockdep_set_class(&ht->lock, key);
+	lockdep_set_class(&ht->lock, &keys->lock_key);
 #ifdef CONFIG_LOCKDEP
-	ht->lockdep_key = key;
+	ht->lockdep_key = &keys->bucket_key;
 #endif
 	memcpy(&ht->p, params, sizeof(*params));
 
@@ -1236,22 +1192,13 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
 }
 EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
 
-/**
- * rhltable_init - initialize a new hash list table
- * @hlt:	hash list table to be initialized
- * @params:	configuration parameters
- *
- * Initializes a new hash list table.
- *
- * See documentation for rhashtable_init.
- */
 int __rhltable_init_noprof(struct rhltable *hlt,
 			   const struct rhashtable_params *params,
-			   struct lock_class_key *key)
+			   struct rhashtable_lockdep_keys *keys)
 {
 	int err;
 
-	err = __rhashtable_init_noprof(&hlt->ht, params, key);
+	err = __rhashtable_init_noprof(&hlt->ht, params, keys);
 	hlt->ht.rhlist = true;
 	return err;
 }
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index 85a615e74591..b767a38a74f9 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
 
 	ht = &rhlt->ht;
 	/* Take the mutex to avoid RCU warning */
-	mutex_lock_nested(&ht->mutex, 1);
+	mutex_lock(&ht->mutex);
 	tbl = rht_dereference(ht->tbl, ht);
 	for (i = 0; i < tbl->size; i++) {
 		struct rhash_head *pos, *next;
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

* [v3 PATCH] rhashtable: Use separate lockdep keys for each lock
  2026-09-16  8:00       ` [v2 PATCH] " Herbert Xu
@ 2026-09-16  8:46         ` Herbert Xu
  2026-09-18  7:59           ` Shin'ichiro Kawasaki
  0 siblings, 1 reply; 8+ messages in thread
From: Herbert Xu @ 2026-09-16  8:46 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Shin'ichiro Kawasaki, syzbot, davem, horms, idosch, kuba,
	linux-kernel, pabeni, razor, steffen.klassert, syzkaller-bugs,
	Thomas Graf, linux-crypto, NeilBrown, quanyeyang

v3 removes an obsolete comment regarding the use of nesting level 2 or more.

---8<---
Use separate lockdep keys for the different types of locks in
rhashtable (mutex, spin lock, and bucket locks).  They are
separate and not normally nested with respect to each other.

Also move the rhashtable_init/rhltable_init kdoc to the header
file as that's where the macros are defined.

Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.")
Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
Assisted-by: Gemini:gemini-3.6-flash
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Reviewed-by: NeilBrown <neil@brown.name>

diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 0e1b172a4f6c..3576b8f08aff 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -70,6 +70,12 @@ struct rhashtable_params {
 	rht_obj_cmpfn_t		obj_cmpfn;
 };
 
+struct rhashtable_lockdep_keys {
+	struct lock_class_key lock_key;
+	struct lock_class_key mutex_key;
+	struct lock_class_key bucket_key;
+};
+
 /**
  * struct rhashtable - Hash table handle
  * @tbl: Bucket table
@@ -141,24 +147,77 @@ struct rhashtable_iter {
 
 int __rhashtable_init_noprof(struct rhashtable *ht,
 		    const struct rhashtable_params *params,
-		    struct lock_class_key *key);
+		    struct rhashtable_lockdep_keys *keys);
 #define rhashtable_init_noprof(ht, params)				\
 ({									\
-	static struct lock_class_key __key;				\
+	static struct rhashtable_lockdep_keys __keys;			\
 									\
-	__rhashtable_init_noprof(ht, params, &__key);			\
+	__rhashtable_init_noprof(ht, params, &__keys);			\
 })
+
+/**
+ * rhashtable_init - initialize a new hash table
+ * @ht:		hash table to be initialized
+ * @params:	configuration parameters
+ *
+ * Initializes a new hash table based on the provided configuration
+ * parameters. A table can be configured either with a variable or
+ * fixed length key:
+ *
+ * Configuration Example 1: Fixed length keys
+ * struct test_obj {
+ *	int			key;
+ *	void *			my_member;
+ *	struct rhash_head	node;
+ * };
+ *
+ * struct rhashtable_params params = {
+ *	.head_offset = offsetof(struct test_obj, node),
+ *	.key_offset = offsetof(struct test_obj, key),
+ *	.key_len = sizeof(int),
+ *	.hashfn = jhash,
+ * };
+ *
+ * Configuration Example 2: Variable length keys
+ * struct test_obj {
+ *	[...]
+ *	struct rhash_head	node;
+ * };
+ *
+ * u32 my_hash_fn(const void *data, u32 len, u32 seed)
+ * {
+ *	struct test_obj *obj = data;
+ *
+ *	return [... hash ...];
+ * }
+ *
+ * struct rhashtable_params params = {
+ *	.head_offset = offsetof(struct test_obj, node),
+ *	.hashfn = jhash,
+ *	.obj_hashfn = my_hash_fn,
+ * };
+ */
 #define rhashtable_init(...)	alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
 
 int __rhltable_init_noprof(struct rhltable *hlt,
 		  const struct rhashtable_params *params,
-		  struct lock_class_key *key);
+		  struct rhashtable_lockdep_keys *keys);
 #define rhltable_init_noprof(hlt, params)				\
 ({									\
-	static struct lock_class_key __key;				\
+	static struct rhashtable_lockdep_keys __keys;			\
 									\
-	__rhltable_init_noprof(hlt, params, &__key);			\
+	__rhltable_init_noprof(hlt, params, &__keys);			\
 })
+
+/**
+ * rhltable_init - initialize a new hash list table
+ * @hlt:	hash list table to be initialized
+ * @params:	configuration parameters
+ *
+ * Initializes a new hash list table.
+ *
+ * See documentation for rhashtable_init.
+ */
 #define rhltable_init(...)	alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
 
 #endif /* _LINUX_RHASHTABLE_TYPES_H */
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 6c5e6d9accba..ec853c1b9af3 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -328,8 +328,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
 
 	local_irq_save(flags);
 	bit_spin_lock(0, (unsigned long *)bucket);
-	/* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */
-	lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_);
+	lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_);
 	return flags;
 }
 
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 5da0e53a8d42..a3a4a1f7751e 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -207,7 +207,6 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
 		return NULL;
 
 #ifdef CONFIG_LOCKDEP
-	/* bitlocks must use nesting level 2 or more */
 	lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", ht->lockdep_key, 0);
 #endif
 
@@ -432,7 +431,7 @@ static void rht_deferred_worker(struct work_struct *work)
 	int err = 0;
 
 	ht = container_of(work, struct rhashtable, run_work);
-	mutex_lock_nested(&ht->mutex, 1);
+	mutex_lock(&ht->mutex);
 
 	tbl = rht_dereference(ht->tbl, ht);
 	tbl = rhashtable_last_table(ht, tbl);
@@ -1122,51 +1121,9 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
 	return jhash2(key, length, seed);
 }
 
-/**
- * rhashtable_init - initialize a new hash table
- * @ht:		hash table to be initialized
- * @params:	configuration parameters
- *
- * Initializes a new hash table based on the provided configuration
- * parameters. A table can be configured either with a variable or
- * fixed length key:
- *
- * Configuration Example 1: Fixed length keys
- * struct test_obj {
- *	int			key;
- *	void *			my_member;
- *	struct rhash_head	node;
- * };
- *
- * struct rhashtable_params params = {
- *	.head_offset = offsetof(struct test_obj, node),
- *	.key_offset = offsetof(struct test_obj, key),
- *	.key_len = sizeof(int),
- *	.hashfn = jhash,
- * };
- *
- * Configuration Example 2: Variable length keys
- * struct test_obj {
- *	[...]
- *	struct rhash_head	node;
- * };
- *
- * u32 my_hash_fn(const void *data, u32 len, u32 seed)
- * {
- *	struct test_obj *obj = data;
- *
- *	return [... hash ...];
- * }
- *
- * struct rhashtable_params params = {
- *	.head_offset = offsetof(struct test_obj, node),
- *	.hashfn = jhash,
- *	.obj_hashfn = my_hash_fn,
- * };
- */
 int __rhashtable_init_noprof(struct rhashtable *ht,
-		    const struct rhashtable_params *params,
-		    struct lock_class_key *key)
+			     const struct rhashtable_params *params,
+			     struct rhashtable_lockdep_keys *keys)
 {
 	struct bucket_table *tbl;
 	size_t size;
@@ -1176,13 +1133,11 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
 		return -EINVAL;
 
 	memset(ht, 0, sizeof(*ht));
-	/* mutex_lock must use nesting level 1 */
-	mutex_init_with_key(&ht->mutex, key);
+	mutex_init_with_key(&ht->mutex, &keys->mutex_key);
 	spin_lock_init(&ht->lock);
-	/* spin_lock can use nesting level 0 */
-	lockdep_set_class(&ht->lock, key);
+	lockdep_set_class(&ht->lock, &keys->lock_key);
 #ifdef CONFIG_LOCKDEP
-	ht->lockdep_key = key;
+	ht->lockdep_key = &keys->bucket_key;
 #endif
 	memcpy(&ht->p, params, sizeof(*params));
 
@@ -1236,22 +1191,13 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
 }
 EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
 
-/**
- * rhltable_init - initialize a new hash list table
- * @hlt:	hash list table to be initialized
- * @params:	configuration parameters
- *
- * Initializes a new hash list table.
- *
- * See documentation for rhashtable_init.
- */
 int __rhltable_init_noprof(struct rhltable *hlt,
 			   const struct rhashtable_params *params,
-			   struct lock_class_key *key)
+			   struct rhashtable_lockdep_keys *keys)
 {
 	int err;
 
-	err = __rhashtable_init_noprof(&hlt->ht, params, key);
+	err = __rhashtable_init_noprof(&hlt->ht, params, keys);
 	hlt->ht.rhlist = true;
 	return err;
 }
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index 85a615e74591..b767a38a74f9 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
 
 	ht = &rhlt->ht;
 	/* Take the mutex to avoid RCU warning */
-	mutex_lock_nested(&ht->mutex, 1);
+	mutex_lock(&ht->mutex);
 	tbl = rht_dereference(ht->tbl, ht);
 	for (i = 0; i < tbl->size; i++) {
 		struct rhash_head *pos, *next;
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

* Re: [v3 PATCH] rhashtable: Use separate lockdep keys for each lock
  2026-09-16  8:46         ` [v3 " Herbert Xu
@ 2026-09-18  7:59           ` Shin'ichiro Kawasaki
  0 siblings, 0 replies; 8+ messages in thread
From: Shin'ichiro Kawasaki @ 2026-09-18  7:59 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Eric Dumazet, syzbot, davem, horms, idosch, kuba, linux-kernel,
	pabeni, razor, steffen.klassert, syzkaller-bugs, Thomas Graf,
	linux-crypto, NeilBrown, quanyeyang

[-- Attachment #1: Type: text/plain, Size: 13987 bytes --]

On Sep 16, 2026 / 18:46, Herbert Xu wrote:
> v3 removes an obsolete comment regarding the use of nesting level 2 or more.
> 
> ---8<---
> Use separate lockdep keys for the different types of locks in
> rhashtable (mutex, spin lock, and bucket locks).  They are
> separate and not normally nested with respect to each other.
> 
> Also move the rhashtable_init/rhltable_init kdoc to the header
> file as that's where the macros are defined.
> 
> Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.")
> Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
> Assisted-by: Gemini:gemini-3.6-flash
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> Reviewed-by: NeilBrown <neil@brown.name>

Thank you for the fix action. I evaluated the patch. It takes very long time to
reproduce the WARN with my test set, so I asked my AI to create a reproducer.
The attached source file is a simple kernel module that recreates the WARN at
module load. Using this module, I tried three kernels:

 v7.3-rc3 kernel                                    : no WARN
 v7.3-rc3 kernel + 4333ab90aaae                     : recreated the WARN [2]
 v7.3-rc3 kernel + 4333ab90aaae + this v3 fix patch : no WARN

The result looks good, hence,

Tested-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>


[2] WARN observed with the reproducer

Sep 18 15:39:28 redsun41 kernel: ------------[ cut here ]------------
Sep 18 15:39:28 redsun41 kernel: Looking for class "&ht->mutex" with key __key.2 [nf_tables], but found a different class "key" with the same key
Sep 18 15:39:28 redsun41 kernel: WARNING: kernel/locking/lockdep.c:955 at look_up_lock_class+0xa8/0x170, CPU#2: kworker/2:1/78
Sep 18 15:39:28 redsun41 kernel: Modules linked in: xt_conntrack nf_conntrack_netbios_ns nf_conntrack_broadcast bridge nft_fib_inet stp nft_fib_ipv4 llc nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat target_core_user ip6table_nat ip6table_mangle target_core_mod ip6table_raw ip6table_security iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw iptable_security qrtr rfkill nf_tables ip6table_filter ip6_tables iptable_filter ip_tables intel_rapl_msr intel_rapl_common sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass rapl intel_cstate iTCO_wdt intel_pmc_bxt sunrpc intel_uncore pcspkr i2c_i801 i2c_smbus igb mei_me lpc_ich mei ses enclosure ioatdma dca binfmt_misc wmi joydev acpi_pad acpi_power_meter btrfs raid6_pq xor dm_multipath zram lz4hc_compress zstd_compress ast drm_client_lib i2c_algo_bit drm_shmem_helper drm_kms_helper drm mpi3mr mpt3sas raid_class scsi_transport_sas fuse scsi_dh_rdac scsi_dh_emc scsi_dh_alua i2c_dev
Sep 18 15:39:28 redsun41 kernel: CPU: 2 UID: 0 PID: 78 Comm: kworker/2:1 Not tainted 7.3.0-rc3-kts+ #85 PREEMPT(lazy) 
Sep 18 15:39:28 redsun41 kernel: Hardware name: Supermicro Super Server/X10SRL-F, BIOS 2.0 12/17/2015
Sep 18 15:39:28 redsun41 kernel: Workqueue: events drm_fb_helper_damage_work [drm_kms_helper]
Sep 18 15:39:28 redsun41 kernel: RIP: 0010:look_up_lock_class+0xa8/0x170
Sep 18 15:39:28 redsun41 kernel: Code: 39 6b 40 75 ed 48 8b 8b b8 00 00 00 49 8b 74 24 18 48 39 f1 74 34 49 8b 14 24 48 81 fa 30 a1 92 ae 74 27 48 8d 3d d8 c5 4e 02 <67> 48 0f b9 3a 48 89 d8 48 8b 6c 24 10 4c 8b 64 24 18 48 8b 5c 24
Sep 18 15:39:28 redsun41 kernel: RSP: 0000:ffff88b77df08148 EFLAGS: 00010002
Sep 18 15:39:28 redsun41 kernel: RAX: 0000000000000001 RBX: ffffffffb2988310 RCX: ffffffffaba2e200
Sep 18 15:39:28 redsun41 kernel: RDX: ffffffffc21822a0 RSI: ffffffffaba2e180 RDI: ffffffffad913390
Sep 18 15:39:28 redsun41 kernel: RBP: ffffffffc21822a0 R08: 0000000000000001 R09: ffff8881c25a3818
Sep 18 15:39:28 redsun41 kernel: R10: 0000000000000004 R11: ffff88b77df08420 R12: ffff8881c25a11f8
Sep 18 15:39:28 redsun41 kernel: R13: 0000000000000003 R14: 0000000000000246 R15: 00000000ffffffff
Sep 18 15:39:28 redsun41 kernel: FS:  0000000000000000(0000) GS:ffff88b7cf69c000(0000) knlGS:0000000000000000
Sep 18 15:39:28 redsun41 kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Sep 18 15:39:28 redsun41 kernel: CR2: 0000000001791b40 CR3: 000000015e8e2005 CR4: 00000000001726f0
Sep 18 15:39:28 redsun41 kernel: Call Trace:
Sep 18 15:39:28 redsun41 kernel:  <IRQ>
Sep 18 15:39:28 redsun41 kernel:  ? ip_local_deliver+0x184/0x4a0
Sep 18 15:39:28 redsun41 kernel:  match_held_lock+0xdb/0x130
Sep 18 15:39:28 redsun41 kernel:  lock_is_held_type+0xb0/0x180
Sep 18 15:39:28 redsun41 kernel:  nft_rhash_lookup+0x541/0x7e0 [nf_tables]
Sep 18 15:39:28 redsun41 kernel:  ? asm_common_interrupt+0x26/0x40
Sep 18 15:39:28 redsun41 kernel:  ? lock_release.part.0+0x39/0x50
Sep 18 15:39:28 redsun41 kernel:  ? lock_vma_under_rcu+0x15e/0x3e0
Sep 18 15:39:28 redsun41 kernel:  ? do_user_addr_fault+0x3a6/0xf30
Sep 18 15:39:28 redsun41 kernel:  ? exc_page_fault+0x98/0x140
Sep 18 15:39:28 redsun41 kernel:  ? asm_exc_page_fault+0x26/0x30
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_nft_rhash_lookup+0x10/0x10 [nf_tables]
Sep 18 15:39:28 redsun41 kernel:  nft_set_do_lookup+0x1ac/0x2a0 [nf_tables]
Sep 18 15:39:28 redsun41 kernel:  ? rcu_read_lock_sched_held+0x40/0x70
Sep 18 15:39:28 redsun41 kernel:  nft_lookup_eval+0xcc/0x590 [nf_tables]
Sep 18 15:39:28 redsun41 kernel:  ? lock_is_held_type+0xb0/0x180
Sep 18 15:39:28 redsun41 kernel:  nft_do_chain+0x2a9/0x1680 [nf_tables]
Sep 18 15:39:28 redsun41 kernel:  ? update_load_avg+0x120/0x2c70
Sep 18 15:39:28 redsun41 kernel:  ? __lock_acquire+0x691/0xd00
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_nft_do_chain+0x10/0x10 [nf_tables]
Sep 18 15:39:28 redsun41 kernel:  ? __local_bh_enable_ip+0xb4/0x150
Sep 18 15:39:28 redsun41 kernel:  ? ipt_do_table+0xa10/0x11e0 [ip_tables]
Sep 18 15:39:28 redsun41 kernel:  ? ipt_do_table+0xa15/0x11e0 [ip_tables]
Sep 18 15:39:28 redsun41 kernel:  nft_do_chain_inet+0xdc/0x4a0 [nf_tables]
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_nft_do_chain_inet+0x10/0x10 [nf_tables]
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_ipt_do_table+0x10/0x10 [ip_tables]
Sep 18 15:39:28 redsun41 kernel:  nf_hook_slow+0xbe/0x210
Sep 18 15:39:28 redsun41 kernel:  ? lock_is_held_type+0xb0/0x180
Sep 18 15:39:28 redsun41 kernel:  ip_local_deliver+0x2d0/0x4a0
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_ip_local_deliver+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? tcp_v4_early_demux.isra.0+0x5c4/0xb20
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_ip_local_deliver_finish+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? ip_rcv_finish_core+0x75b/0x1470
Sep 18 15:39:28 redsun41 kernel:  ? lock_is_held_type+0xb0/0x180
Sep 18 15:39:28 redsun41 kernel:  ip_list_rcv_finish+0x815/0xbd0
Sep 18 15:39:28 redsun41 kernel:  ? ip_sublist_rcv+0x106/0x2f0
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_ip_list_rcv_finish+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? __lock_release.isra.0+0x69/0x1a0
Sep 18 15:39:28 redsun41 kernel:  ip_sublist_rcv+0x8b/0x2f0
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_ip_sublist_rcv+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? __kasan_mempool_unpoison_object+0x128/0x1c0
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_ip_rcv_finish+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? ip_rcv_core+0x619/0xd00
Sep 18 15:39:28 redsun41 kernel:  ? __kasan_slab_alloc+0x6a/0x90
Sep 18 15:39:28 redsun41 kernel:  ip_list_rcv+0x2dd/0x440
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_ip_list_rcv+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? lock_is_held_type+0xb0/0x180
Sep 18 15:39:28 redsun41 kernel:  ? __lock_acquire+0x691/0xd00
Sep 18 15:39:28 redsun41 kernel:  __netif_receive_skb_list_core+0x6bf/0xa10
Sep 18 15:39:28 redsun41 kernel:  ? __pfx___netif_receive_skb_list_core+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? lock_acquire.part.0+0xc8/0x240
Sep 18 15:39:28 redsun41 kernel:  ? netif_receive_skb_list_internal+0x382/0xc90
Sep 18 15:39:28 redsun41 kernel:  ? lock_acquire+0x11a/0x140
Sep 18 15:39:28 redsun41 kernel:  netif_receive_skb_list_internal+0x603/0xc90
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_netif_receive_skb_list_internal+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? igb_clean_tx_irq+0x10f1/0x17f0 [igb]
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_igb_clean_rx_irq+0x10/0x10 [igb]
Sep 18 15:39:28 redsun41 kernel:  napi_complete_done+0x1a4/0x900
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_napi_complete_done+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_igb_clean_tx_irq+0x10/0x10 [igb]
Sep 18 15:39:28 redsun41 kernel:  ? __lock_acquire+0x691/0xd00
Sep 18 15:39:28 redsun41 kernel:  igb_poll+0x18f/0x1f0 [igb]
Sep 18 15:39:28 redsun41 kernel:  __napi_poll+0x351/0x520
Sep 18 15:39:28 redsun41 kernel:  net_rx_action+0x446/0xc30
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_net_rx_action+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? do_raw_spin_unlock+0x59/0x230
Sep 18 15:39:28 redsun41 kernel:  ? lock_release.part.0+0x1c/0x50
Sep 18 15:39:28 redsun41 kernel:  ? sched_clock_cpu+0x69/0x630
Sep 18 15:39:28 redsun41 kernel:  ? __lock_acquire+0x691/0xd00
Sep 18 15:39:28 redsun41 kernel:  ? mark_held_locks+0x40/0x70
Sep 18 15:39:28 redsun41 kernel:  handle_softirqs+0x1db/0x870
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_handle_softirqs+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? irqtime_account_irq+0x3e/0x2d0
Sep 18 15:39:28 redsun41 kernel:  __irq_exit_rcu+0x164/0x290
Sep 18 15:39:28 redsun41 kernel:  irq_exit_rcu+0xe/0x20
Sep 18 15:39:28 redsun41 kernel:  common_interrupt+0x85/0xa0
Sep 18 15:39:28 redsun41 kernel:  </IRQ>
Sep 18 15:39:28 redsun41 kernel:  <TASK>
Sep 18 15:39:28 redsun41 kernel:  asm_common_interrupt+0x26/0x40
Sep 18 15:39:28 redsun41 kernel: RIP: 0010:qlist_free_all+0x2e/0x130
Sep 18 15:39:28 redsun41 kernel: Code: 85 c0 0f 84 16 01 00 00 41 57 41 56 41 be 00 00 00 80 41 55 49 89 fd 41 54 49 89 f4 55 53 eb 3b 48 63 93 cc 00 00 00 48 8b 28 <48> 89 df 48 29 d0 48 89 c6 49 89 c7 e8 d1 ef ff ff 66 90 4c 89 fe
Sep 18 15:39:28 redsun41 kernel: RSP: 0000:ffff88810284f848 EFLAGS: 00000246
Sep 18 15:39:28 redsun41 kernel: RAX: ffff8882958a3200 RBX: ffff8881003aec80 RCX: 0000000000000000
Sep 18 15:39:28 redsun41 kernel: RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88810284f7e0
Sep 18 15:39:28 redsun41 kernel: RBP: ffff8882958a3f00 R08: ffff8882956f3500 R09: ffffffffa8df51ce
Sep 18 15:39:28 redsun41 kernel: R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
Sep 18 15:39:28 redsun41 kernel: R13: ffff88810284f880 R14: 0000000080000000 R15: ffff8882956f3500
Sep 18 15:39:28 redsun41 kernel:  ? qlist_free_all+0x4e/0x130
Sep 18 15:39:28 redsun41 kernel:  ? qlist_free_all+0x53/0x130
Sep 18 15:39:28 redsun41 kernel:  kasan_quarantine_reduce+0x19a/0x250
Sep 18 15:39:28 redsun41 kernel:  __kasan_slab_alloc+0x6a/0x90
Sep 18 15:39:28 redsun41 kernel:  __kmalloc_cache_noprof+0x219/0x660
Sep 18 15:39:28 redsun41 kernel:  ? drm_gem_duplicate_shadow_plane_state+0x6f/0xf0 [drm_kms_helper]
Sep 18 15:39:28 redsun41 kernel:  drm_gem_duplicate_shadow_plane_state+0x6f/0xf0 [drm_kms_helper]
Sep 18 15:39:28 redsun41 kernel:  drm_atomic_get_plane_state+0x227/0x960 [drm]
Sep 18 15:39:28 redsun41 kernel:  ? modeset_lock+0x164/0x620 [drm]
Sep 18 15:39:28 redsun41 kernel:  drm_atomic_helper_dirtyfb+0x45b/0x770 [drm_kms_helper]
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_drm_atomic_helper_dirtyfb+0x10/0x10 [drm_kms_helper]
Sep 18 15:39:28 redsun41 kernel:  ? find_held_lock+0x2b/0x80
Sep 18 15:39:28 redsun41 kernel:  ? do_raw_spin_lock+0x131/0x280
Sep 18 15:39:28 redsun41 kernel:  ? find_held_lock+0x2b/0x80
Sep 18 15:39:28 redsun41 kernel:  ? mark_held_locks+0x40/0x70
Sep 18 15:39:28 redsun41 kernel:  drm_fbdev_shmem_helper_fb_dirty+0x1a0/0x440 [drm_shmem_helper]
Sep 18 15:39:28 redsun41 kernel:  ? _raw_spin_unlock_irqrestore+0x45/0x60
Sep 18 15:39:28 redsun41 kernel:  drm_fb_helper_fb_dirty+0x3fa/0xa60 [drm_kms_helper]
Sep 18 15:39:28 redsun41 kernel:  ? process_one_work+0x8c3/0x1760
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_drm_fb_helper_fb_dirty+0x10/0x10 [drm_kms_helper]
Sep 18 15:39:28 redsun41 kernel:  ? lock_acquire+0x11a/0x140
Sep 18 15:39:28 redsun41 kernel:  process_one_work+0x947/0x1760
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_process_one_work+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? lock_acquire.part.0+0xc8/0x240
Sep 18 15:39:28 redsun41 kernel:  ? lock_is_held_type+0xb0/0x180
Sep 18 15:39:28 redsun41 kernel:  worker_thread+0x601/0xff0
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_worker_thread+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? __kthread_parkme+0xbd/0x210
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_worker_thread+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_worker_thread+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  kthread+0x361/0x460
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_kthread+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ret_from_fork+0x560/0x860
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_ret_from_fork+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ? __switch_to+0x473/0xd50
Sep 18 15:39:28 redsun41 kernel:  ? __switch_to_asm+0x39/0x70
Sep 18 15:39:28 redsun41 kernel:  ? __switch_to_asm+0x33/0x70
Sep 18 15:39:28 redsun41 kernel:  ? __pfx_kthread+0x10/0x10
Sep 18 15:39:28 redsun41 kernel:  ret_from_fork_asm+0x1a/0x30
Sep 18 15:39:28 redsun41 kernel:  </TASK>
Sep 18 15:39:28 redsun41 kernel: irq event stamp: 332632
Sep 18 15:39:28 redsun41 kernel: hardirqs last  enabled at (332632): [<ffffffffa81e3134>] __local_bh_enable_ip+0xb4/0x150
Sep 18 15:39:28 redsun41 kernel: hardirqs last disabled at (332631): [<ffffffffa81e316a>] __local_bh_enable_ip+0xea/0x150
Sep 18 15:39:28 redsun41 kernel: softirqs last  enabled at (332492): [<ffffffffa81e2802>] handle_softirqs+0x632/0x870
Sep 18 15:39:28 redsun41 kernel: softirqs last disabled at (332613): [<ffffffffa81e2bb4>] __irq_exit_rcu+0x164/0x290
Sep 18 15:39:28 redsun41 kernel: ---[ end trace 0000000000000000 ]---


[-- Attachment #2: rht_lockdep_repro.c --]
[-- Type: text/plain, Size: 2959 bytes --]

// SPDX-License-Identifier: GPL-2.0

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/ww_mutex.h>
#include <linux/spinlock.h>
#include <linux/lockdep.h>
#include <linux/rhashtable.h>
#include <linux/slab.h>

/*
 * ww_mutex machinery used to give a held lock a non-zero ->references.
 * All ww_mutexes of one ww_class share a single lockdep class, and
 * ww_mutex_lock() passes nest_lock = &ctx->dep_map, so acquiring the second
 * one sets ->references on the first one's held_lock entry.
 */
static DEFINE_WW_CLASS(repro_ww_class);
static struct ww_mutex ww_a;
static struct ww_mutex ww_b;

struct repro_obj {
	int			value;
	struct rhash_head	node;
};

static struct rhashtable ht;
static const struct rhashtable_params repro_params = {
	.key_len	= sizeof(int),
	.key_offset	= offsetof(struct repro_obj, value),
	.head_offset	= offsetof(struct repro_obj, node),
};

/*
 * Run fn() while holding two same-class ww_mutexes under one acquire context,
 * so that the first held_lock entry has ->references != 0.
 */
static int with_referenced_held_lock(void (*fn)(void))
{
	struct ww_acquire_ctx ctx;
	int ret;

	ww_mutex_init(&ww_a, &repro_ww_class);
	ww_mutex_init(&ww_b, &repro_ww_class);

	ww_acquire_init(&ctx, &repro_ww_class);

	ret = ww_mutex_lock(&ww_a, &ctx);
	if (ret) {
		pr_err("ww_mutex_lock(ww_a) failed: %d\n", ret);
		goto out_fini;
	}
	/* same class as ww_a plus a nest_lock -> bumps ->references */
	ret = ww_mutex_lock(&ww_b, &ctx);
	if (ret) {
		pr_err("ww_mutex_lock(ww_b) failed: %d\n", ret);
		ww_mutex_unlock(&ww_a);
		goto out_fini;
	}

	fn();

	ww_mutex_unlock(&ww_b);
	ww_mutex_unlock(&ww_a);
out_fini:
	ww_acquire_fini(&ctx);
	return ret;
}

static void lookup_rhashtable(void)
{
	int wanted = 42;

	pr_info("doing rhashtable_lookup_fast()\n");
	pr_info("rhashtable_lookup_fast() = %px\n",
		rhashtable_lookup_fast(&ht, &wanted, repro_params));
}

static int __init repro_rhashtable(void)
{
	struct rhashtable_iter iter;
	int ret;

	ret = rhashtable_init(&ht, &repro_params);
	if (ret) {
		pr_err("rhashtable_init failed: %d\n", ret);
		return ret;
	}

	/*
	 * rhashtable_walk_enter() takes spin_lock(&ht->lock), which is what
	 * registers subclass 0 of this instance's key under the name "key".
	 */
	rhashtable_walk_enter(&ht, &iter);
	rhashtable_walk_exit(&iter);

	ret = with_referenced_held_lock(lookup_rhashtable);

	rhashtable_destroy(&ht);
	return ret;
}

static int __init repro_init(void)
{
	if (!IS_ENABLED(CONFIG_PROVE_LOCKING)) {
		pr_err("CONFIG_PROVE_LOCKING is required\n");
		return -EOPNOTSUPP;
	}
	if (!debug_locks) {
		pr_err("lockdep is already disabled, cannot test\n");
		return -EOPNOTSUPP;
	}

	return repro_rhashtable();
}

static void __exit repro_exit(void)
{
	pr_info("rht_lockdep_repro: unloaded\n");
}

module_init(repro_init);
module_exit(repro_exit);

MODULE_DESCRIPTION("Reproducer for the rhashtable lockdep subclass collision");
MODULE_LICENSE("GPL");

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

end of thread, other threads:[~2026-09-18  7:59 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-13  1:31 [syzbot] [bridge?] WARNING: locking bug in match_held_lock syzbot
2026-09-15  3:40 ` Shin'ichiro Kawasaki
2026-09-15  4:06   ` Eric Dumazet
2026-09-15  6:04     ` [PATCH] rhashtable: Use separate lockdep keys for each lock Herbert Xu
2026-09-15 21:06       ` NeilBrown
2026-09-16  8:00       ` [v2 PATCH] " Herbert Xu
2026-09-16  8:46         ` [v3 " Herbert Xu
2026-09-18  7:59           ` Shin'ichiro Kawasaki

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®