CVE-2026-89988 Overview
CVE-2026-89988 is a use-after-free vulnerability in the Linux kernel's kprobes subsystem. The function __within_kprobe_blacklist() traverses kprobe_blacklist without holding kprobe_mutex. When a module unloads, kprobe_remove_area_blacklist() removes blacklist entries and frees them immediately with kfree(). A concurrent call to within_kprobe_blacklist() can dereference freed memory. The function may also run in atomic or non-preemptible contexts where the sleeping kprobe_mutex cannot be acquired. The fix protects kprobe_blacklist with Read-Copy-Update (RCU) semantics.
Critical Impact
A local attacker with the ability to trigger module unload and concurrent kprobe operations can corrupt kernel memory, leading to privilege escalation, kernel information disclosure, or system crash.
Affected Products
- Linux kernel (upstream) - versions containing the pre-RCU kprobe_blacklist traversal logic
- Distributions shipping affected stable kernel branches
- Systems with CONFIG_KPROBES enabled and loadable module support
Discovery Timeline
- 2026-09-16 - CVE-2026-89988 published to NVD
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-89988
Vulnerability Analysis
The Linux kernel's kprobes framework maintains a kprobe_blacklist list of kernel symbols where probes are prohibited. The helper __within_kprobe_blacklist() walks this list to determine whether a candidate address falls within a blacklisted range. Before the fix, this traversal held no synchronization primitive.
Module unload paths invoke kprobe_remove_area_blacklist(), which unlinks entries and calls kfree() on them immediately. Because the reader path takes no lock and the writer performs synchronous frees, a race window exists in which the reader can follow a next pointer into memory that has already been released to the slab allocator.
The reader cannot be trivially converted to acquire kprobe_mutex because within_kprobe_blacklist() is reachable from atomic and non-preemptible contexts, where sleeping is forbidden. This constraint is what makes RCU the correct synchronization primitive for the reader side.
Root Cause
The root cause is missing synchronization between concurrent readers and writers of a shared kernel linked list, combined with immediate deallocation of removed entries. This is a classic use-after-free race condition in kernel data structure management.
Attack Vector
Exploitation requires local access with the ability to trigger module load and unload operations, or to invoke code paths that call within_kprobe_blacklist() concurrently with a module unload. The attack vector is local with low complexity. A successful race can produce kernel memory corruption suitable for privilege escalation, or a kernel oops resulting in denial of service.
No public proof-of-concept exploit is currently available. See the upstream commits (0c42561, 518d9b5, 5da247e) for the corrective patches that introduce guard(rcu)(), list_for_each_entry_rcu(), list_add_tail_rcu(), list_del_rcu(), and kfree_rcu() in the affected code paths.
Detection Methods for CVE-2026-89988
Indicators of Compromise
- Kernel oops or panic messages referencing __within_kprobe_blacklist or within_kprobe_blacklist in the call stack
- KASAN (Kernel Address Sanitizer) reports of use-after-free within the kprobes subsystem
- Unexpected slab corruption warnings coincident with module unload events
Detection Strategies
- Monitor kernel logs via dmesg and journald for stack traces implicating kprobes list traversal during or shortly after module unload
- Deploy KASAN-enabled kernels in test environments to catch the race deterministically before production rollout
- Correlate module load/unload audit events with kprobe or tracing subsystem activity to identify anomalous sequences
Monitoring Recommendations
- Enable auditd rules for init_module, finit_module, and delete_module syscalls to track module lifecycle
- Collect and centralize kernel ring buffer output for anomaly analysis
- Track processes invoking perf, bpftrace, or ftrace in proximity to module unload activity
How to Mitigate CVE-2026-89988
Immediate Actions Required
- Apply the upstream stable kernel updates that introduce RCU protection for kprobe_blacklist on all affected hosts
- Restrict module load and unload capabilities to root and audit CAP_SYS_MODULE grants across the fleet
- Limit access to kernel tracing interfaces such as /sys/kernel/debug/tracing and perf_event_open to trusted operators
Patch Information
The fix is distributed across multiple stable branch commits: 0c42561, 518d9b5, 5da247e, 630ed87, 6e62cf9, and 8f40620. The patches convert kprobe_blacklist traversal to RCU using guard(rcu)() and list_for_each_entry_rcu(), and reclaim removed entries via kfree_rcu() after a grace period. Consult your distribution's security advisories for the specific package version containing the backport.
Workarounds
- Disable dynamic module loading where operationally feasible by setting kernel.modules_disabled=1 after boot
- Set kernel.kptr_restrict=2 and kernel.perf_event_paranoid=3 to raise the bar for local attackers probing kernel internals
- Restrict access to kprobe-consuming tools (bpftrace, perf probe, kprobe_events) to a narrow administrator group
# Configuration example
# Lock modules after boot (after all required modules are loaded)
sysctl -w kernel.modules_disabled=1
# Restrict kernel pointer exposure and perf usage
sysctl -w kernel.kptr_restrict=2
sysctl -w kernel.perf_event_paranoid=3
# Persist across reboots
cat <<EOF >> /etc/sysctl.d/99-kprobe-hardening.conf
kernel.kptr_restrict=2
kernel.perf_event_paranoid=3
EOF
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

