diff options
Diffstat (limited to 'arch/powerpc/kernel/ptrace.c')
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 54 |
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 | ||
1016 | static 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 | */ | ||
1022 | long 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 | ||
1034 | void 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 | ||
1060 | void do_syscall_trace_leave(struct pt_regs *regs) | 1057 | void 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 | } |