CVE-2026-89988 in Linuxinfo

Summary

by MITRE • 09/16/2026

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

kprobes: Protect kprobe_blacklist with RCU

__within_kprobe_blacklist() traverses kprobe_blacklist without holding kprobe_mutex. When a module is unloaded, kprobe_remove_area_blacklist() removes blacklist entries and immediately frees them with kfree(). A concurrent call to within_kprobe_blacklist() can therefore dereference freed memory.

Furthermore, within_kprobe_blacklist() can be called in atomic or non-preemptible contexts where the sleeping kprobe_mutex cannot be taken.

Protect kprobe_blacklist with RCU. Use guard(rcu)() and list_for_each_entry_rcu() for traversal, list_add_tail_rcu() for insertions, list_del_rcu() for deletions, and kfree_rcu() to reclaim entries safely after a grace period.

If you want to get best quality of vulnerability data, you may have to visit VulDB.

Analysis

by VulDB Data Team • 09/16/2026

The Linux kernel's dynamic tracing subsystem, specifically the kprobes framework, contained a critical concurrency vulnerability related to memory safety during module unloading operations. The core of this issue lies in how the function __within_kprobe_blacklist() interacts with the global kprobe blacklist data structure. This function is responsible for checking whether a given instruction pointer falls within addresses that are blacklisted from being probed, which is essential for preventing probes on sensitive kernel code or areas where probing could cause instability. The vulnerability arises because this traversal occurs without holding the kprobe_mutex, a synchronization primitive intended to protect modifications to the blacklist. Under normal circumstances, one might expect mutexes to prevent race conditions, but in this specific context, structural constraints prevented their use during certain execution paths.

The root cause of the flaw is that __within_kprobe_blacklist() can be invoked from atomic or non-preemptible contexts where sleeping locks like kprobe_mutex are prohibited due to potential deadlocks or scheduler violations. When a kernel module is unloaded, the function kprobe_remove_area_blacklist() removes entries from this blacklist and immediately frees them using standard memory deallocation functions such as kfree(). Because the removal happens without holding the mutex that protects concurrent access, there exists a race condition window where one CPU core may be in the process of freeing these data structures while another CPU core is simultaneously executing __within_kprobe_blacklist() to check an address. This leads to a use-after-free scenario where the traversing function dereferences memory addresses that have already been returned to the system allocator and potentially overwritten by other allocations, resulting in undefined behavior.

The operational impact of this vulnerability can range from subtle data corruption to severe system crashes or privilege escalation attempts if an attacker can influence the allocation patterns after the free operation. Dereferencing freed kernel memory typically results in a kernel panic due to invalid pointer access, causing a denial of service for the entire system. In more sophisticated attack scenarios, use-after-free vulnerabilities are frequently leveraged to achieve arbitrary code execution by manipulating the contents of the reclaimed memory before it is reallocated for malicious purposes. This specific flaw highlights the complexity of maintaining consistency in highly concurrent kernel subsystems where different access patterns require distinct synchronization mechanisms that do not rely on sleeping locks.

To resolve this issue, the vulnerability was addressed by implementing Read-Copy-Update (RCU) protection around the kprobe_blacklist data structure. RCU is a synchronization mechanism designed for read-heavy workloads and allows readers to proceed without acquiring traditional locks, while writers defer actual memory reclamation until all pre-existing readers have completed their access via grace periods. The fix involves replacing standard list traversal with list_for_each_entry_rcu(), which safely iterates over the blacklist under RCU read-side critical sections. Insertions are handled using list_add_tail_rcu() to maintain consistency, and deletions utilize list_del_rcu() to logically remove entries from the list without immediately freeing them. Crucially, memory reclamation is deferred by employing kfree_rcu(), which ensures that the blacklisted entry structures remain valid until all ongoing RCU read-side critical sections have finished executing. This approach eliminates the race condition entirely while respecting the constraints of atomic contexts where sleeping mutexes cannot be used.

From a classification perspective, this vulnerability aligns with CWE-416, Use After Free, as it involves accessing memory after it has been freed due to improper synchronization. It also relates to CWE-362, Concurrent Execution using Shared Resource with Improper Synchronization, given the race condition between module unloading and blacklist traversal. In terms of adversary tactics, this type of vulnerability is relevant to ATT&CK technique T1059, Command and Scripting Interpreter, or more broadly to privilege escalation vectors where kernel memory corruption is exploited to gain higher system privileges. The mitigation strategy demonstrates best practices for handling shared data structures in the Linux kernel by leveraging RCU semantics to ensure safe concurrent access without blocking atomic execution contexts.

Responsible

Linux

Reservation

09/11/2026

Disclosure

09/16/2026

Moderation

accepted

CPE

ready

EPSS

0.00000

KEV

no

Activities

very low

Sources

Do you know our Splunk app?

Download it now for free!