aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/entry_32.S7
-rw-r--r--arch/powerpc/kernel/entry_64.S7
-rw-r--r--arch/powerpc/kernel/ptrace.c47
3 files changed, 34 insertions, 27 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index da52269aec1e..e6fca6a9014d 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -343,7 +343,12 @@ syscall_dotrace:
343 stw r0,_TRAP(r1) 343 stw r0,_TRAP(r1)
344 addi r3,r1,STACK_FRAME_OVERHEAD 344 addi r3,r1,STACK_FRAME_OVERHEAD
345 bl do_syscall_trace_enter 345 bl do_syscall_trace_enter
346 lwz r0,GPR0(r1) /* Restore original registers */ 346 /*
347 * Restore argument registers possibly just changed.
348 * We use the return value of do_syscall_trace_enter
349 * for call number to look up in the table (r0).
350 */
351 mr r0,r3
347 lwz r3,GPR3(r1) 352 lwz r3,GPR3(r1)
348 lwz r4,GPR4(r1) 353 lwz r4,GPR4(r1)
349 lwz r5,GPR5(r1) 354 lwz r5,GPR5(r1)
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index d7369243ae44..79c089e97ce4 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -214,7 +214,12 @@ syscall_dotrace:
214 bl .save_nvgprs 214 bl .save_nvgprs
215 addi r3,r1,STACK_FRAME_OVERHEAD 215 addi r3,r1,STACK_FRAME_OVERHEAD
216 bl .do_syscall_trace_enter 216 bl .do_syscall_trace_enter
217 ld r0,GPR0(r1) /* Restore original registers */ 217 /*
218 * Restore argument registers possibly just changed.
219 * We use the return value of do_syscall_trace_enter
220 * for the call number to look up in the table (r0).
221 */
222 mr r0,r3
218 ld r3,GPR3(r1) 223 ld r3,GPR3(r1)
219 ld r4,GPR4(r1) 224 ld r4,GPR4(r1)
220 ld r5,GPR5(r1) 225 ld r5,GPR5(r1)
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 66204cb51a1a..6b66cd85b433 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -22,6 +22,7 @@
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/ptrace.h> 23#include <linux/ptrace.h>
24#include <linux/regset.h> 24#include <linux/regset.h>
25#include <linux/tracehook.h>
25#include <linux/elf.h> 26#include <linux/elf.h>
26#include <linux/user.h> 27#include <linux/user.h>
27#include <linux/security.h> 28#include <linux/security.h>
@@ -1014,31 +1015,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1014 return ret; 1015 return ret;
1015} 1016}
1016 1017
1017static void do_syscall_trace(void) 1018/*
1019 * We must return the syscall number to actually look up in the table.
1020 * This can be -1L to skip running any syscall at all.
1021 */
1022long do_syscall_trace_enter(struct pt_regs *regs)
1018{ 1023{
1019 /* the 0x80 provides a way for the tracing parent to distinguish 1024 long ret = 0;
1020 between a syscall stop and SIGTRAP delivery */
1021 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
1022 ? 0x80 : 0));
1023
1024 /*
1025 * this isn't the same as continuing with a signal, but it will do
1026 * for normal use. strace only continues with a signal if the
1027 * stopping signal is not SIGTRAP. -brl
1028 */
1029 if (current->exit_code) {
1030 send_sig(current->exit_code, current, 1);
1031 current->exit_code = 0;
1032 }
1033}
1034 1025
1035void do_syscall_trace_enter(struct pt_regs *regs)
1036{
1037 secure_computing(regs->gpr[0]); 1026 secure_computing(regs->gpr[0]);
1038 1027
1039 if (test_thread_flag(TIF_SYSCALL_TRACE) 1028 if (test_thread_flag(TIF_SYSCALL_TRACE) &&
1040 && (current->ptrace & PT_PTRACED)) 1029 tracehook_report_syscall_entry(regs))
1041 do_syscall_trace(); 1030 /*
1031 * Tracing decided this syscall should not happen.
1032 * We'll return a bogus call number to get an ENOSYS
1033 * error, but leave the original number in regs->gpr[0].
1034 */
1035 ret = -1L;
1042 1036
1043 if (unlikely(current->audit_context)) { 1037 if (unlikely(current->audit_context)) {
1044#ifdef CONFIG_PPC64 1038#ifdef CONFIG_PPC64
@@ -1056,16 +1050,19 @@ void do_syscall_trace_enter(struct pt_regs *regs)
1056 regs->gpr[5] & 0xffffffff, 1050 regs->gpr[5] & 0xffffffff,
1057 regs->gpr[6] & 0xffffffff); 1051 regs->gpr[6] & 0xffffffff);
1058 } 1052 }
1053
1054 return ret ?: regs->gpr[0];
1059} 1055}
1060 1056
1061void do_syscall_trace_leave(struct pt_regs *regs) 1057void do_syscall_trace_leave(struct pt_regs *regs)
1062{ 1058{
1059 int step;
1060
1063 if (unlikely(current->audit_context)) 1061 if (unlikely(current->audit_context))
1064 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, 1062 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
1065 regs->result); 1063 regs->result);
1066 1064
1067 if ((test_thread_flag(TIF_SYSCALL_TRACE) 1065 step = test_thread_flag(TIF_SINGLESTEP);
1068 || test_thread_flag(TIF_SINGLESTEP)) 1066 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
1069 && (current->ptrace & PT_PTRACED)) 1067 tracehook_report_syscall_exit(regs, step);
1070 do_syscall_trace();
1071} 1068}