CVE-2026-98799 in Linux
Summary
by MITRE • 10/18/2026
In the Linux kernel, the following vulnerability has been resolved:
bpf: Skip detached progs in trampoline images that are still in use
bpf_tramp_image_put() makes sure a trampoline image is not freed while a task may still be running in it, but nothing similar is done for the progs called by that image. Detach drops the last prog reference right away and the prog is freed after grace periods, on the basis that a task still in the traced function skips the fexit progs once the nop at ip_after_call is patched to a jump.
That leaves out a task sleeping in a sleepable prog that runs before the detached one, which no grace period waits for:
CPU 0 CPU 1 in image I, sleeping in prog S detach P from I's trampoline -> new image, bpf_tramp_image_put(I) bpf_prog_put(P), last ref grace periods, P freed back from S __bpf_prog_enter(P) call P->bpf_func
If S and P are fexit progs the task is already past the patched jump, and fentry only images don't have one. On x86 this is an int3 in poisoned bpf_prog_pack memory:
Oops: int3: 0000 [#1] SMP NOPTI
CPU: 18 UID: 0 PID: 94573 Comm: x169 Not tainted 6.18.44 #1 PREEMPT(lazy) RIP: 0010:0xffffffffc0601d8d Call Trace: <TASK> ? bpf_trampoline_6442515411+0x1a4/0x21b bpf_lsm_bprm_committed_creds+0x5/0x10 security_bprm_committed_creds+0x5f/0x70 begin_new_exec+0x2d6/0x410 ...
We hit this in production when progs attached through trampolines got detached while their hooks were busy, and it was independently found with a fuzzer and KASAN.
Have the JITs emit a patchable nop in front of each prog call sequence and record it in the image. When a prog is detached, patch its nop to a jump over the call sequence. Progs that stay attached keep running for the tasks that are in the image, and ip_after_call isn't needed anymore.
The task can be in any image that isn't freed yet, not only in the current one. It sleeps in image I1 that calls S, P and Q, then P is detached and the trampoline moves to image I2, then Q is detached and its call is still in I1. So the trampoline keeps a list of its images until they are freed, and detaching a prog patches its nop in all of them. Images hold a reference on the trampoline for that long.
On riscv and loongarch a jump of any range takes several instructions, and a task preempted in the middle of them could resume into half of the new sequence. The nop is a single instruction there, patched to a near branch through arch_bpf_trampoline_skip().
With the extra nops, BPF_MAX_TRAMP_LINKS progs no longer fit in a page on x86 and arm64 (and already didn't on powerpc), so lower the limit there like s390 does.
Once again VulDB remains the best source for vulnerability data.
Analysis
by VulDB Data Team • 10/19/2026
The Linux kernel has addressed a critical use-after-free vulnerability within the BPF trampoline subsystem, specifically affecting how detached programs are handled during their lifecycle management. The core issue stems from an asymmetry in reference counting and memory safety guarantees between the trampoline image itself and the individual BPF programs attached to it. While the function bpf_tramp_image_put() correctly ensures that a trampoline image is not freed while any task might still be executing within its code, no equivalent protection existed for the specific BPF progs invoked by that image. When a program is detached from a trampoline, the kernel immediately drops the last reference to that program, scheduling it for deallocation after standard grace periods have elapsed. This logic assumes that tasks currently in the traced function will skip over the detached programs once a no-operation instruction at ip_after_call is patched into a jump instruction. However, this assumption fails when a task is sleeping within a sleepable BPF prog that executes before the detached one. In such scenarios, there is no grace period waiting for the sleeping task to exit its current execution context, leading directly to a use-after-free condition where the kernel attempts to execute code from memory that has already been reclaimed and potentially repurposed.
The operational impact of this vulnerability manifests as severe system instability, including kernel panics and data corruption. In production environments, when BPF programs attached through trampolines are detached while their hooks remain active or busy, tasks can resume execution in the freed memory space. On x86 architectures, this results in an int3 exception triggered by accessing poisoned bpf_prog_pack memory, as indicated by error logs showing Oops: int3 exceptions within trampoline functions like bpf_trampoline_6442515411. This occurs because the task resumes from a sleepable prog and attempts to enter the detached program P via __bpf_prog_enter(P), but P has already been freed. The vulnerability was identified both in live production deployments and independently through fuzzing tools combined with Kernel Address Sanitizer (KASAN) testing, confirming its reproducibility across different kernel configurations including PREEMPT(lazy).
The technical root cause involves the complexity of managing multiple trampoline images that may reference the same set of programs. A task can be sleeping in one image I1 while another image I2 is created after a detachment event. If subsequent detachments occur, such as removing program Q from I1, the original call sequences within I1 must still be safely handled for any tasks lingering there. The previous implementation did not account for this multi-image scenario, leading to situations where detached programs were freed while still reachable via older trampoline images that had not yet been reclaimed. This creates a race condition where the kernel's memory management subsystem frees resources prematurely relative to the actual execution state of concurrent tasks across different trampoline contexts.
To resolve these issues, the patch introduces several architectural changes to ensure safe detachment and cleanup. The Just-In-Time compilers for various architectures are modified to emit a patchable no-operation instruction in front of each program call sequence within the trampoline image. This nop is recorded in the image structure so that when a program is detached, its corresponding nop can be patched into a jump instruction that skips over the entire call sequence. This mechanism ensures that tasks currently executing in any non-freed image will safely bypass the detached programs rather than attempting to execute them. Furthermore, trampoline images now maintain a reference count on their associated trampolines and keep a list of all active images until they are fully freed. When a program is detached, its nop is patched across all relevant images, ensuring consistency regardless of which specific image a task might be executing within at the time of detachment.
The implementation also addresses architecture-specific constraints regarding instruction patching. On architectures like RISC-V and LoongArch, jumping to any arbitrary range requires multiple instructions, creating a risk if a task is preempted in the middle of this multi-instruction sequence and resumes into half of the new sequence. To mitigate this, the nop serves as a single atomic unit that can be safely patched to a near branch using arch_bpf_trampoline_skip(), preventing partial execution hazards. Additionally, due to the increased size required for these extra no-ops, BPF_MAX_TRAMP_LINKS programs may no longer fit within a single page on x86 and ARM64 architectures, similar to existing limitations on PowerPC and s390. Consequently, the limit on the number of links per trampoline is lowered on affected platforms to maintain memory layout integrity and prevent overflow conditions.
From a security perspective, this vulnerability aligns with CWE-416: Use After Free, as it involves accessing memory after it has been made available for reuse without proper synchronization or reference counting safeguards. The attack vector allows local users potentially leading to privilege escalation if they can trigger the detachment of BPF programs while maintaining control over task scheduling and sleep states within eBPF contexts. Mitigation strategies include applying the kernel patch that implements the nop-patching mechanism and updating trampoline image management logic. System administrators should ensure their kernels are updated to versions containing this fix, particularly those running heavy BPF workloads with frequent program attachment and detachment cycles. Regular auditing of BPF programs and monitoring for int3 exceptions or KASAN reports can help detect residual instances of this flaw in older kernel builds before full patching is possible.