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 | } |
