CVE-2026-98641
NoneCVSS
—
EPSS
0.2%
Published
Oct 18, 2026
CISA due date
—
Cloudanix analysis
A flaw in the Linux kernel on certain processors can let specially crafted low-level programs crash the entire system or corrupt memory.
- Exploitation
- Local Privilege
- Attacker needs
- Low Privilege
- Complexity
- Moderate
- Impact
- Full Compromise
- Component
- OS kernel
- Class
- Memory Corruption
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
The arm64 BPF exception callback prologue skips setting ctx->fp_used because build_prologue takes the exception_cb path and never calls push_callee_regs or find_used_callee_regs, so the mov x25, sp instruction is never emitted; x25 retains a stale subprogram frame pointer and stack accesses performed through helpers using that register write below the callback's live stack pointer, overwriting return addresses.
Why it matters to the business
Systems running untrusted or complex BPF programs on arm64 may experience kernel panics and abrupt crashes, causing denial of service and potential loss of availability; successful exploitation could allow kernel memory corruption.
How an attack unfolds
An attacker loads a BPF program that uses an exception boundary together with a subprogram that allocates its own stack frame, calls bpf_throw from the subprogram, and passes the address of a local variable to a helper; because the frame pointer is stale the helper writes attacker-controlled data over the kernel return address, triggering a fatal exception.
How to fix it
Apply the upstream kernel patch that forces ctx->fp_used on the exception callback path so the frame pointer is correctly initialized from the stack pointer; rebuild and deploy the fixed kernel on all arm64 systems that load BPF programs.
How to confirm the fix worked
Confirm the patched kernel source contains the ctx->fp_used assignment in the exception_cb prologue path; exercise BPF programs that combine exception callbacks with subprogram stack usage and verify no stale-frame writes occur.
Typical attack path
- Load a malicious BPF program containing an exception callback and a subprogram that uses stack space
- Trigger bpf_throw from within the subprogram
- Pass the address of a subprogram local to a helper function
- Helper performs write using the stale frame pointer below the callback stack
- Overwrite kernel return address leading to panic or code execution
How to detect it
Search kernel logs and crash dumps for oops traces containing bpf_test_run, bpf_prog_test_run_skb, and __sys_bpf together with pc and lr values indicating writes below the stack pointer.
- bpf_test_run+0x188/0x3e0
- bpf_prog_test_run_skb+0x47c/0x998
- Kernel panic - not syncing: Oops: Fatal exception in interrupt
- pc : 0x1234
- lr : 0x1234
What your security team should do
- Immediately schedule kernel updates for all arm64 hosts that permit BPF program loading
- Temporarily disable unprivileged BPF loading via sysctl until patches are applied
- Add kernel oops monitoring for bpf_test_run and bpf_prog_test_run_skb symbols
The record
In the Linux kernel, the following vulnerability has been resolved: bpf, arm64: set up the frame pointer for the exception callback A program acting as exception boundary saves all callee-saved registers, so build_prologue() takes the exception_cb path and never calls push_callee_regs(). That is the only place find_used_callee_regs() runs, and with it the only place ctx->fp_used is set, so the callback prologue does not emit the mov x25, sp that points BPF_REG_FP at the frame the callback runs on. x25 keeps whatever it held when bpf_throw() was called. If the throw came from a subprogram that uses its own BPF stack, that is the subprogram's frame pointer, and since the subprogram never returns it never restores x25 either. Stack accesses through BPF_REG_FP are rewritten to be stack pointer relative, so those still land in the callback's own frame. Materializing the register does not: a callback that passes the address of a local variable to a helper hands over an address in the dead subprogram's frame. That address is below the callback's stack pointer by then, and the helper's own call chain covers it, so the helper can write over its own return address. 0x1234 below is the value the helper was asked to store: pc : 0x1234 lr : 0x1234 Call trace: 0x1234 (P) bpf_test_run+0x188/0x3e0 bpf_prog_test_run_skb+0x47c/0x998 __sys_bpf+0xbdc/0xdd8 Kernel panic - not syncing: Oops: Fatal exception in interrupt Set ctx->fp_used on the exception callback path so that the existing code further down sets x25 from the stack pointer. The epilogue restores it from the main program's save area along with the other callee-saved registers, as it already does. x86 sets the frame pointer for the callback from the argument it is passed, and powerpc computes it from the stack pointer.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|