From 5df0189e10bd0aaad5381cc8db9ce12e35562151 Mon Sep 17 00:00:00 2001 From: Chen Zhongjin Date: Mon, 6 Jan 2025 08:54:59 +0000 Subject: [PATCH] kprobes: Fix deadlock when unwinding kretprobe_trampoline Offering: HULK hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBFZSL -------------------------------- When there are two kretprobes on one stack and unwind the stack in the top kretprobe handler, there will be a AA dead lock as below: kretprobe_find_ret_addr <- try to lock hash lock unwind_stack kretp_handler __kretprobe_trampoline_handler <- holding hash lock 1 trampoline_probe_handler 2 kretprobe_trampoline+0 <- unwinding this frame ... Fix this if the unwinding task is current because hash table for current task can't be changed in unwinding, so there is no need to lock the hash ptr. Fixes: b67815b05d67 ("[Backport] kprobes: Add kretprobe_find_ret_addr() for searching return address") Signed-off-by: Chen Zhongjin --- kernel/kprobes.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 5d64d97975ba..9df872b3818a 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1995,7 +1995,11 @@ unsigned long kretprobe_find_ret_addr(struct task_struct *tsk, void *fp) unsigned long flags; kprobe_opcode_t *correct_ret_addr = NULL; - kretprobe_hash_lock(tsk, &head, &flags); + if (tsk != current) + kretprobe_hash_lock(tsk, &head, &flags); + else + head = &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; + hlist_for_each_entry(ri, head, hlist) { if (ri->task != tsk) continue; @@ -2006,7 +2010,8 @@ unsigned long kretprobe_find_ret_addr(struct task_struct *tsk, void *fp) break; } } - kretprobe_hash_unlock(tsk, &flags); + if (tsk != current) + kretprobe_hash_unlock(tsk, &flags); return (unsigned long)correct_ret_addr; } NOKPROBE_SYMBOL(kretprobe_find_ret_addr); -- Gitee