[ARM] 3262/4: allow ptraced syscalls to be overriden
authorNicolas Pitre <nico@cam.org>
Sat, 14 Jan 2006 19:30:04 +0000 (19:30 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 14 Jan 2006 19:30:04 +0000 (19:30 +0000)
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 <nico@cam.org>
Signed-off-by: Daniel Jacobowitz <dan@debian.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/kernel/entry-common.S
arch/arm/kernel/ptrace.c
include/asm-arm/ptrace.h

index 8826d9803aebac3295a4a16d9921d0d6e7df1159..2b92ce85f97feef93415fd25c9260afa6367a6ae 100644 (file)
@@ -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
index e591f72bcdeb0abf8d6714e94219de4cdc2d7720..7b6256bb590ed4ddc90a2300ddf3d7299452c016 100644 (file)
@@ -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;
 }
index f40948d54448b7e4aa4f38bf1c1de697875369bf..77adb7fa169bb291368589f4fc206821f2988707 100644 (file)
@@ -23,6 +23,9 @@
 #define PTRACE_OLDSETOPTIONS   21
 
 #define PTRACE_GET_THREAD_AREA 22
+
+#define PTRACE_SET_SYSCALL     23
+
 /*
  * PSR bits
  */