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 int syscall_trace(int dir, struct pt_regs *regs) { unsigned long saved_reg; if (!test_thread_flag(TIF_SYSCALL_TRACE)) return regs->syscallno; if (is_compat_task()) { /* AArch32 uses ip (r12) for scratch */ saved_reg = regs->regs[12]; regs->regs[12] = dir; } else { /* * Save X7. X7 is used to denote syscall entry/exit: * X7 = 0 -> entry, = 1 -> exit */ saved_reg = regs->regs[7]; regs->regs[7] = dir; } if (dir) tracehook_report_syscall_exit(regs, 0); else if (tracehook_report_syscall_entry(regs)) regs->syscallno = ~0UL; if (is_compat_task()) regs->regs[12] = saved_reg; else regs->regs[7] = saved_reg; return regs->syscallno; }
void do_syscall_trace_exit(struct pt_regs *regs) { int stepping = test_thread_flag(TIF_SINGLESTEP) || test_thread_flag(TIF_BLOCKSTEP); if (stepping || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, stepping); }
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); }
asmlinkage void syscall_trace_leave(struct pt_regs *regs) { int step; step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); }
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)); }
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) { int step; if (unlikely(current->audit_context)) audit_syscall_exit(AUDITSC_RESULT(regs->r3), regs->r3); step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); }
asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p) { int ret = 0; if (test_thread_flag(TIF_SYSCALL_TRACE)) { if (syscall_exit_p) tracehook_report_syscall_exit(regs, 0); else ret = tracehook_report_syscall_entry(regs); } return ret; }
/* * 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); }
void syscall_trace_leave(struct pt_regs *regs) { int ptraced = current->ptrace; audit_syscall_exit(regs); /* Fake a debug trap */ if (ptraced & PT_DTRACE) send_sigtrap(current, ®s->regs, 0); if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; tracehook_report_syscall_exit(regs, 0); /* force do_signal() --> is_syscall() */ if (ptraced & PT_PTRACED) set_thread_flag(TIF_SIGPENDING); }
/* * 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(); }
static void tracehook_report_syscall(struct pt_regs *regs, enum ptrace_syscall_dir dir) { int regno; unsigned long saved_reg; /* * A scratch register (ip(r12) on AArch32, x7 on AArch64) is * used to denote syscall entry/exit: */ regno = (is_compat_task() ? 12 : 7); saved_reg = regs->regs[regno]; regs->regs[regno] = dir; if (dir == PTRACE_SYSCALL_EXIT) tracehook_report_syscall_exit(regs, 0); else if (tracehook_report_syscall_entry(regs)) regs->syscallno = ~0UL; regs->regs[regno] = saved_reg; }
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); }
asmlinkage void syscall_trace_exit(struct pt_regs *regs) { tracehook_report_syscall_exit(regs, 0); }