aboutsummaryrefslogtreecommitdiff
path: root/arch/parisc/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/kernel/ptrace.c')
-rw-r--r--arch/parisc/kernel/ptrace.c78
1 files changed, 49 insertions, 29 deletions
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 927db3668b6..e842ee233db 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -13,20 +13,21 @@
#include <linux/smp.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
+#include <linux/tracehook.h>
#include <linux/user.h>
#include <linux/personality.h>
#include <linux/security.h>
#include <linux/compat.h>
#include <linux/signal.h>
+#include <linux/audit.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
#include <asm/processor.h>
#include <asm/asm-offsets.h>
/* PSW bits we allow the debugger to modify */
-#define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB)
+#define USER_PSW_BITS (PSW_N | PSW_B | PSW_V | PSW_CB)
/*
* Called by kernel/ptrace.c when detaching..
@@ -35,7 +36,8 @@
*/
void ptrace_disable(struct task_struct *task)
{
- task->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
+ clear_tsk_thread_flag(task, TIF_SINGLESTEP);
+ clear_tsk_thread_flag(task, TIF_BLOCKSTEP);
/* make sure the trap bits are not set */
pa_psw(task)->r = 0;
@@ -55,8 +57,8 @@ void user_disable_single_step(struct task_struct *task)
void user_enable_single_step(struct task_struct *task)
{
- task->ptrace &= ~PT_BLOCKSTEP;
- task->ptrace |= PT_SINGLESTEP;
+ clear_tsk_thread_flag(task, TIF_BLOCKSTEP);
+ set_tsk_thread_flag(task, TIF_SINGLESTEP);
if (pa_psw(task)->n) {
struct siginfo si;
@@ -98,8 +100,8 @@ void user_enable_single_step(struct task_struct *task)
void user_enable_block_step(struct task_struct *task)
{
- task->ptrace &= ~PT_SINGLESTEP;
- task->ptrace |= PT_BLOCKSTEP;
+ clear_tsk_thread_flag(task, TIF_SINGLESTEP);
+ set_tsk_thread_flag(task, TIF_BLOCKSTEP);
/* Enable taken branch trap. */
pa_psw(task)->r = 0;
@@ -108,7 +110,8 @@ void user_enable_block_step(struct task_struct *task)
pa_psw(task)->l = 0;
}
-long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request,
+ unsigned long addr, unsigned long data)
{
unsigned long tmp;
long ret = -EIO;
@@ -118,11 +121,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Read the word at location addr in the USER area. For ptraced
processes, the kernel saves all regs on a syscall. */
case PTRACE_PEEKUSR:
- if ((addr & (sizeof(long)-1)) ||
- (unsigned long) addr >= sizeof(struct pt_regs))
+ if ((addr & (sizeof(unsigned long)-1)) ||
+ addr >= sizeof(struct pt_regs))
break;
tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
- ret = put_user(tmp, (unsigned long *) data);
+ ret = put_user(tmp, (unsigned long __user *) data);
break;
/* Write the word at location addr in the USER area. This will need
@@ -149,8 +152,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
- if ((addr & (sizeof(long)-1)) ||
- (unsigned long) addr >= sizeof(struct pt_regs))
+ if ((addr & (sizeof(unsigned long)-1)) ||
+ addr >= sizeof(struct pt_regs))
break;
if ((addr >= PT_GR1 && addr <= PT_GR31) ||
addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
@@ -263,22 +266,39 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
}
#endif
+long do_syscall_trace_enter(struct pt_regs *regs)
+{
+ long ret = 0;
+
+ if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+ tracehook_report_syscall_entry(regs))
+ ret = -1L;
+
+#ifdef CONFIG_64BIT
+ if (!is_compat_task())
+ audit_syscall_entry(AUDIT_ARCH_PARISC64,
+ regs->gr[20],
+ regs->gr[26], regs->gr[25],
+ regs->gr[24], regs->gr[23]);
+ else
+#endif
+ audit_syscall_entry(AUDIT_ARCH_PARISC,
+ regs->gr[20] & 0xffffffff,
+ regs->gr[26] & 0xffffffff,
+ regs->gr[25] & 0xffffffff,
+ regs->gr[24] & 0xffffffff,
+ regs->gr[23] & 0xffffffff);
+
+ return ret ? : regs->gr[20];
+}
-void syscall_trace(void)
+void do_syscall_trace_exit(struct pt_regs *regs)
{
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return;
- if (!(current->ptrace & PT_PTRACED))
- return;
- 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;
- }
+ int stepping = test_thread_flag(TIF_SINGLESTEP) ||
+ test_thread_flag(TIF_BLOCKSTEP);
+
+ audit_syscall_exit(regs);
+
+ if (stepping || test_thread_flag(TIF_SYSCALL_TRACE))
+ tracehook_report_syscall_exit(regs, stepping);
}