CVE-2026-98398: locking/lockdep: Invalidate stale class_cache entries for zapped classes
In the Linux kernel, the following vulnerability has been resolved:
locking/lockdep: Invalidate stale classcache entries for zapped classes
syzbot reported a lockdep splat hitting DEBUGLOCKSWARNON(1) in hlockclass() due to an invalid classidx:
WARNING: kernel/locking/lockdep.c:238 at lockacquire+0x382/0x2cf0 kernel/locking/lockdep.c:5203 Workqueue: wg-crypt-wg0 wgpackettxworker RIP: 0010:hlockclass kernel/locking/lockdep.c:238 [inline] RIP: 0010:checkwaitcontext kernel/locking/lockdep.c:4870 [inline] RIP: 0010:lockacquire+0x389/0x2cf0 kernel/locking/lockdep.c:5203 Call Trace: <IRQ> lockacquire+0x106/0x350 kernel/locking/lockdep.c:5886 rawspinlock+0x2e/0x40 kernel/locking/spinlock.c:173 tcptsqhandler+0x29/0x200 net/ipv4/tcpoutput.c:1291 tcptsqworkfn+0x384/0x410 net/ipv4/tcpoutput.c:1325 ...
When a lock class is zapped (e.g. during module unload or key unregistration), zapclass() clears the class's bit in lockclassesinuse and removes it from the class hash table. However, existing lockdepmap instances embedded in data structures may still retain a pointer to the zapped class in their classcache[] array.
When lockacquire() subsequently runs on such a lock, it finds lock->classcache[subclass] != NULL, skipping registerlockclass() and assigning hlock->classidx to the index of the zapped class. When checkwaitcontext() or hlockclass() inspects the heldlock, it finds !testbit(classidx, lockclassesinuse) and warns. Furthermore, if the zapped slot is subsequently re-allocated to an unrelated lock key, the stale classcache entry would erroneously match the unrelated class (ABA issue).
Add lockclasscacheisvalid() to validate that the cached class is within lockclasses bounds, still allocated in lockclassesinuse (using uninstrumented archtestbit() in alwaysinline context so it is safe in noinstr contexts like matchheldlock()), and that class->key matches the expected subkey (taking lockdepsetsubclass() overrides into account). Also use READONCE()/WRITEONCE() when accessing classcache[]. If the entry is invalid or stale, fall back to registerlockclass() / lookuplockclass().
Affected Software
Event History
Frequently Asked Questions
What sequence leads to the invalid lock class index?
A lock class must first be zapped, such as during module unload or key unregistration. A lockdep_map embedded in an existing data structure can retain a stale class_cache entry, and a later lock acquisition can use that stale class reference.
How can I tell whether a system has encountered this issue?
The reported symptom is a lockdep warning from DEBUG_LOCKS_WARN_ON(1) in hlock_class(), reached through check_wait_context() and __lock_acquire(). The example trace occurred in a workqueue context involving wg_packet_tx_worker and TCP transmit work.
What can be done before the fix is deployed?
The described trigger involves zapping lock classes during operations such as module unload or key unregistration while stale lockdep_map cache entries remain. Where operationally feasible, avoid those triggering lifecycle operations until the available stable fix is applied.