CVE-2026-89906 Overview
CVE-2026-89906 affects the Linux kernel's LoongArch Berkeley Packet Filter (BPF) Just-In-Time (JIT) compiler. The flaw resides in the tail call jump offset calculation, where a macro-based approach derived jump distances from a stale prior-pass code stride. Under additional JIT passes, this produces incorrect branch offsets and can trigger soft lockups on affected systems. A local, authenticated user with the ability to load BPF programs can exploit the miscalculation to disrupt kernel availability. The upstream fix computes the offset directly from the absolute target using ctx->offset[insn + 1] - ctx->idx and adds a ctx->image == NULL guard to inject a safe dummy offset during size estimation.
Critical Impact
Incorrect BPF JIT branch offsets on LoongArch can cause kernel soft lockups, resulting in denial of service and potential integrity impact on affected hosts.
Affected Products
- Linux kernel on LoongArch architecture with BPF JIT enabled
- Distributions shipping the vulnerable LoongArch BPF JIT tail call implementation
- Kernel versions prior to the commits referenced in the upstream fix series
Discovery Timeline
- 2026-09-16 - CVE-2026-89906 published to the National Vulnerability Database (NVD)
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-89906
Vulnerability Analysis
The LoongArch BPF JIT compiler translates BPF bytecode into native LoongArch instructions across multiple passes. Tail calls require the JIT to emit branch instructions whose displacement depends on the final placement of the target instruction.
The original implementation relied on a macro that reused the code stride from a previous JIT pass. When the compiler executed extra passes, the reused stride no longer reflected the current instruction layout. The emitted branch therefore pointed to an incorrect offset.
Executing a BPF program with a miscomputed tail call branch can redirect control flow within the JIT-generated code region. The immediate observable effect is a soft lockup, in which a CPU spins in kernel context long enough to trigger the watchdog. The vulnerability requires local access and the privilege to load or execute BPF programs.
Root Cause
The root cause is a stale-state calculation defect in the JIT. The jmp_offset macro derived the branch distance from data produced by an earlier pass rather than the current pass. When the JIT performed additional passes to converge on final code size, the delta between passes invalidated the cached stride.
Attack Vector
Exploitation is local. An attacker with permission to load BPF programs constructs a program containing tail calls whose layout forces the JIT into an extra pass. The mismatched branch offset then produces divergent control flow at runtime, culminating in a soft lockup that denies service to other kernel tasks on the affected CPU.
No verified proof-of-concept code has been published. The upstream commits describe the fix and provide sufficient detail for kernel maintainers to backport the change. Refer to Kernel Git Commit 37d545d, Kernel Git Commit 882b891, and Kernel Git Commit 96f44d4 for the corrected offset calculation.
Detection Methods for CVE-2026-89906
Indicators of Compromise
- Kernel log entries reporting soft lockup - CPU#N stuck for Xs! on LoongArch systems running BPF workloads
- Repeated crashes or hangs correlated with loading of custom BPF programs that use tail calls
- Unexpected BUG: messages originating from BPF JIT-generated code regions on LoongArch hosts
Detection Strategies
- Inventory LoongArch Linux hosts and identify kernel versions predating the fix commits 37d545d, 882b891, and 96f44d4
- Audit which local users and workloads hold CAP_BPF or CAP_SYS_ADMIN and can load BPF programs
- Correlate soft lockup events in dmesg and journal logs with BPF program load events captured via audit rules
Monitoring Recommendations
- Enable kernel audit rules for bpf() syscall invocations and forward events to a central log platform
- Alert on soft lockup and watchdog messages emitted by LoongArch kernels
- Track kernel version drift across the fleet to confirm patch adoption on LoongArch nodes
How to Mitigate CVE-2026-89906
Immediate Actions Required
- Apply the upstream kernel patches referenced in commits 37d545d, 882b891, and 96f44d4 to all LoongArch systems
- Restrict the ability to load BPF programs to trusted administrators by tightening CAP_BPF and CAP_SYS_ADMIN assignments
- Set kernel.unprivileged_bpf_disabled=1 on affected hosts where unprivileged BPF is not required
Patch Information
The fix replaces the stale macro-based offset calculation with a direct computation against the absolute target: ctx->offset[insn + 1] - ctx->idx. A ctx->image == NULL guard injects a safe dummy offset during size estimation to prevent a false 16-bit range check abort. Upstream commits are available at Kernel Git Commit 37d545d, Kernel Git Commit 882b891, and Kernel Git Commit 96f44d4. Consult your distribution vendor for backported stable releases.
Workarounds
- Disable unprivileged BPF program loading using the kernel.unprivileged_bpf_disabled sysctl
- Remove or constrain BPF-related capabilities from workloads that do not require them
- Where feasible, disable the LoongArch BPF JIT via net.core.bpf_jit_enable=0 until patches are applied
# Configuration example: reduce BPF exposure until the patch is applied
sysctl -w kernel.unprivileged_bpf_disabled=1
sysctl -w net.core.bpf_jit_enable=0
echo 'kernel.unprivileged_bpf_disabled=1' >> /etc/sysctl.d/99-bpf-hardening.conf
echo 'net.core.bpf_jit_enable=0' >> /etc/sysctl.d/99-bpf-hardening.conf
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

