CVE-2026-98530
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 kprobe_sysctl_mutex held, so any later read or write of that sysctl hangs as well. For example, with vfs_read+9 as an optimizable address in this build:
wait_for_kprobe_optimizer_locked() reinitializes optimizer_completion, asks the optimizer thread to flush and sleeps in wait_for_completion().
Read full descriptionShow less
The thread drains the (un)optimizing lists, but calls complete() only if completion_done() is true, i.e. if the completion is already done, which never happens while someone waits. disarm_all_kprobes() and kprobe_trace_self_tests_init() wait the same way.
Calling complete() unconditionally would not be enough: the waiter drops kprobe_mutex 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:
where c is &optimizer_completion. 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 wake_up_var_locked(), both under kprobe_mutex. A flusher samples the count and waits with wait_var_event_mutex(), which drops kprobe_mutex 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.
Technical details traces, logs and code from the original report
# cd /sys/kernel/tracing
# echo 'p:myprobe vfs_read+9' >> kprobe_events
# 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
schedule_timeout+0x17b/0x260
wait_for_completion+0x173/0x3c0
wait_for_kprobe_optimizer_locked+0xbc/0x130
proc_kprobes_optimization_handler+0x156/0x1b0
proc_sys_call_handler+0x324/0x490
vfs_write+0x52d/0xfe0
ksys_write+0xff/0x200
do_syscall_64+0x106/0x630
entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>
...
INFO: task cat:265 is blocked on a mutex likely owned by task sh:246.
sysctl write debugfs "enabled" write
unoptimize_all_kprobes()
wait_for_kprobe_optimizer_locked()
init_completion(c)
mutex_unlock(&kprobe_mutex)
wait_for_completion(c)
disarm_all_kprobes()
wait_for_kprobe_optimizer_locked()
init_completion(c)
// c->wait is reset, the first
// waiter is off the queue
mutex_unlock(&kprobe_mutex)
wait_for_completion(c)
kprobe_optimizer()
complete(c)
// wakes the debugfs writer onlyCVSS
NVD hasn't assigned a CVSS score to this CVE (common since the April 2026 policy change).
Exploitation probability (EPSS)
- Probability of exploitation in the next 30 days
- 0.20 %
- Percentile among all scored CVEs
- 9
- Score date
- 10/20/2026
EPSS (Exploit Prediction Scoring System, FIRST) estimates how likely a vulnerability is to be exploited in the wild within 30 days. It complements CVSS (impact) and CISA KEV (confirmed exploitation).
Affected technologies (1)
⚠ AI-inferred from the description — NVD hasn't analyzed this CVE yet, these aren't verified CPEs.
References
Raw JSON (NVD)
Show
{
"id": "CVE-2026-98530",
"cveTags": [],
"metrics": {},
"affected": [
{
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"affectedData": [
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "73c12f209462d1712c5f55f3021a1b65b2e084c3",
"lessThan": "f05a01fc7d4f731b4c100d2aef1e85ad77728862",
"versionType": "git"
},
{
"status": "affected",
"version": "73c12f209462d1712c5f55f3021a1b65b2e084c3",
"lessThan": "5bfa9f1a9dcb6ecb607adbc1c0226605c972935b",
"versionType": "git"
}
],
"programFiles": [
"kernel/kprobes.c"
],
"defaultStatus": "unaffected"
},
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "7.0"
},
{
"status": "unaffected",
"version": "0",
"lessThan": "7.0",
"versionType": "semver"
},
{
"status": "unaffected",
"version": "7.2.9",
"versionType": "semver",
"lessThanOrEqual": "7.2.*"
},
{
"status": "unaffected",
"version": "7.3",
"versionType": "original_commit_for_fix",
"lessThanOrEqual": "*"
}
],
"programFiles": [
"kernel/kprobes.c"
],
"defaultStatus": "affected"
}
]
}
],
"published": "2026-10-18T16:17:04.530",
"references": [
{
"url": "https://git.kernel.org/stable/c/5bfa9f1a9dcb6ecb607adbc1c0226605c972935b",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/f05a01fc7d4f731b4c100d2aef1e85ad77728862",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}
],
"vulnStatus": "Received",
"descriptions": [
{
"lang": "en",
"value": "In the Linux kernel, the following vulnerability has been resolved:\n\nkprobes: Fix permanent hang when flushing the kprobe optimizer\n\nWriting 0 to /proc/sys/debug/kprobes-optimization while a kprobe is\njump-optimized never returns. The writer sleeps in D state forever with\nkprobe_sysctl_mutex held, so any later read or write of that sysctl\nhangs as well. For example, with vfs_read+9 as an optimizable address\nin this build:\n\n # cd /sys/kernel/tracing\n # echo 'p:myprobe vfs_read+9' >> kprobe_events\n # echo 1 > events/kprobes/myprobe/enable\n # # wait until /sys/kernel/debug/kprobes/list shows [OPTIMIZED]\n # echo 0 > /proc/sys/debug/kprobes-optimization\n\n INFO: task sh:246 blocked for more than 10 seconds.\n Call Trace:\n <TASK>\n __schedule+0x1176/0x4f70\n schedule+0xdc/0x2c0\n schedule_timeout+0x17b/0x260\n wait_for_completion+0x173/0x3c0\n wait_for_kprobe_optimizer_locked+0xbc/0x130\n proc_kprobes_optimization_handler+0x156/0x1b0\n proc_sys_call_handler+0x324/0x490\n vfs_write+0x52d/0xfe0\n ksys_write+0xff/0x200\n do_syscall_64+0x106/0x630\n entry_SYSCALL_64_after_hwframe+0x77/0x7f\n </TASK>\n ...\n INFO: task cat:265 is blocked on a mutex likely owned by task sh:246.\n\nwait_for_kprobe_optimizer_locked() reinitializes optimizer_completion,\nasks the optimizer thread to flush and sleeps in wait_for_completion().\nThe thread drains the (un)optimizing lists, but calls complete() only\nif completion_done() is true, i.e. if the completion is already done,\nwhich never happens while someone waits. disarm_all_kprobes() and\nkprobe_trace_self_tests_init() wait the same way.\n\nCalling complete() unconditionally would not be enough: the waiter\ndrops kprobe_mutex while it sleeps, and nothing else serializes the\nsysctl handler against the debugfs \"enabled\" file. A second flusher\nthat still finds the lists non-empty, e.g. because a disabled probe is\nqueued for unoptimizing, reinitializes the completion under the first:\n\n sysctl write debugfs \"enabled\" write\n unoptimize_all_kprobes()\n wait_for_kprobe_optimizer_locked()\n init_completion(c)\n mutex_unlock(&kprobe_mutex)\n wait_for_completion(c)\n disarm_all_kprobes()\n wait_for_kprobe_optimizer_locked()\n init_completion(c)\n // c->wait is reset, the first\n // waiter is off the queue\n mutex_unlock(&kprobe_mutex)\n wait_for_completion(c)\n kprobe_optimizer()\n complete(c)\n // wakes the debugfs writer only\n\nwhere c is &optimizer_completion. Lining up the two writes during an\noptimizer pass loses the sysctl writer this way.\n\nReplace the completion with a counter of optimizer passes, bumped at the\nend of each pass and signalled with wake_up_var_locked(), both under\nkprobe_mutex. A flusher samples the count and waits with\nwait_var_event_mutex(), which drops kprobe_mutex only while sleeping, so\na new count means a whole pass ran in the meantime. Nothing is\nreinitialized, so several flushers can sleep in the wait at once."
}
],
"lastModified": "2026-10-19T10:19:08.410",
"sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}