CVE-2026-31526 Overview
A vulnerability has been resolved in the Linux kernel's BPF (Berkeley Packet Filter) subsystem affecting exception exit lock checking for subprogs. The process_bpf_exit_full() function incorrectly passes check_lock = !curframe to check_resource_leak(), which evaluates to false when bpf_throw() is called from a static subprog. This causes check_resource_leak() to skip validation of active_rcu_locks, active_preempt_locks, and active_irq_id on exception exits from subprogs.
At runtime, bpf_throw() unwinds the stack via ORC (Oops Rewind Capability) without releasing any user-acquired locks, which may lead to various security and stability issues including potential deadlocks, privilege escalation, or system instability.
Critical Impact
BPF exception exits may bypass lock validation, allowing user-acquired locks (RCU, preempt, IRQ) to remain held after stack unwinding, potentially causing system instability or security violations.
Affected Products
- Linux Kernel (BPF subsystem)
- Systems running affected kernel versions with BPF functionality enabled
Discovery Timeline
- 2026-04-22 - CVE CVE-2026-31526 published to NVD
- 2026-04-23 - Last updated in NVD database
Technical Details for CVE-2026-31526
Vulnerability Analysis
This vulnerability resides in the Linux kernel's BPF verifier, specifically in how exception exits are validated for proper resource cleanup. The BPF verifier is responsible for ensuring that BPF programs are safe to execute, including verification that all acquired locks are properly released before program termination.
The core issue is in process_bpf_exit_full(), which determines whether to check for resource leaks based on the current frame (curframe). When a BPF program calls bpf_throw() from within a static subprogram, the check_lock variable is set to false because the exception is occurring in a non-zero frame. This bypasses the validation that should ensure active_rcu_locks, active_preempt_locks, and active_irq_id are properly cleared.
Since exceptions bypass all intermediate frame cleanup and bpf_throw() uses ORC-based stack unwinding, any locks held at the time of the exception remain acquired. This can lead to RCU read locks being held indefinitely, preemption being disabled when it shouldn't be, or interrupt handlers being left in an inconsistent state.
Root Cause
The root cause is a logic error in the conditional check for resource leak validation. The expression check_lock = !curframe assumes that lock checking is only needed when exiting from the main frame (frame 0). However, this assumption is incorrect for exception exits, where bpf_throw() unwinds the entire stack regardless of the current frame depth. The fix sets check_lock = true for all exception exits, ensuring that resource leak validation occurs regardless of which frame the exception originates from.
Attack Vector
An attacker with the ability to load BPF programs could craft a malicious program that acquires kernel locks (such as RCU read locks or preemption locks) within a static subprogram and then deliberately triggers an exception via bpf_throw(). Since the lock checking is bypassed for subprogram exception exits, the locks would remain held after the BPF program terminates, potentially leading to system-wide effects including:
- Denial of service through resource exhaustion or deadlock conditions
- Kernel instability due to improper lock states
- Potential privilege escalation if the held locks affect security-critical kernel subsystems
The vulnerability requires local access and the ability to load BPF programs, which typically requires CAP_BPF or CAP_SYS_ADMIN capabilities.
Detection Methods for CVE-2026-31526
Indicators of Compromise
- Unexpected kernel warnings or oops messages related to RCU or preemption lock states
- System hangs or performance degradation after BPF program execution
- Kernel log entries indicating RCU stall warnings or preemption imbalance
- Abnormal BPF program behavior, particularly those using bpf_throw() in subprograms
Detection Strategies
- Monitor kernel logs for RCU stall warnings (rcu: INFO: rcu_preempt detected stalls)
- Audit loaded BPF programs for usage of bpf_throw() within static subprograms
- Implement eBPF-based monitoring to detect unusual lock acquisition patterns
- Use kernel lockdep debugging to identify lock imbalance conditions
Monitoring Recommendations
- Enable kernel lockdep (CONFIG_PROVE_LOCKING) in development and testing environments
- Configure alerting for RCU stall detector warnings in production systems
- Monitor for unusual patterns in BPF program loading, especially from unprivileged users
- Review BPF verifier rejection logs for programs attempting exception-based exits
How to Mitigate CVE-2026-31526
Immediate Actions Required
- Apply the kernel patches from the official Linux kernel git repository
- Restrict BPF program loading capabilities to trusted users only (CAP_BPF, CAP_SYS_ADMIN)
- Audit existing BPF programs for usage of bpf_throw() in subprograms
- Consider disabling unprivileged BPF if not required for your use case
Patch Information
The fix has been committed to the Linux kernel stable branches. The patch sets check_lock = true for exception exits regardless of curframe, ensuring proper resource leak validation occurs for all bpf_throw() invocations. Additionally, the error message prefix has been updated to "bpf_throw" for exception exits to distinguish them from normal BPF_EXIT operations.
Patches are available from the following kernel commits:
- Kernel Commit 5a399f3117642494e35545f6ca397d3e177c1f9b
- Kernel Commit 6c2128505f61b504c79a20b89596feba61388112
- Kernel Commit c0281da1f2aa5c2fca3a05f79b86bea96591c358
Workarounds
- Restrict BPF program loading to privileged users by setting kernel.unprivileged_bpf_disabled=1
- Implement additional controls on BPF program deployment through containerization or seccomp profiles
- Monitor and audit BPF programs for exception-based exit patterns until patches can be applied
- Consider using SELinux or AppArmor policies to restrict BPF capabilities
# Disable unprivileged BPF as a temporary mitigation
sysctl -w kernel.unprivileged_bpf_disabled=1
# Make the setting persistent across reboots
echo "kernel.unprivileged_bpf_disabled=1" >> /etc/sysctl.conf
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


