[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.