[PATCH 4.9.y] arm: kprobes: Allow to handle reentered kprobe on single-stepping
From: Masami Hiramatsu commit f3fbd7ec62dec1528fb8044034e2885f2b257941 upstream This is arm port of commit 6a5022a56ac3 ("kprobes/x86: Allow to handle reentered kprobe on single-stepping") Since the FIQ handlers can interrupt in the single stepping (or preparing the single stepping, do_debug etc.), we should consider a kprobe is hit in the NMI handler. Even in that case, the kprobe is allowed to be reentered as same as the kprobes hit in kprobe handlers (KPROBE_HIT_ACTIVE or KPROBE_HIT_SSDONE). The real issue will happen when a kprobe hit while another reentered kprobe is processing (KPROBE_REENTER), because we already consumed a saved-area for the previous kprobe. Signed-off-by: Masami Hiramatsu Signed-off-by: Jon Medhurst Fixes: 24ba613c9d6c ("ARM kprobes: core code") Cc: sta...@vger.kernel.org #v2.6.25~v4.11 Signed-off-by: huangshaobo --- arch/arm/probes/kprobes/core.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 3eb018fa1a1f..c3362ddd6c4c 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -270,6 +270,7 @@ void __kprobes kprobe_handler(struct pt_regs *regs) switch (kcb->kprobe_status) { case KPROBE_HIT_ACTIVE: case KPROBE_HIT_SSDONE: + case KPROBE_HIT_SS: /* A pre- or post-handler probe got us here. */ kprobes_inc_nmissed_count(p); save_previous_kprobe(kcb); @@ -278,6 +279,11 @@ void __kprobes kprobe_handler(struct pt_regs *regs) singlestep(p, regs, kcb); restore_previous_kprobe(kcb); break; + case KPROBE_REENTER: + /* A nested probe was hit in FIQ, it is a BUG */ + pr_warn("Unrecoverable kprobe detected at %p.\n", + p->addr); + /* fall through */ default: /* impossible cases */ BUG(); -- 2.12.3
Re: [PATCH 4.4.y] arm: kprobes: Allow to handle reentered kprobe on single-stepping
On March 1, 2021 at 11:30 AM, Greg KH wrote: > On Mon, Feb 27, 2021 at 05:17:01PM +0800, huangshaobo wrote: > > From: Masami Hiramatsu > > > > commit f3fbd7ec62dec1528fb8044034e2885f2b257941 upstream > > > > This is arm port of commit 6a5022a56ac3 ("kprobes/x86: Allow to handle > > reentered kprobe on single-stepping") > > > > Since the FIQ handlers can interrupt in the single stepping (or > > preparing the single stepping, do_debug etc.), we should consider a > > kprobe is hit in the NMI handler. Even in that case, the kprobe is > > allowed to be reentered as same as the kprobes hit in kprobe handlers > > (KPROBE_HIT_ACTIVE or KPROBE_HIT_SSDONE). > > > > The real issue will happen when a kprobe hit while another reentered > > kprobe is processing (KPROBE_REENTER), because we already consumed a > > saved-area for the previous kprobe. > > > > Signed-off-by: Masami Hiramatsu > > Signed-off-by: Jon Medhurst > > Fixes: 24ba613c9d6c ("ARM kprobes: core code") > > Cc: sta...@vger.kernel.org #v2.6.25~v4.11 > > Signed-off-by: huangshaobo > > --- > > arch/arm/probes/kprobes/core.c | 6 ++ > > 1 file changed, 6 insertions(+) > > What about the 4.9.y tree as well? > > thanks, > > greg k-h Yes, I tested on the 4.4.y tree. From the code analysis, the same problem exists in the 2.6.25 to 4.11 trees, and of course the 4.9.y tree is also included. thanks, ShaoBo Huang
Re: [PATCH 4.4.y] arm: kprobes: Allow to handle reentered kprobe on single-stepping
> > From: Masami Hiramatsu > > commit f3fbd7ec62dec1528fb8044034e2885f2b257941 upstream > > This is arm port of commit 6a5022a56ac3 ("kprobes/x86: Allow to > handle reentered kprobe on single-stepping") > > Since the FIQ handlers can interrupt in the single stepping > (or preparing the single stepping, do_debug etc.), we should > consider a kprobe is hit in the NMI handler. Even in that > case, the kprobe is allowed to be reentered as same as the > kprobes hit in kprobe handlers > (KPROBE_HIT_ACTIVE or KPROBE_HIT_SSDONE). > > The real issue will happen when a kprobe hit while another > reentered kprobe is processing (KPROBE_REENTER), because > we already consumed a saved-area for the previous kprobe. > > Signed-off-by: Masami Hiramatsu > Signed-off-by: Jon Medhurst > Fixes: 24ba613c9d6c ("ARM kprobes: core code") > Cc: sta...@vger.kernel.org #v2.6.25~v4.11 > Signed-off-by: huangshaobo arm32 jprobe does not handle interrupt reentry correctly. When jprobe is running in singlestep, jprobe is triggered again in system interrupt, it will run to the BUG function to cause panic. jprobe needs to enter the kprobe_handler function twice, the first time to enter kprobe_handler to save the context environment; the second time to enter kprobe_handler to simulate the replaced instruction and restore the context environment of the probed function.But the system interrupt is not closed when the kprobe_handler is entered for the second time in jprobe_return. the code of jprobe_return is as follows: void __kprobes jprobe_return(void) { struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); __asm__ __volatile__ ( /* * Setup an empty pt_regs. Fill SP and PC fields as * they're needed by longjmp_break_handler. * * We allocate some slack between the original SP and start of * our fabricated regs. To be precise we want to have worst case * covered which is STMFD with all 16 regs so we allocate 2 * * sizeof(struct_pt_regs)). * * This is to prevent any simulated instruction from writing * over the regs when they are accessing the stack. */ #ifdef CONFIG_THUMB2_KERNEL ... #else "subsp, %0, %1 \n\t" #endif "ldrr0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t" "str%0, [sp, %2]\n\t" "strr0, [sp, %3]\n\t" "movr0, sp \n\t" "bl kprobe_handler \n\t" /* * Return to the context saved by setjmp_pre_handler * and restored by longjmp_break_handler. */ #ifdef CONFIG_THUMB2_KERNEL ... #else "ldrr0, [sp, %4]\n\t" "msrcpsr_cxsf, r0 \n\t" "ldmia sp, {r0 - pc} \n\t" #endif : : "r" (kcb->jprobe_saved_regs.ARM_sp), "I" (sizeof(struct pt_regs) * 2), "J" (offsetof(struct pt_regs, ARM_sp)), "J" (offsetof(struct pt_regs, ARM_pc)), "J" (offsetof(struct pt_regs, ARM_cpsr)), "J" (offsetof(struct pt_regs, ARM_lr)) : "memory", "cc"); } If the execution reaches the singlestep, the jprobe status is KPROBE_HIT_SS. If an interrupt is generated at this time, and jprobe is triggered again in the interrupt, jprobe reentry will be generated, at this time kcb->kprobe_status==KPROBE_HIT_SS, Enter the default branch to execute the BUG function, causing the system to panic. The partial code of kprobe_handler is as follows: void __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p, *cur; struct kprobe_ctlblk *kcb; kcb = get_kprobe_ctlblk(); cur = kprobe_running(); #ifdef CONFIG_THUMB2_KERNEL /* * First look for a probe which was registered using an address with * bit 0 set, this is the usual situation for pointers to Thumb code. * If not found, fallback to looking for one with bit 0 clear. */ p = get_kprobe((kprobe_opcode_t *)(regs->ARM_pc | 1)); if (!p) p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc); #else /* ! CONFIG_THUMB2_KERNEL */ p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc); #endif if (p) { if (cur) { /* Kprobe is pending, so we're recursing. */ switch (kcb->kprobe_status) { case KPROBE_HIT_ACTIVE: case KPROBE_HIT_SSDONE: /* A pre- or post-handler probe got us here. */ kprobes_inc_nmissed_count(p);
[PATCH] ARM: fix panic when kasan and kprobe are enabled
From: huangshaobo arm32 uses software to simulate the instruction replaced by kprobe. some instructions may be simulated by constructing assembly functions. therefore, before executing instruction simulation, it is necessary to construct assembly function execution environment in C language through binding registers. after kasan is enabled, the register binding relationship will be destroyed, resulting in instruction simulation errors and causing kernel panic. the kprobe emulate instruction function is distributed in three files: actions-common.c actions-arm.c actions-thumb.c, so disable KASAN when compiling these files. for example, use kprobe insert on cap_capable+20 after kasan enabled, the cap_capable assembly code is as follows: : e92d47f0push{r4, r5, r6, r7, r8, r9, sl, lr} e1a05000mov r5, r0 e280006cadd r0, r0, #108; 0x6c e1a04001mov r4, r1 e1a06002mov r6, r2 e59fa090ldr sl, [pc, #144] ; ebfc7bf8bl c03aa4b4 <__asan_load4> e595706cldr r7, [r5, #108] ; 0x6c e2859014add r9, r5, #20 .. The emulate_ldr assembly code after enabling kasan is as follows: c06f1384 : e92d47f0push{r4, r5, r6, r7, r8, r9, sl, lr} e282803cadd r8, r2, #60 ; 0x3c e1a05000mov r5, r0 e7e37855ubfxr7, r5, #16, #4 e1a8mov r0, r8 e1a09001mov r9, r1 e1a04002mov r4, r2 ebf35462bl c03c6530 <__asan_load4> e357000fcmp r7, #15 e7e36655ubfxr6, r5, #12, #4 e205a00fand sl, r5, #15 0a01beq c06f13bc e0840107add r0, r4, r7, lsl #2 ebf3545cbl c03c6530 <__asan_load4> e084010aadd r0, r4, sl, lsl #2 ebf3545abl c03c6530 <__asan_load4> e2890010add r0, r9, #16 ebf35458bl c03c6530 <__asan_load4> e5990010ldr r0, [r9, #16] e12fff30blx r0 e356000fcm r6, #15 1a14bne c06f1430 e1a06000mov r6, r0 e2840040add r0, r4, #64 ; 0x40 .. when running in emulate_ldr to simulate the ldr instruction, panic occurred, and the log is as follows: Unable to handle kernel NULL pointer dereference at virtual address 0090 pgd = ecb46400 [0090] *pgd=2e0fa003, *pmd= Internal error: Oops: 206 [#1] SMP ARM PC is at cap_capable+0x14/0xb0 LR is at emulate_ldr+0x50/0xc0 psr: 600d0293 sp : ecd63af8 ip : 0004 fp : c0a7c30c r10: r9 : c30897f4 r8 : ecd63cd4 r7 : 000f r6 : 000a r5 : e59fa090 r4 : ecd63c98 r3 : c06ae294 r2 : r1 : b7611300 r0 : bf4ec008 Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 32c5387d Table: 2d546400 DAC: Process bash (pid: 1643, stack limit = 0xecd60190) (cap_capable) from (kprobe_handler+0x218/0x340) (kprobe_handler) from (kprobe_trap_handler+0x24/0x48) (kprobe_trap_handler) from (do_undefinstr+0x13c/0x364) (do_undefinstr) from (__und_svc_finish+0x0/0x30) (__und_svc_finish) from (cap_capable+0x18/0xb0) (cap_capable) from (cap_vm_enough_memory+0x38/0x48) (cap_vm_enough_memory) from (security_vm_enough_memory_mm+0x48/0x6c) (security_vm_enough_memory_mm) from (copy_process.constprop.5+0x16b4/0x25c8) (copy_process.constprop.5) from (_do_fork+0xe8/0x55c) (_do_fork) from (SyS_clone+0x1c/0x24) (SyS_clone) from (__sys_trace_return+0x0/0x10) Code: 0050a0e1 6c0080e2 0140a0e1 0260a0e1 (f801f0e7) Fixes: 35aa1df43283 ("ARM kprobes: instruction single-stepping support") Fixes: 421015713b30 ("ARM: 9017/2: Enable KASan for ARM") Signed-off-by: huangshaobo --- arch/arm/probes/kprobes/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/probes/kprobes/Makefile b/arch/arm/probes/kprobes/Makefile index 14db56f49f0a..6159010dac4a 100644 --- a/arch/arm/probes/kprobes/Makefile +++ b/arch/arm/probes/kprobes/Makefile @@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +KASAN_SANITIZE_actions-common.o := n +KASAN_SANITIZE_actions-arm.o := n +KASAN_SANITIZE_actions-thumb.o := n obj-$(CONFIG_KPROBES) += core.o actions-common.o checkers-common.o obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o test-kprobes-objs := test-core.o -- 2.12.3