Commit 1ffd6efb1b58 for kernel
commit 1ffd6efb1b58e596ed70f660182803264a4c84d9
Author: Mani Tofigh <mt4022@columbia.edu>
Date: Thu Nov 5 15:32:14 2026 -0500
kprobes: Arm reused optprobe on cooling list
A new probe that reuses an unused probe still on a cooling list doesn't
fire. reuse_unused_kprobe() clears DISABLED, so register_aggr_kprobe()
doesn't arm it and the probe has no int3 until it's optimized again, or
ever if it can't be (e.g., it has a post_handler).
Keep a reused cooling probe disabled instead, so register_aggr_kprobe()
arms it if the new probe is enabled, or enable_kprobe() does it later.
The probe is then still unused when add_new_kprobe() force-unoptimizes
it for a new probe with a post_handler, which would unhash it and queue
it for freeing. Skip that since a cooling probe is already unoptimized.
With the fix, the new probe fires.
Link: https://lore.kernel.org/all/20261105-kprobes-optprobe-state-v2-3-7a2f5290baa0@columbia.edu/
Fixes: 06e0d3b89da1 ("kprobes: Make optprobe optimizer multi-generational and asynchronous")
Suggested-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
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 4b79bc42c57f..dddad1e01866 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1061,6 +1061,10 @@ static int reuse_unused_kprobe(struct kprobe *ap)
*/
op = container_of(ap, struct optimized_kprobe, kp);
WARN_ON_ONCE(list_empty(&op->list));
+ /* Already disarmed, the caller arms it only for an enabled probe */
+ if (optprobe_queued_cooling(op))
+ return 0;
+
/* Enable the probe again */
ap->flags &= ~KPROBE_FLAG_DISABLED;
/* Optimize it again. (remove from 'op->list') */
@@ -1573,7 +1577,8 @@ void kprobe_busy_end(void)
/* Add the new probe to 'ap->list'. */
static int add_new_kprobe(struct kprobe *ap, struct kprobe *p)
{
- if (p->post_handler)
+ /* A reused cooling probe is already unoptimized */
+ if (p->post_handler && !kprobe_unused(ap))
unoptimize_kprobe(ap, true); /* Fall back to normal kprobe */
list_add_rcu(&p->list, &ap->list);