CVE-2026-98530: kprobes: Fix permanent hang when flushing the kprobe optimizer

Published Oct 18, 2026
·
Updated

In the Linux kernel, the following vulnerability has been resolved:

kprobes: Fix permanent hang when flushing the kprobe optimizer

Writing 0 to /proc/sys/debug/kprobes-optimization while a kprobe is jump-optimized never returns. The writer sleeps in D state forever with kprobesysctlmutex held, so any later read or write of that sysctl hangs as well. For example, with vfsread+9 as an optimizable address in this build:

# cd /sys/kernel/tracing # echo 'p:myprobe vfsread+9' >> kprobeevents # echo 1 > events/kprobes/myprobe/enable # # wait until /sys/kernel/debug/kprobes/list shows [OPTIMIZED] # echo 0 > /proc/sys/debug/kprobes-optimization

INFO: task sh:246 blocked for more than 10 seconds. Call Trace: <TASK> schedule+0x1176/0x4f70 schedule+0xdc/0x2c0 scheduletimeout+0x17b/0x260 waitforcompletion+0x173/0x3c0 waitforkprobeoptimizerlocked+0xbc/0x130 prockprobesoptimizationhandler+0x156/0x1b0 procsyscallhandler+0x324/0x490 vfswrite+0x52d/0xfe0 ksyswrite+0xff/0x200 dosyscall64+0x106/0x630 entrySYSCALL64afterhwframe+0x77/0x7f </TASK> ... INFO: task cat:265 is blocked on a mutex likely owned by task sh:246.

waitforkprobeoptimizerlocked() reinitializes optimizercompletion, asks the optimizer thread to flush and sleeps in waitforcompletion(). The thread drains the (un)optimizing lists, but calls complete() only if completiondone() is true, i.e. if the completion is already done, which never happens while someone waits. disarmallkprobes() and kprobetraceselftestsinit() wait the same way.

Calling complete() unconditionally would not be enough: the waiter drops kprobemutex while it sleeps, and nothing else serializes the sysctl handler against the debugfs "enabled" file. A second flusher that still finds the lists non-empty, e.g. because a disabled probe is queued for unoptimizing, reinitializes the completion under the first:

sysctl write debugfs "enabled" write unoptimizeallkprobes() waitforkprobeoptimizerlocked() initcompletion(c) mutexunlock(&kprobemutex) waitforcompletion(c) disarmallkprobes() waitforkprobeoptimizerlocked() initcompletion(c) // c->wait is reset, the first // waiter is off the queue mutexunlock(&kprobemutex) waitforcompletion(c) kprobeoptimizer() complete(c) // wakes the debugfs writer only

where c is &optimizercompletion. Lining up the two writes during an optimizer pass loses the sysctl writer this way.

Replace the completion with a counter of optimizer passes, bumped at the end of each pass and signalled with wakeupvarlocked(), both under kprobemutex. A flusher samples the count and waits with waitvareventmutex(), which drops kprobemutex only while sleeping, so a new count means a whole pass ran in the meantime. Nothing is reinitialized, so several flushers can sleep in the wait at once.

Affected Software

1 affected component
Linux Linux kernel

Event History

Oct 18, 2026
CVE Published
via MITRE·03:17 PM
Data Sourced
via MITRE·03:17 PM
Description
Data Sourced
via NVD·04:17 PM
Description

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203