Commit ce9bc14902d1 for kernel
commit ce9bc14902d1c27b6c0eac25666e2516e13f2b19
Author: Mani Tofigh <mt4022@columbia.edu>
Date: Thu Nov 5 15:32:13 2026 -0500
kprobes: Do not disarm unhashed optprobe on dispatch
A new probe at the address of a force-unoptimized probe can stop
firing. When unoptimize_kprobe() force-unoptimizes an unused probe it
disarms and unhashes it, but the next dispatch disarms it again. If a
new probe was registered at the same address in the meantime, the
second disarm clears the new probe's int3. For a module address the
same disarm would write to freed module text after rmmod.
Skip the disarm for unhashed probes since they're always disarmed before
they're unhashed. With the fix, the new probe fires.
Link: https://lore.kernel.org/all/20261105-kprobes-optprobe-state-v2-2-7a2f5290baa0@columbia.edu/
Fixes: 06e0d3b89da1 ("kprobes: Make optprobe optimizer multi-generational and asynchronous")
Signed-off-by: Mani Tofigh <mt4022@columbia.edu>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 2df6f9894c3e..4b79bc42c57f 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -633,8 +633,12 @@ static void do_unoptimize_kprobes(struct list_head *unopt_list,
list_for_each_entry_safe(op, tmp, free_list, list) {
/* Switching from detour code to origin */
op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
- /* Disarm probes if marked disabled and not gone */
- if (kprobe_disabled(&op->kp) && !kprobe_gone(&op->kp))
+ /*
+ * Disarm probes if marked disabled and not gone. Unhashed probes
+ * were disarmed before they were unhashed.
+ */
+ if (kprobe_disabled(&op->kp) && !kprobe_gone(&op->kp) &&
+ !hlist_unhashed(&op->kp.hlist))
arch_disarm_kprobe(&op->kp);
if (kprobe_unused(&op->kp)) {
/*