From 82f852cd73e8daa9edf2cb6e68a892df79e87816 Mon Sep 17 00:00:00 2001 From: Chen Zhongjin Date: Wed, 2 Apr 2025 07:20:51 +0000 Subject: [PATCH 1/2] kprobes: Fix deadlock when unwinding kretprobe_trampoline hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBY4FJ -------------------------------- 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 From ee2130603240b0c82414f6dfd2cf14afade7f74d Mon Sep 17 00:00:00 2001 From: Chen Zhongjin Date: Wed, 2 Apr 2025 07:20:52 +0000 Subject: [PATCH 2/2] powerpc: Fix save r13 on kprobe/ftrace entry hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBY4FQ -------------------------------- In kprobe and ftrace entry, r13 will be saved to stack and restored after handler. There is a period between entry and handler where the task can be scheduled, then the r13 for one cpu will be restored to another cpu, and cause the paca_ptrs wrong. Fix this by stop saving and restoring r13 in kprobe/ftrace entry. Fixes: 51c9c0843993 ("powerpc/kprobes: Implement Optprobes") Signed-off-by: Chen Zhongjin --- arch/powerpc/kernel/optprobes_head.S | 10 ++++++---- arch/powerpc/kernel/trace/ftrace_64_mprofile.S | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/kernel/optprobes_head.S b/arch/powerpc/kernel/optprobes_head.S index ff8ba4d3824d..9d803cc2392f 100644 --- a/arch/powerpc/kernel/optprobes_head.S +++ b/arch/powerpc/kernel/optprobes_head.S @@ -36,8 +36,9 @@ optprobe_template_entry: addi r0,r1,INT_FRAME_SIZE std r0,GPR1(r1) SAVE_10GPRS(2,r1) - SAVE_10GPRS(12,r1) - SAVE_10GPRS(22,r1) + SAVE_GPR(12,r1) + SAVE_10GPRS(14,r1) + SAVE_8GPRS(24,r1) /* Save SPRS */ mfmsr r5 std r5,_MSR(r1) @@ -119,8 +120,9 @@ optprobe_template_call_emulate: mtcr r5 REST_GPR(0,r1) REST_10GPRS(2,r1) - REST_10GPRS(12,r1) - REST_10GPRS(22,r1) + REST_GPR(12,r1) + REST_10GPRS(14,r1) + REST_8GPRS(24,r1) /* Restore the previous SP */ addi r1,r1,INT_FRAME_SIZE diff --git a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S index 0bc39ff53233..32e354d9ee9b 100644 --- a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S +++ b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S @@ -51,8 +51,9 @@ _GLOBAL(ftrace_regs_caller) cmpdi r3, 0 beq ftrace_no_trace - SAVE_10GPRS(12, r1) - SAVE_10GPRS(22, r1) + SAVE_GPR(12,r1) + SAVE_10GPRS(14,r1) + SAVE_8GPRS(24,r1) /* Save previous stack pointer (r1) */ addi r8, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE @@ -115,8 +116,9 @@ ftrace_regs_call: /* Restore gprs */ REST_GPR(0,r1) REST_10GPRS(2,r1) - REST_10GPRS(12,r1) - REST_10GPRS(22,r1) + REST_GPR(12,r1) + REST_10GPRS(14,r1) + REST_8GPRS(24,r1) /* Restore possibly modified LR */ ld r0, _LINK(r1) -- Gitee