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 Original line 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_SINGLESTEP		4	/* singlestepping active */
#define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
#define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
#define TIF_SECCOMP		6	/* secure computing */
#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_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_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE		18
#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_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
#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_SINGLESTEP		(1 << TIF_SINGLESTEP)
#define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP		(1 << TIF_SECCOMP)
#define _TIF_SECCOMP		(1 << TIF_SECCOMP)
#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
#define _TIF_USEDFPU		(1 << TIF_USEDFPU)
#define _TIF_USEDFPU		(1 << TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
#define _TIF_FREEZE		(1 << TIF_FREEZE)
#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 */
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK	(_TIF_SYSCALL_TRACE | _TIF_SIGPENDING      | \
#define _TIF_ALLWORK_MASK	(_TIF_SYSCALL_TRACE | _TIF_SIGPENDING      | \
				 _TIF_NEED_RESCHED  | _TIF_SYSCALL_AUDIT   | \
				 _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 */
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK		(_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
#define _TIF_WORK_MASK		(_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
+9 −8
Original line number Original line Diff line number Diff line
@@ -987,11 +987,11 @@ work_resched:
work_notifysig:
work_notifysig:
	gettr	tr1, LINK
	gettr	tr1, LINK


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


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


	/* Trace it by calling syscall_trace before and after */
	/* Trace it by calling syscall_trace before and after */
	movi	syscall_trace, r4
	movi	do_syscall_trace_enter, r4
	or	SP, ZERO, r2
	or	SP, ZERO, r2
	or	ZERO, ZERO, r3
	ptabs	r4, tr0
	ptabs	r4, tr0
	blink	tr0, LINK
	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
	ld.q	SP, FRAME_S(FSYSCALL_ID), r5
	andi	r5, 0x1ff, r5
	andi	r5, 0x1ff, r5


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


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


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


	if (unlikely(current->audit_context) && entryexit)
	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
		audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
	    tracehook_report_syscall_entry(regs))
				   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));

		/*
		/*
	 * this isn't the same as continuing with a signal, but it will do
		 * Tracing decided this syscall should not happen.
	 * for normal use.  strace only continues with a signal if the
		 * We'll return a bogus call number to get an ENOSYS
	 * stopping signal is not SIGTRAP.  -brl
		 * error, but leave the original number in regs->regs[0].
		 */
		 */
	if (tsk->exit_code) {
		ret = -1L;
		send_sig(tsk->exit_code, tsk, 1);
		tsk->exit_code = 0;
	}


out:
	if (unlikely(current->audit_context))
	if (unlikely(current->audit_context) && !entryexit)
		audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3],
		audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3],
				    regs->regs[4], regs->regs[5],
				    regs->regs[4], regs->regs[5],
				    regs->regs[6], regs->regs[7]);
				    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 Original line Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/syscalls.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/seccomp.h>
#include <linux/tracehook.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <asm/pgtable.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);
	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]);
	secure_computing(regs->regs[9]);


	if (unlikely(current->audit_context) && entryexit)
	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
		audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
	    tracehook_report_syscall_entry(regs))
				   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));

		/*
		/*
	 * this isn't the same as continuing with a signal, but it will do
		 * Tracing decided this syscall should not happen.
	 * for normal use.  strace only continues with a signal if the
		 * We'll return a bogus call number to get an ENOSYS
	 * stopping signal is not SIGTRAP.  -brl
		 * error, but leave the original number in regs->regs[0].
		 */
		 */
	if (tsk->exit_code) {
		ret = -1LL;
		send_sig(tsk->exit_code, tsk, 1);
		tsk->exit_code = 0;
	}


out:
	if (unlikely(current->audit_context))
	if (unlikely(current->audit_context) && !entryexit)
		audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1],
		audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1],
				    regs->regs[2], regs->regs[3],
				    regs->regs[2], regs->regs[3],
				    regs->regs[4], regs->regs[5]);
				    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 */
/* Called with interrupts disabled */
Loading