[PATCH v1 1/4] LoongArch: ftrace: Fix stale per-CPU kprobe state after task migration
From: Tiezhu Yang
Date: Tue May 12 2026 - 04:25:54 EST
When probing kernel functions via ftrace, a scheduling event occurring
inside the kprobe handler can lead to task migration. If the executing
task is migrated to another CPU after setting per-CPU "current_kprobe"
but before clearing it, the original CPU is left with a stale state.
This stale state causes the original CPU to remain permanently "busy"
from the kprobe perspective, as its per-CPU "current_kprobe" is never
cleared thereafter. As a result, subsequent kprobes triggered on that
CPU are incorrectly treated as nested probes and skipped (increasing
nmissed count), leading to functional failures on the affected CPU.
Fix this by adding a self-reset mechanism in kprobe_ftrace_handler().
When a kprobe is triggered while the "current_kprobe" is already set,
verify if it is a stale state by checking:
(1) In task context (not a legitimate interrupt nest).
(2) A different kprobe (not a recursive trigger on the same probe).
(3) In an active or stepping state.
If these conditions are met, it indicates that the previous kprobe
execution was scheduled and migrated. Reset the per-CPU state to
recover the CPU's kprobe functionality, allowing the current probe
to be processed normally.
This acts as a defensive mechanism to recover the CPU's kprobe state
machine from inconsistent states caused by unexpected task migrations
during kprobe execution.
Fixes: 09e679c28a4d ("LoongArch: Add kprobes on ftrace support")
Reported-by: Hui Li <lihui@xxxxxxxxxxx>
Signed-off-by: Tiezhu Yang <yangtiezhu@xxxxxxxxxxx>
---
arch/loongarch/kernel/ftrace_dyn.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/loongarch/kernel/ftrace_dyn.c b/arch/loongarch/kernel/ftrace_dyn.c
index d5d81d74034c..03d303d67f18 100644
--- a/arch/loongarch/kernel/ftrace_dyn.c
+++ b/arch/loongarch/kernel/ftrace_dyn.c
@@ -310,6 +310,29 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
goto out;
kcb = get_kprobe_ctlblk();
+
+ if (kprobe_running()) {
+ /*
+ * If a previous kprobe handler was interrupted by a scheduling event
+ * and the task migrated to another CPU, the "current_kprobe" state
+ * might be left stale on this CPU.
+ *
+ * Reset the stale state here to allow the current probe to proceed
+ * normally instead of being falsely treated as a nested probe if:
+ *
+ * (1) In task context (not a legitimate interrupt nest).
+ * (2) A different kprobe (not a recursive trigger on the same probe).
+ * (3) In an active or stepping state.
+ *
+ * This acts as a defensive mechanism to recover the CPU's kprobe state
+ * machine from inconsistent states caused by unexpected task migrations.
+ */
+ if (in_task() && kprobe_running() != p &&
+ (kcb->kprobe_status == KPROBE_HIT_ACTIVE ||
+ kcb->kprobe_status == KPROBE_HIT_SSDONE))
+ reset_current_kprobe();
+ }
+
if (kprobe_running()) {
kprobes_inc_nmissed_count(p);
} else {
--
2.42.0