powerpc: Make syscall tracing use tracehook.h helpers
authorRoland McGrath <roland@redhat.com>
Sun, 27 Jul 2008 06:51:03 +0000 (16:51 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 28 Jul 2008 06:30:49 +0000 (16:30 +1000)
This changes powerpc syscall tracing to use the new tracehook.h entry
points.  There is no change, only cleanup.

In addition, the assembly changes allow do_syscall_trace_enter() to
abort the syscall without losing the information about the original
r0 value.

Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/ptrace.c

index da52269aec1e86fc05a2e1fb79d46dcc0b846a88..e6fca6a9014d172864b4d6b393132ca4f0369a55 100644 (file)
@@ -343,7 +343,12 @@ syscall_dotrace:
        stw     r0,_TRAP(r1)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      do_syscall_trace_enter
-       lwz     r0,GPR0(r1)     /* Restore original registers */
+       /*
+        * Restore argument registers possibly just changed.
+        * We use the return value of do_syscall_trace_enter
+        * for call number to look up in the table (r0).
+        */
+       mr      r0,r3
        lwz     r3,GPR3(r1)
        lwz     r4,GPR4(r1)
        lwz     r5,GPR5(r1)
index d7369243ae44ab3aa0e12fcec3db30ae717677c2..79c089e97ce4a595ed60e7131e3e39fe366966e9 100644 (file)
@@ -214,7 +214,12 @@ syscall_dotrace:
        bl      .save_nvgprs
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .do_syscall_trace_enter
-       ld      r0,GPR0(r1)     /* Restore original registers */
+       /*
+        * Restore argument registers possibly just changed.
+        * We use the return value of do_syscall_trace_enter
+        * for the call number to look up in the table (r0).
+        */
+       mr      r0,r3
        ld      r3,GPR3(r1)
        ld      r4,GPR4(r1)
        ld      r5,GPR5(r1)
index 66204cb51a1aaae8ca95fb7d01e2a9de144dd123..6b66cd85b433ce8c296848f42e77ae5e18bcca87 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/regset.h>
+#include <linux/tracehook.h>
 #include <linux/elf.h>
 #include <linux/user.h>
 #include <linux/security.h>
@@ -1014,31 +1015,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        return ret;
 }
 
-static void do_syscall_trace(void)
+/*
+ * We must return the syscall number to actually look up in the table.
+ * This can be -1L to skip running any syscall at all.
+ */
+long do_syscall_trace_enter(struct pt_regs *regs)
 {
-       /* 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)
-                                ? 0x80 : 0));
-
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
-       }
-}
+       long ret = 0;
 
-void do_syscall_trace_enter(struct pt_regs *regs)
-{
        secure_computing(regs->gpr[0]);
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE)
-           && (current->ptrace & PT_PTRACED))
-               do_syscall_trace();
+       if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+           tracehook_report_syscall_entry(regs))
+               /*
+                * Tracing decided this syscall should not happen.
+                * We'll return a bogus call number to get an ENOSYS
+                * error, but leave the original number in regs->gpr[0].
+                */
+               ret = -1L;
 
        if (unlikely(current->audit_context)) {
 #ifdef CONFIG_PPC64
@@ -1056,16 +1050,19 @@ void do_syscall_trace_enter(struct pt_regs *regs)
                                            regs->gpr[5] & 0xffffffff,
                                            regs->gpr[6] & 0xffffffff);
        }
+
+       return ret ?: regs->gpr[0];
 }
 
 void do_syscall_trace_leave(struct pt_regs *regs)
 {
+       int step;
+
        if (unlikely(current->audit_context))
                audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
                                   regs->result);
 
-       if ((test_thread_flag(TIF_SYSCALL_TRACE)
-            || test_thread_flag(TIF_SINGLESTEP))
-           && (current->ptrace & PT_PTRACED))
-               do_syscall_trace();
+       step = test_thread_flag(TIF_SINGLESTEP);
+       if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall_exit(regs, step);
 }