Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab99c733 authored by Paul Mundt's avatar Paul Mundt
Browse files

sh: Make syscall tracer use tracehook notifiers, add TIF_NOTIFY_RESUME.



This follows the changes in commits:

7d6d637d
4f72c427

on powerpc. Adding in TIF_NOTIFY_RESUME, and cleaning up the syscall
tracing to be more generic. This is an incremental step to turning
on tracehook, as well as unifying more of the ptrace and signal code
across the 32/64 split.

Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent c459dbf2
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -119,10 +119,11 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SINGLESTEP		4	/* singlestepping active */
#define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
#define TIF_SECCOMP		6	/* secure computing */
#define TIF_NOTIFY_RESUME	7	/* callback before returning to user */
#define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE		18
#define TIF_FREEZE		19
#define TIF_FREEZE		19	/* Freezing for suspend */

#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -131,6 +132,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
#define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP		(1 << TIF_SECCOMP)
#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
#define _TIF_USEDFPU		(1 << TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
#define _TIF_FREEZE		(1 << TIF_FREEZE)
@@ -148,7 +150,8 @@ static inline struct thread_info *current_thread_info(void)
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK	(_TIF_SYSCALL_TRACE | _TIF_SIGPENDING      | \
				 _TIF_NEED_RESCHED  | _TIF_SYSCALL_AUDIT   | \
				 _TIF_SINGLESTEP    | _TIF_RESTORE_SIGMASK)
				 _TIF_SINGLESTEP    | _TIF_RESTORE_SIGMASK | \
				 _TIF_NOTIFY_RESUME)

/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK		(_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
+9 −8
Original line number Diff line number Diff line
@@ -987,11 +987,11 @@ work_resched:
work_notifysig:
	gettr	tr1, LINK

	movi	do_signal, r6
	movi	do_notify_resume, r6
	ptabs	r6, tr0
	or	SP, ZERO, r2
	or	ZERO, ZERO, r3
	blink	tr0, LINK	    /* Call do_signal(regs, 0), return here */
	or	r7, ZERO, r3
	blink	tr0, LINK	    /* Call do_notify_resume(regs, current_thread_info->flags), return here */

restore_all:
	/* Do prefetches */
@@ -1305,13 +1305,15 @@ syscall_allowed:
	beq/l	r6, ZERO, tr0

	/* Trace it by calling syscall_trace before and after */
	movi	syscall_trace, r4
	movi	do_syscall_trace_enter, r4
	or	SP, ZERO, r2
	or	ZERO, ZERO, r3
	ptabs	r4, tr0
	blink	tr0, LINK

	/* Reload syscall number as r5 is trashed by syscall_trace */
	/* Save the retval */
	st.q	SP, FRAME_R(2), r2

	/* Reload syscall number as r5 is trashed by do_syscall_trace_enter */
	ld.q	SP, FRAME_S(FSYSCALL_ID), r5
	andi	r5, 0x1ff, r5

@@ -1343,9 +1345,8 @@ syscall_ret_trace:
	/* We get back here only if under trace */
	st.q	SP, FRAME_R(9), r2	/* Save return value */

	movi	syscall_trace, LINK
	movi	do_syscall_trace_leave, LINK
	or	SP, ZERO, r2
	movi	1, r3
	ptabs	LINK, tr0
	blink	tr0, LINK

+5 −7
Original line number Diff line number Diff line
@@ -211,10 +211,8 @@ syscall_exit_work:
	 nop
#endif
	sti
	! XXX setup arguments...
	mov	r15, r4
	mov	#1, r5
	mov.l	4f, r0			! do_syscall_trace
	mov.l	8f, r0			! do_syscall_trace_leave
	jsr	@r0
	 nop
	bra	resume_userspace
@@ -223,12 +221,11 @@ syscall_exit_work:
	.align	2
syscall_trace_entry:
	!                     	Yes it is traced.
	! XXX setup arguments...
	mov     r15, r4
	mov     #0, r5
	mov.l	4f, r11		! Call do_syscall_trace which notifies
	mov.l	7f, r11		! Call do_syscall_trace_enter which notifies
	jsr	@r11	    	! superior (will chomp R[0-7])
	 nop
	mov.l	r0, @(OFF_R0,r15)	! Save return value
	!			Reload R0-R4 from kernel stack, where the
	!   	    	    	parent may have modified them using
	!   	    	    	ptrace(POKEUSR).  (Note that R0-R2 are
@@ -389,8 +386,9 @@ syscall_exit:
#endif
2:	.long	NR_syscalls
3:	.long	sys_call_table
4:	.long	do_syscall_trace
#ifdef CONFIG_TRACE_IRQFLAGS
5:	.long	trace_hardirqs_on
6:	.long	trace_hardirqs_off
#endif
7:	.long	do_syscall_trace_enter
8:	.long	do_syscall_trace_leave
+26 −28
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/tracehook.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -216,41 +217,38 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
	return ret;
}

asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
	struct task_struct *tsk = current;
	long ret = 0;

	secure_computing(regs->regs[0]);

	if (unlikely(current->audit_context) && entryexit)
		audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
				   regs->regs[0]);

	if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
	    !test_thread_flag(TIF_SINGLESTEP))
		goto out;
	if (!(tsk->ptrace & PT_PTRACED))
		goto out;

	/* the 0x80 provides a way for the tracing parent to distinguish
	   between a syscall stop and SIGTRAP delivery */
	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
				 !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));

	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
	    tracehook_report_syscall_entry(regs))
		/*
	 * 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
		 * 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->regs[0].
		 */
	if (tsk->exit_code) {
		send_sig(tsk->exit_code, tsk, 1);
		tsk->exit_code = 0;
	}
		ret = -1L;

out:
	if (unlikely(current->audit_context) && !entryexit)
	if (unlikely(current->audit_context))
		audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3],
				    regs->regs[4], regs->regs[5],
				    regs->regs[6], regs->regs[7]);

	return ret ?: regs->regs[0];
}

asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
	int step;

	if (unlikely(current->audit_context))
		audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
				   regs->regs[0]);

	step = test_thread_flag(TIF_SINGLESTEP);
	if (step || test_thread_flag(TIF_SYSCALL_TRACE))
		tracehook_report_syscall_exit(regs, step);
}
+24 −26
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/syscalls.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/tracehook.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -221,40 +222,37 @@ asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
	return sys_ptrace(request, pid, addr, data);
}

asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit)
asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs)
{
	struct task_struct *tsk = current;
	long long ret = 0;

	secure_computing(regs->regs[9]);

	if (unlikely(current->audit_context) && entryexit)
		audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
				   regs->regs[9]);

	if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
	    !test_thread_flag(TIF_SINGLESTEP))
		goto out;
	if (!(tsk->ptrace & PT_PTRACED))
		goto out;

	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
				!test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));

	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
	    tracehook_report_syscall_entry(regs))
		/*
	 * 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
		 * 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->regs[0].
		 */
	if (tsk->exit_code) {
		send_sig(tsk->exit_code, tsk, 1);
		tsk->exit_code = 0;
	}
		ret = -1LL;

out:
	if (unlikely(current->audit_context) && !entryexit)
	if (unlikely(current->audit_context))
		audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1],
				    regs->regs[2], regs->regs[3],
				    regs->regs[4], regs->regs[5]);

	return ret ?: regs->regs[9];
}

asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
	if (unlikely(current->audit_context))
		audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
				   regs->regs[9]);

	if (test_thread_flag(TIF_SYSCALL_TRACE))
		tracehook_report_syscall_exit(regs, 0);
}

/* Called with interrupts disabled */
Loading