CVE-2026-64235: x86/ftrace: Relocate %rip-relative percpu refs in dynamic trampolines
In the Linux kernel, the following vulnerability has been resolved:
x86/ftrace: Relocate %rip-relative percpu refs in dynamic trampolines
With CONFIGCALLDEPTHTRACKING enabled on an x86 retbleed-affected platform (eg: Skylake), with retbleed=stuff, registering a dynamic ftrace trampoline crashes on the first call into the traced function:
BUG: unable to handle page fault for address: ffff88817ae18880 #PF: supervisor write access in kernel mode #PF: errorcode(0x0002) - not-present page PGD 4b53067 P4D 4b53067 PUD 0 Oops: Oops: 0002 [#1] SMP PTI CPU: 3 UID: 0 PID: 187 Comm: usleep Not tainted 7.0.10 #243 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.17.0-2-2 04/01/2014 Code: 24 78 00 00 00 00 48 89 ea 48 89 54 24 20 48 8b b4 24 b8 00 00 00 48 8b bc 24 b0 00 00 00 48 89 bc 24 80 00 00 00 48 83 ef 05 <65> 48 c1 3d 1f a8 b6 02 05 48 8b 15 f6 00 00 00 4c 89 3c 24 4c 89 Call Trace: <TASK> ? findheldlock ? excpagefault ? lockrelease ? x64sysclocknanosleep ? lockdephardirqsonprepare ? tracehardirqson x64sysclocknanosleep dosyscall64 ? excpagefault ? calldepthreturnthunk entrySYSCALL64afterhwframe ... Kernel panic - not syncing: Fatal exception
This small reproducer allows to easily trigger the crash:
# echo 'p x64sysclocknanosleep' > /sys/kernel/tracing/kprobeevents # echo 1 > /sys/kernel/tracing/events/kprobes/px64sysclocknanosleep0/enable # usleep 1
Monitoring the crash under GDB points to the exact instruction in charge of incrementing the call depth:
sarq $5, %gs:x86calldepth(%rip)
This instruction matches the one inserted by the ftraceregscaller from ftrace64.S. This emitted code was likely working fine until the introduction of
59bec00ace28 ("x86/percpu: Introduce %rip-relative addressing to PERCPUVAR()"):
it has made the call depth accounting addressing relative to $rip, instead of being based on an absolute address.
As this code exact location depends on where the trampoline lives in memory, the corresponding displacement needs to be adjusted at runtime to actually correctly find the per-cpu x86calldepth value, otherwise the targeted address is wrong, leading to the page fault seen above.
Fix the %rip-relative displacement of the copied CALLDEPTHACCOUNT instruction (from ftraceregscaller) by calling textpokeapplyrelocation(), as it is done for example by the x86 BPF JIT compiler through x86calldepthemitaccounting(). This corrects both CALLDEPTHACCOUNT slots, in ftracecaller and ftraceregscaller.
[ bp: Massage. ]
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Patch 59bec00ace28 - Configuration
On x86 retbleed-affected platforms, disable CONFIG_CALL_DEPTH_TRACKING because the reproducer indicates the crash is triggered when CONFIG_CALL_DEPTH_TRACKING is enabled.
Linux kernel (CONFIG_CALL_DEPTH_TRACKING) CONFIG_CALL_DEPTH_TRACKING = enabled - Compensating control
If you use dynamic ftrace trampolines / tracing (e.g., via kprobes/ftrace), avoid relying on %rip-relative relocation for ftrace_regs_caller/ftrace_caller CALL_DEPTH_ACCOUNT until the relocation fix described as "x86/ftrace: Relocate %rip-relative percpu refs in dynamic trampolines" is applied, since wrong displacement leads to the kernel page fault shown.
Event History
Frequently Asked Questions
Which systems are exposed to the crash condition?
The described condition requires an x86 platform affected by Retbleed, such as Skylake, with CONFIG_CALL_DEPTH_TRACKING enabled and the retbleed=stuff mitigation selected. It is triggered when a dynamic ftrace trampoline is registered.
Does exploitation require an authenticated local user or user interaction?
The supplied severity vector indicates network attack vector, no privileges required, and no user interaction. The technical description specifically identifies registration of a dynamic ftrace trampoline as the triggering action.
What is the observed impact when the condition is triggered?
The first call into the traced function can cause a supervisor-mode page fault, followed by an oops and kernel panic. The severity vector rates confidentiality, integrity, and availability impacts as high.
How can an administrator identify a potentially affected crash?
Look for a kernel page-fault oops or panic occurring on the first call to a dynamically traced function, particularly with call-depth tracking and retbleed=stuff enabled. The example includes a supervisor write page fault and a call trace containing call_depth_return_thunk.