CVE-2025-21999 Overview
A use-after-free (UAF) vulnerability has been identified in the Linux kernel's proc filesystem implementation, specifically in the proc_get_inode() function. This vulnerability arises from a race condition between kernel module unloading (rmmod) and /proc/XXX inode instantiation. The flaw allows an attacker with local access to potentially achieve arbitrary code execution or cause system instability by exploiting the timing window where pde->proc_ops is dereferenced after the owning module has been freed.
Critical Impact
Local attackers can exploit this race condition to trigger use-after-free, potentially leading to privilege escalation, arbitrary code execution, or denial of service on affected Linux systems.
Affected Products
- Linux Kernel versions prior to patched releases
- Linux Kernel 6.14-rc1 through 6.14-rc4
- Various Linux distributions including Debian LTS
Discovery Timeline
- April 3, 2025 - CVE-2025-21999 published to NVD
- November 3, 2025 - Last updated in NVD database
Technical Details for CVE-2025-21999
Vulnerability Analysis
This vulnerability is classified as CWE-416 (Use After Free). The fundamental issue lies in the ownership semantics of pde->proc_ops structures. These operations structures belong to kernel modules, not to the /proc filesystem itself. When a /proc entry is registered, the associated proc_ops pointer references memory within the module's address space.
The race condition occurs during the narrow timing window where:
- A lookup operation obtains a reference to a proc directory entry via proc_lookup_de() and calls pde_get(de)
- Concurrently, rmmod triggers the module exit handler, which calls proc_remove() → remove_proc_subtree() → proc_entry_rundown(de)
- The module is then freed via free_module(mod)
- The lookup operation continues to execute proc_get_inode(), which attempts to dereference de->proc_ops->proc_read_iter
At step 4, the proc_ops structure has already been freed along with the module, resulting in a use-after-free condition. KASAN reports this as a page fault when attempting to access the freed memory.
Root Cause
The root cause is improper lifecycle management of the pde->proc_ops pointer. The existing protection mechanism using use_pde()/unuse_pde() pairs was not employed in this code path, allowing the dereference to occur without ensuring the module remains loaded. The fix addresses this by caching the necessary information from proc_ops in the proc directory entry (PDE) structure before calling proc_register(), eliminating the need to dereference pde->proc_ops during inode instantiation.
Attack Vector
The attack requires local access to the system with the ability to trigger /proc lookups while simultaneously unloading kernel modules. The exploitation scenario involves:
- An attacker loads a kernel module that registers a /proc entry
- The attacker initiates multiple parallel operations: directory listings or stat calls targeting the /proc entry
- Simultaneously, the attacker triggers module unloading via rmmod
- With precise timing, the race condition is triggered, causing the kernel to access freed memory
- By controlling the contents of the freed memory region (through heap manipulation techniques), an attacker could potentially redirect execution flow
The kernel oops trace shows the fault occurring at proc_get_inode+0x302/0x6e0 when dereferencing memory at address fffffbfff80a702b, confirming the use-after-free condition.
Detection Methods for CVE-2025-21999
Indicators of Compromise
- Kernel oops messages referencing proc_get_inode() in the call trace
- KASAN reports indicating use-after-free in proc filesystem operations
- Unexpected page faults with addresses in the kernel shadow memory region (addresses starting with fffffbfff)
- System instability or crashes during module loading/unloading operations
Detection Strategies
- Enable KASAN (Kernel Address Sanitizer) in development and staging environments to detect UAF conditions
- Monitor kernel logs for oops traces containing proc_get_inode, proc_lookup_de, or related proc filesystem functions
- Implement audit rules to track rmmod and module operations alongside /proc access patterns
- Deploy kernel live patching solutions to detect and prevent exploitation attempts
Monitoring Recommendations
- Configure syslog aggregation to capture and alert on kernel oops messages
- Implement SentinelOne Singularity for real-time kernel-level threat detection and behavioral analysis
- Monitor for unusual patterns of module loading/unloading combined with /proc filesystem access
- Review system audit logs for processes attempting rapid module operations
How to Mitigate CVE-2025-21999
Immediate Actions Required
- Apply the latest kernel patches from your distribution's security updates
- Restrict access to kernel module loading/unloading to trusted administrators only
- Consider disabling dynamic module loading on production systems where possible
- Update Debian LTS systems per the Debian LTS security announcements
Patch Information
The Linux kernel maintainers have released patches across multiple stable branches. The fix caches necessary inode information in the PDE structure before proc registration, avoiding the unsafe pde->proc_ops dereference. Apply the appropriate patch for your kernel version:
- Kernel patch 63b53198aff2
- Kernel patch 64dc7c68e040
- Kernel patch 654b33ada4ab
- Kernel patch 966f331403dc
- Kernel patch ede3e8ac90ae
Workarounds
- Restrict module loading capabilities by setting kernel.modules_disabled=1 via sysctl after boot (note: this prevents all module loading)
- Limit user access to systems where module unloading is required
- Apply SELinux or AppArmor policies to restrict which processes can perform module operations
- Consider using signed kernel modules and disabling unsigned module loading
# Disable dynamic module loading (apply after boot)
sysctl -w kernel.modules_disabled=1
# Restrict module loading to specific capabilities
# In /etc/sysctl.conf or /etc/sysctl.d/99-security.conf
kernel.modules_disabled=1
# Alternative: Use capabilities to restrict module operations
# Ensure only root with CAP_SYS_MODULE can load modules
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


