INFO: trying to register non-static key in try_to_wake_up (2)

Status: moderation: reported on 2026/11/05 11:22
Subsystems: fs
Labels: prio:high
[Documentation on labels]
Reported-by: syzbot+78a03018b02ced4a004c@syzkaller.appspotmail.com
First crash: 1d23h, last: 1d23h
✨ AI-generated root cause summary:

During AF_UNIX message delivery via unix_dgram_sendmsg(), sock_def_readable() wakes up socket waiters on &wq->wait, invoking the poll wait-queue callback pollwake() -> __pollwake(). In __pollwake(), the polling task pointer (pwq->polling_task) retrieved from wait->private is passed to default_wake_function() and try_to_wake_up(). During spinlock acquisition of &p->pi_lock, lockdep caught an uninitialized lockdep map (lock->key == NULL), which violates the invariant that all valid task_struct instances have their pi_lock initialized with a static class key during copy_process(). This points to a dangling wait-queue entry or use-after-free of struct poll_wqueues / task_struct, causing try_to_wake_up() to operate on a stale or corrupted task pointer.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit 6628e7d4c6b2:

Technical Mechanism and Root Cause Analysis

1. Crash Manifestation

The reported lockdep warning (INFO: trying to register non-static key) triggers in assign_lock_key() via register_lock_class() when try_to_wake_up() attempts to acquire p->pi_lock:

scoped_guard (raw_spinlock_irqsave, &p->pi_lock) { ... }

During registration of the lock class, lock->key is NULL. assign_lock_key() verifies whether the lock is per-CPU or a static object (static_obj(lock)). Because task_struct (and thus p->pi_lock) is dynamically allocated on the heap, static_obj() returns false, leading lockdep to report an uninitialized key on the lock.

2. Lifecycle and Invariant Analysis

  • task_struct->pi_lock invariant: In kernel/fork.c, every task created via copy_process() explicitly initializes p->pi_lock using rt_mutex_init_task(p) -> raw_spin_lock_init(&p->pi_lock). The init task statically initializes it in init/init_task.c via __RAW_SPIN_LOCK_UNLOCKED. Consequently, every valid, live struct task_struct in the Linux kernel has an initialized pi_lock associated with a static class key.
  • Poll waitqueue lifecycle:
    • In fs/select.c, poll/select syscalls (do_select(), do_sys_poll()) allocate struct poll_wqueues table on their stack frame and initialize it via poll_initwait(&table), which records pwq->polling_task = current.
    • When waitqueue entries are registered via __pollwait(), init_waitqueue_func_entry(&entry->wait, pollwake) configures the callback and assigns entry->wait.private = pwq.
    • When socket data arrives in unix_dgram_sendmsg() / sock_def_readable(), it wakes up waiters on &wq->wait:
      sock_def_readable()
        wake_up_interruptible_sync_poll(&wq->wait, ...)
          __wake_up_common()
            curr->func() -> pollwake()
              __pollwake()
                default_wake_function(&dummy_wait, ...)
                  try_to_wake_up(curr->private, ...)
      
    • In __pollwake(), pwq = wait->private is retrieved, and a dummy waitqueue entry is passed to default_wake_function() with dummy_wait.private = pwq->polling_task.

3. Root Cause and Failure Mechanism

Because p->pi_lock is strictly guaranteed to have an initialized static lockdep key on any valid task_struct, hitting lock->key == NULL in register_lock_class() proves that try_to_wake_up() received a pointer p pointing to:

  1. Memory that has been freed or zeroed (e.g., pwq or task_struct use-after-free), or
  2. Memory belonging to an object that was overwritten or corrupted.

Specifically, poll_table_entry wait-queue entries should be detached by poll_freewait() before table goes out of scope when select() / poll() completes. If a wait-queue entry remains registered on sk->sk_wq->wait due to a race or missing removal, a subsequent sock_def_readable() invocation traverses the dangling wait-queue entry and dereferences a stale pwq and/or pwq->polling_task, causing try_to_wake_up() to operate on an invalid task_struct pointer.

▶ ▼ ✨ AI Jobs (1)
ID Workflow Result Correct Bug Created Started Finished Revision
64c16ac2 assessment-security DenialOfService: ✅ Exploitable: ✅ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ✅ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ✅ UserNamespace: ✅ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ INFO: trying to register non-static key in try_to_wake_up (2) 2026/11/03 12:39 2026/11/03 12:40 2026/11/03 13:18 0a94d799
▶ ▼ Similar bugs (3)
Kernel Title Rank 🛈 Repro Cause bisect Fix bisect Count Last Reported Patched Status
upstream INFO: trying to register non-static key in try_to_wake_up fbdev -1 1 2414d 2410d 0/29 auto-closed as invalid on 2020/07/25 04:54
linux-4.14 INFO: trying to register non-static key in try_to_wake_up -1 2 2435d 2440d 0/1 auto-closed as invalid on 2020/07/03 19:01
linux-4.19 INFO: trying to register non-static key in try_to_wake_up -1 1 2267d 2267d 0/1 auto-closed as invalid on 2020/12/19 07:07

Sample crash report:
INFO: trying to register non-static key.
The code is fine but needs lockdep annotation, or maybe
you didn't initialize this object before use?
turning off the locking correctness validator.
CPU: 1 UID: 0 PID: 4404 Comm: dhcpcd Tainted: G             L      syzkaller #0 PREEMPT 
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/14/2026
Call trace:
 show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:499 (C)
 __dump_stack+0x30/0x40 lib/dump_stack.c:94
 dump_stack_lvl+0xd8/0x12c lib/dump_stack.c:120
 dump_stack+0x1c/0x28 lib/dump_stack.c:129
 assign_lock_key+0xcc/0xdc kernel/locking/lockdep.c:1028
 register_lock_class+0xf8/0x31c kernel/locking/lockdep.c:1343
 __lock_acquire+0x140/0x2b08 kernel/locking/lockdep.c:5162
 lock_acquire+0x13c/0x320 kernel/locking/lockdep.c:5942
 __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:155 [inline]
 _raw_spin_lock_irqsave+0x5c/0x7c kernel/locking/spinlock.c:181
 class_raw_spinlock_irqsave_constructor include/linux/spinlock.h:595 [inline]
 try_to_wake_up+0x64/0xfe0 kernel/sched/core.c:4365
 default_wake_function+0x58/0x74 kernel/sched/core.c:7674
 __pollwake fs/select.c:205 [inline]
 pollwake+0x15c/0x208 fs/select.c:215
 __wake_up_common+0x104/0x180 kernel/sched/wait.c:108
 __wake_up_common_lock+0x4c/0x78 kernel/sched/wait.c:125
 __wake_up_sync_key+0x20/0x2c kernel/sched/wait.c:188
 sock_def_readable+0x208/0x5d0 net/core/sock.c:3739
 unix_dgram_sendmsg+0xc18/0x10d4 net/unix/af_unix.c:2304
 unix_seqpacket_sendmsg+0x108/0x1d0 net/unix/af_unix.c:2549
 sock_sendmsg_nosec net/socket.c:800 [inline]
 __sock_sendmsg+0xc8/0x188 net/socket.c:818
 sock_write_iter+0x220/0x310 net/socket.c:1269
 do_iter_readv_writev+0x48c/0x6f8 fs/read_write.c:-1
 vfs_writev+0x2a8/0x630 fs/read_write.c:1058
 do_writev+0x134/0x2a8 fs/read_write.c:1104
 __do_sys_writev fs/read_write.c:1172 [inline]
 __se_sys_writev fs/read_write.c:1169 [inline]
 __arm64_sys_writev+0x88/0x9c fs/read_write.c:1169
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x60/0x1d8 arch/arm64/kernel/entry-common.c:796
 el0t_64_sync_handler+0x44/0x104 arch/arm64/kernel/entry-common.c:815
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:606

Crashes (1):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/11/03 12:39 git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci 6628e7d4c6b2 0a94d799 .config console log report info [disk image] [vmlinux] [kernel image] ci-upstream-gce-arm64 INFO: trying to register non-static key in try_to_wake_up
* Struck through repros no longer work on HEAD.