On Tue, 17 Feb 2026 16:55:44 +0000
Mark Rutland [off-list ref] wrote:
On Tue, Feb 17, 2026 at 07:08:54PM +0530, Khaja Hussain Shaik Khaji wrote:
quoted
On arm64, non-emulatable kprobes instructions execute out-of-line (XOL)
after returning from the initial debug exception. The XOL instruction
runs in normal kernel context, while kprobe state is maintained per-CPU.
The XOL instruction runs in a context with all DAIF bits set (see
kprobes_save_local_irqflag() and kprobes_restore_local_irqflag()), so
not quite a regular kernel context.
quoted
If the task is preempted or migrates during the XOL window, the subsequent
SS-BRK exception may be handled on a different CPU, corrupting per-CPU
kprobe state and preventing correct recovery.
I think we need a better explanation of this.
Since DAIF is masked, we won't take an IRQ to preempt during the actual
XOL execution.
AFAICT we *could* explicitly preempt/schedule in C code around the XOL
execution. However, AFAICT that'd equally apply to other architectures,
and on x86 they *removed* the preempt count manipulation in commit:
2bbda764d720aaca ("kprobes/x86: Do not disable preempt on int3 path")
... so it looks like there's a wider potential problem here.
Can you please share an example failure that you have seen? .. and how
you triggered it (e.g. is this a plain kprobe, something with bpf, etc).
Yeah, this is important to know. Did it really happen on the single
stepping? or in user's handler function?
I reckon you could hack a warning something into schedule() (or
cond_resched(), etc) that detects when there's an active XOL slot, so
that we can get the full backtrace.
Sounds good way to show it.
Thank you,
quoted
Disable preemption across the XOL instruction and re-enable it in the
SS-BRK handler to prevent migration until control returns to the kprobe
handler.
This might work, but without some more detail I'm not certain this is
sufficient, and I believe other architectures are likely affected by the
same problem.
Thanks,
Mark.
quoted
Signed-off-by: Khaja Hussain Shaik Khaji <redacted>
---
arch/arm64/kernel/probes/kprobes.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 43a0361a8bf0..d8a70c456543 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -227,6 +227,14 @@ static void __kprobes setup_singlestep(struct kprobe *p,
kprobes_save_local_irqflag(kcb, regs);
instruction_pointer_set(regs, slot);
+
+ /*
+ * Disable preemption across the out-of-line (XOL) instruction.
+ * The XOL instruction executes in normal kernel context and
+ * kprobe state is per-CPU.
+ */
+ preempt_disable();
+
} else {
/* insn simulation */
arch_simulate_insn(p, regs);@@ -363,6 +371,11 @@ kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr)
kprobes_restore_local_irqflag(kcb, regs);
post_kprobe_handler(cur, kcb, regs);
+ /*
+ * Re-enable preemption after completing the XOL instruction.
+ */
+ preempt_enable_no_resched();
+
return DBG_HOOK_HANDLED;
}
--
2.34.1
--
Masami Hiramatsu (Google) [off-list ref]