Commit 4f72c427 authored by Roland McGrath's avatar Roland McGrath Committed by Benjamin Herrenschmidt

powerpc: Make syscall tracing use tracehook.h helpers

This changes powerpc syscall tracing to use the new tracehook.h entry
points.  There is no change, only cleanup.

In addition, the assembly changes allow do_syscall_trace_enter() to
abort the syscall without losing the information about the original
r0 value.
Signed-off-by: default avatarRoland McGrath <roland@redhat.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 6558ba2b
...@@ -343,7 +343,12 @@ syscall_dotrace: ...@@ -343,7 +343,12 @@ syscall_dotrace:
stw r0,_TRAP(r1) stw r0,_TRAP(r1)
addi r3,r1,STACK_FRAME_OVERHEAD addi r3,r1,STACK_FRAME_OVERHEAD
bl do_syscall_trace_enter bl do_syscall_trace_enter
lwz r0,GPR0(r1) /* Restore original registers */ /*
* Restore argument registers possibly just changed.
* We use the return value of do_syscall_trace_enter
* for call number to look up in the table (r0).
*/
mr r0,r3
lwz r3,GPR3(r1) lwz r3,GPR3(r1)
lwz r4,GPR4(r1) lwz r4,GPR4(r1)
lwz r5,GPR5(r1) lwz r5,GPR5(r1)
......
...@@ -214,7 +214,12 @@ syscall_dotrace: ...@@ -214,7 +214,12 @@ syscall_dotrace:
bl .save_nvgprs bl .save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD addi r3,r1,STACK_FRAME_OVERHEAD
bl .do_syscall_trace_enter bl .do_syscall_trace_enter
ld r0,GPR0(r1) /* Restore original registers */ /*
* Restore argument registers possibly just changed.
* We use the return value of do_syscall_trace_enter
* for the call number to look up in the table (r0).
*/
mr r0,r3
ld r3,GPR3(r1) ld r3,GPR3(r1)
ld r4,GPR4(r1) ld r4,GPR4(r1)
ld r5,GPR5(r1) ld r5,GPR5(r1)
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/regset.h> #include <linux/regset.h>
#include <linux/tracehook.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/user.h> #include <linux/user.h>
#include <linux/security.h> #include <linux/security.h>
...@@ -1014,31 +1015,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1014,31 +1015,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return ret; return ret;
} }
static void do_syscall_trace(void) /*
* We must return the syscall number to actually look up in the table.
* This can be -1L to skip running any syscall at all.
*/
long do_syscall_trace_enter(struct pt_regs *regs)
{ {
/* the 0x80 provides a way for the tracing parent to distinguish long ret = 0;
between a syscall stop and SIGTRAP delivery */
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;
}
}
void do_syscall_trace_enter(struct pt_regs *regs)
{
secure_computing(regs->gpr[0]); secure_computing(regs->gpr[0]);
if (test_thread_flag(TIF_SYSCALL_TRACE) if (test_thread_flag(TIF_SYSCALL_TRACE) &&
&& (current->ptrace & PT_PTRACED)) tracehook_report_syscall_entry(regs))
do_syscall_trace(); /*
* Tracing decided this syscall should not happen.
* We'll return a bogus call number to get an ENOSYS
* error, but leave the original number in regs->gpr[0].
*/
ret = -1L;
if (unlikely(current->audit_context)) { if (unlikely(current->audit_context)) {
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
...@@ -1056,16 +1050,19 @@ void do_syscall_trace_enter(struct pt_regs *regs) ...@@ -1056,16 +1050,19 @@ void do_syscall_trace_enter(struct pt_regs *regs)
regs->gpr[5] & 0xffffffff, regs->gpr[5] & 0xffffffff,
regs->gpr[6] & 0xffffffff); regs->gpr[6] & 0xffffffff);
} }
return ret ?: regs->gpr[0];
} }
void do_syscall_trace_leave(struct pt_regs *regs) void do_syscall_trace_leave(struct pt_regs *regs)
{ {
int step;
if (unlikely(current->audit_context)) if (unlikely(current->audit_context))
audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
regs->result); regs->result);
if ((test_thread_flag(TIF_SYSCALL_TRACE) step = test_thread_flag(TIF_SINGLESTEP);
|| test_thread_flag(TIF_SINGLESTEP)) if (step || test_thread_flag(TIF_SYSCALL_TRACE))
&& (current->ptrace & PT_PTRACED)) tracehook_report_syscall_exit(regs, step);
do_syscall_trace();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment