From: Nicolas Pitre Date: Sat, 14 Jan 2006 19:30:04 +0000 (+0000) Subject: [ARM] 3262/4: allow ptraced syscalls to be overriden X-Git-Tag: v2.6.16-rc1~107^2 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3f471126ee53feb5e9b210ea2f525ed3bb9b7a7f;p=linux-2.6 [ARM] 3262/4: allow ptraced syscalls to be overriden Patch from Nicolas Pitre This is needed by strace to properly handle the tracing of some system calls. It could be useful for other applications as well. Based on an earlier patch from Daniel Jacobowitz. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Jacobowitz Signed-off-by: Russell King --- diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 8826d9803a..2b92ce85f9 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -214,11 +214,13 @@ ENTRY(vector_swi) * context switches, and waiting for our parent to respond. */ __sys_trace: + mov r2, scno add r1, sp, #S_OFF mov r0, #0 @ trace entry [IP = 0] bl syscall_trace adr lr, __sys_trace_return @ return address + mov scno, r0 @ syscall number (possibly new) add r1, sp, #S_R0 + S_OFF @ pointer to regs cmp scno, #NR_syscalls @ check upper syscall limit ldmccia r1, {r0 - r3} @ have to reload r0 - r3 @@ -227,6 +229,7 @@ __sys_trace: __sys_trace_return: str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 + mov r2, scno mov r1, sp mov r0, #1 @ trace exit [IP = 1] bl syscall_trace diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index e591f72bcd..7b6256bb59 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -766,6 +766,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) (unsigned long __user *) data); break; + case PTRACE_SET_SYSCALL: + ret = 0; + child->ptrace_message = data; + break; + default: ret = ptrace_request(child, request, addr, data); break; @@ -774,14 +779,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } -asmlinkage void syscall_trace(int why, struct pt_regs *regs) +asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) { unsigned long ip; if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + return scno; if (!(current->ptrace & PT_PTRACED)) - return; + return scno; /* * Save IP. IP is used to denote syscall entry/exit: @@ -790,6 +795,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs) ip = regs->ARM_ip; regs->ARM_ip = why; + current->ptrace_message = scno; + /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) @@ -804,4 +811,6 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs) current->exit_code = 0; } regs->ARM_ip = ip; + + return current->ptrace_message; } diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h index f40948d544..77adb7fa16 100644 --- a/include/asm-arm/ptrace.h +++ b/include/asm-arm/ptrace.h @@ -23,6 +23,9 @@ #define PTRACE_OLDSETOPTIONS 21 #define PTRACE_GET_THREAD_AREA 22 + +#define PTRACE_SET_SYSCALL 23 + /* * PSR bits */