aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/ptrace.c')
-rw-r--r--arch/powerpc/kernel/ptrace.c54
1 files changed, 26 insertions, 28 deletions
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index a5d0e78779c8..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>
@@ -717,7 +718,7 @@ void user_disable_single_step(struct task_struct *task)
717 struct pt_regs *regs = task->thread.regs; 718 struct pt_regs *regs = task->thread.regs;
718 719
719 720
720#if defined(CONFIG_44x) || defined(CONFIG_BOOKE) 721#if defined(CONFIG_BOOKE)
721 /* If DAC then do not single step, skip */ 722 /* If DAC then do not single step, skip */
722 if (task->thread.dabr) 723 if (task->thread.dabr)
723 return; 724 return;
@@ -744,10 +745,11 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
744 if (addr > 0) 745 if (addr > 0)
745 return -EINVAL; 746 return -EINVAL;
746 747
748 /* The bottom 3 bits in dabr are flags */
747 if ((data & ~0x7UL) >= TASK_SIZE) 749 if ((data & ~0x7UL) >= TASK_SIZE)
748 return -EIO; 750 return -EIO;
749 751
750#ifdef CONFIG_PPC64 752#ifndef CONFIG_BOOKE
751 753
752 /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. 754 /* For processors using DABR (i.e. 970), the bottom 3 bits are flags.
753 * It was assumed, on previous implementations, that 3 bits were 755 * It was assumed, on previous implementations, that 3 bits were
@@ -769,7 +771,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
769 task->thread.dabr = data; 771 task->thread.dabr = data;
770 772
771#endif 773#endif
772#if defined(CONFIG_44x) || defined(CONFIG_BOOKE) 774#if defined(CONFIG_BOOKE)
773 775
774 /* As described above, it was assumed 3 bits were passed with the data 776 /* As described above, it was assumed 3 bits were passed with the data
775 * address, but we will assume only the mode bits will be passed 777 * address, but we will assume only the mode bits will be passed
@@ -1013,31 +1015,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1013 return ret; 1015 return ret;
1014} 1016}
1015 1017
1016static 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)
1017{ 1023{
1018 /* the 0x80 provides a way for the tracing parent to distinguish 1024 long ret = 0;
1019 between a syscall stop and SIGTRAP delivery */
1020 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
1021 ? 0x80 : 0));
1022
1023 /*
1024 * this isn't the same as continuing with a signal, but it will do
1025 * for normal use. strace only continues with a signal if the
1026 * stopping signal is not SIGTRAP. -brl
1027 */
1028 if (current->exit_code) {
1029 send_sig(current->exit_code, current, 1);
1030 current->exit_code = 0;
1031 }
1032}
1033 1025
1034void do_syscall_trace_enter(struct pt_regs *regs)
1035{
1036 secure_computing(regs->gpr[0]); 1026 secure_computing(regs->gpr[0]);
1037 1027
1038 if (test_thread_flag(TIF_SYSCALL_TRACE) 1028 if (test_thread_flag(TIF_SYSCALL_TRACE) &&
1039 && (current->ptrace & PT_PTRACED)) 1029 tracehook_report_syscall_entry(regs))
1040 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;
1041 1036
1042 if (unlikely(current->audit_context)) { 1037 if (unlikely(current->audit_context)) {
1043#ifdef CONFIG_PPC64 1038#ifdef CONFIG_PPC64
@@ -1055,16 +1050,19 @@ void do_syscall_trace_enter(struct pt_regs *regs)
1055 regs->gpr[5] & 0xffffffff, 1050 regs->gpr[5] & 0xffffffff,
1056 regs->gpr[6] & 0xffffffff); 1051 regs->gpr[6] & 0xffffffff);
1057 } 1052 }
1053
1054 return ret ?: regs->gpr[0];
1058} 1055}
1059 1056
1060void do_syscall_trace_leave(struct pt_regs *regs) 1057void do_syscall_trace_leave(struct pt_regs *regs)
1061{ 1058{
1059 int step;
1060
1062 if (unlikely(current->audit_context)) 1061 if (unlikely(current->audit_context))
1063 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, 1062 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
1064 regs->result); 1063 regs->result);
1065 1064
1066 if ((test_thread_flag(TIF_SYSCALL_TRACE) 1065 step = test_thread_flag(TIF_SINGLESTEP);
1067 || test_thread_flag(TIF_SINGLESTEP)) 1066 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
1068 && (current->ptrace & PT_PTRACED)) 1067 tracehook_report_syscall_exit(regs, step);
1069 do_syscall_trace();
1070} 1068}