Example #1
0
void do_syscall_trace_exit(struct pt_regs *regs)
{
	long errno;

	/*
	 * We may come here right after calling schedule_user()
	 * in which case we can be in RCU user mode.
	 */
	user_exit();

	/*
	 * The standard tile calling convention returns the value (or negative
	 * errno) in r0, and zero (or positive errno) in r1.
	 * It saves a couple of cycles on the hot path to do this work in
	 * registers only as we return, rather than updating the in-memory
	 * struct ptregs.
	 */
	errno = (long) regs->regs[0];
	if (errno < 0 && errno > -4096)
		regs->regs[1] = -errno;
	else
		regs->regs[1] = 0;

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

	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
		trace_sys_exit(regs, regs->regs[0]);
}
asmlinkage void syscall_trace_exit(struct pt_regs *regs)
{
	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
		trace_sys_exit(regs, regs_return_value(regs));

	if (test_thread_flag(TIF_SYSCALL_TRACE))
		tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
}
Example #3
0
void syscall_trace_leave(struct pt_regs *regs)
{
	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
		trace_sys_exit(regs, regs->ctx.DX[0].U1);

	if (test_thread_flag(TIF_SYSCALL_TRACE))
		tracehook_report_syscall_exit(regs, 0);
}
Example #4
0
asmlinkage void syscall_trace_exit(struct pt_regs *regs)
{
	audit_syscall_exit(regs);

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

	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
		trace_sys_exit(regs, syscall_get_return_value(current, regs));
}
Example #5
0
/*
 * Called with IRQs on and fully valid regs.  Returns with IRQs off in a
 * state such that we can immediately switch to user mode.
 */
__visible void syscall_return_slowpath(struct pt_regs *regs)
{
    struct thread_info *ti = pt_regs_to_thread_info(regs);
    u32 cached_flags = READ_ONCE(ti->flags);
    bool step;

    CT_WARN_ON(ct_state() != CONTEXT_KERNEL);

    if (WARN(irqs_disabled(), "syscall %ld left IRQs disabled",
             regs->orig_ax))
        local_irq_enable();

    /*
     * First do one-time work.  If these work items are enabled, we
     * want to run them exactly once per syscall exit with IRQs on.
     */
    if (cached_flags & (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT |
                        _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT)) {
        audit_syscall_exit(regs);

        if (cached_flags & _TIF_SYSCALL_TRACEPOINT)
            trace_sys_exit(regs, regs->ax);

        /*
         * If TIF_SYSCALL_EMU is set, we only get here because of
         * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP).
         * We already reported this syscall instruction in
         * syscall_trace_enter().
         */
        step = unlikely(
                   (cached_flags & (_TIF_SINGLESTEP | _TIF_SYSCALL_EMU))
                   == _TIF_SINGLESTEP);
        if (step || cached_flags & _TIF_SYSCALL_TRACE)
            tracehook_report_syscall_exit(regs, step);
    }

#ifdef CONFIG_COMPAT
    /*
     * Compat syscalls set TS_COMPAT.  Make sure we clear it before
     * returning to user mode.
     */
    ti->status &= ~TS_COMPAT;
#endif

    local_irq_disable();
    prepare_exit_to_usermode(regs);
}
Example #6
0
/*
 * Notification of system call entry/exit
 * - triggered by current->work.syscall_trace
 */
asmlinkage void syscall_trace_leave(struct pt_regs *regs)
{
        /*
	 * We may come here right after calling schedule_user()
	 * or do_notify_resume(), in which case we can be in RCU
	 * user mode.
	 */
	user_exit();

	audit_syscall_exit(regs);

	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
		trace_sys_exit(regs, regs_return_value(regs));

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

	user_enter();
}
Example #7
0
static void syscall_slow_exit_work(struct pt_regs *regs, u32 cached_flags)
{
	bool step;

	audit_syscall_exit(regs);

	if (cached_flags & _TIF_SYSCALL_TRACEPOINT)
		trace_sys_exit(regs, regs->ax);

	/*
	 * If TIF_SYSCALL_EMU is set, we only get here because of
	 * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP).
	 * We already reported this syscall instruction in
	 * syscall_trace_enter().
	 */
	step = unlikely(
		(cached_flags & (_TIF_SINGLESTEP | _TIF_SYSCALL_EMU))
		== _TIF_SINGLESTEP);
	if (step || cached_flags & _TIF_SYSCALL_TRACE)
		tracehook_report_syscall_exit(regs, step);
}