[bug 20412] PTRACE_SINGLESTEP'ing an instruction that calls user helpers never stops the child on ARM
Timo Juhani Lindfors <[email protected]>
| Newsgroups | gmane.linux.ports.arm.general |
|---|---|
| Message-ID | <[email protected]> |
Hi, [ Also available as https://bugzilla.kernel.org/show_bug.cgi?id=20412 ] On ARM glibc contains 0x4009b864 <getchar+240>: sub pc, r3, #63 ; 0x3f that jumps to the kernel provided user helper page to access __kernel_cmpxchg at 0xffff0fc0. If I try to PTRACE_SINGLESTEP this instruction the child never stops. Parent keeps wait()ing forever but child effectively escapes the tracing completely and continues executing instructions without notifying the parent. On ARM single stepping is done by adding a breakpoint to possible branch targets of each instruction. I guess when ptrace_set_bpt() tries to add_breakpoint() to this page it just fails? (There's even a comment that says it can fail and that return value is not checked...) Since all user helpers return to LR I think we could teach get_branch_address to treat jumps to user helpers as instructions that branch to lr? The attached patch works for me but I am not sure if it is a good solution. _______________________________________________ linux-arm mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm
0001-Make-PTRACE_SINGLESTEP-work-with-user-helpers.patch
(text/x-diff, 1.2 KB)
From 61ee9012929a406f2a63f43ad055279af08bba3b Mon Sep 17 00:00:00 2001 From: Timo Juhani Lindfors <[email protected]> Date: Sat, 16 Oct 2010 16:15:55 +0300 Subject: [PATCH] Make PTRACE_SINGLESTEP work with user helpers When userland jumps to kernel provided user helper page to perform operations like __kernel_cmpxchg trace_set_bpt() is unable to add breakpoints. Since single stepping is implemented with breakpoints this means that a process can effectively escape tracing completely. This patch treats jumps to user helper page as instructions that branch to LR since all user helpers return to LR. --- arch/arm/kernel/ptrace.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 3f562a7..5877c0e 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -26,6 +26,7 @@ #include "ptrace.h" +#define REG_LR 14 #define REG_PC 15 #define REG_PSR 16 /* @@ -329,6 +330,9 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in break; } + if (alt >= (void*)CONFIG_VECTORS_BASE && alt < (void*)CONFIG_VECTORS_BASE + PAGE_SIZE) + alt = get_user_reg(child, REG_LR); + return alt; } -- 1.5.6.5