File Index
Files and directories
Sign in
FILE

syscall-common.c

File preview with syntax highlighting.

linux-6.19.14/kernel/entry/syscall-common.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <linux/audit.h>
  4#include <linux/entry-common.h>
  5#include "common.h"
  6
  7#define CREATE_TRACE_POINTS
  8#include <trace/events/syscalls.h>
  9
 10static inline void syscall_enter_audit(struct pt_regs *regs, long syscall)
 11{
 12	if (unlikely(audit_context())) {
 13		unsigned long args[6];
 14
 15		syscall_get_arguments(current, regs, args);
 16		audit_syscall_entry(syscall, args[0], args[1], args[2], args[3]);
 17	}
 18}
 19
 20long syscall_trace_enter(struct pt_regs *regs, long syscall,
 21				unsigned long work)
 22{
 23	long ret = 0;
 24
 25	/*
 26	 * Handle Syscall User Dispatch.  This must comes first, since
 27	 * the ABI here can be something that doesn't make sense for
 28	 * other syscall_work features.
 29	 */
 30	if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) {
 31		if (syscall_user_dispatch(regs))
 32			return -1L;
 33	}
 34
 35	/* Handle ptrace */
 36	if (work & (SYSCALL_WORK_SYSCALL_TRACE | SYSCALL_WORK_SYSCALL_EMU)) {
 37		ret = ptrace_report_syscall_entry(regs);
 38		if (ret || (work & SYSCALL_WORK_SYSCALL_EMU))
 39			return -1L;
 40	}
 41
 42	/* Do seccomp after ptrace, to catch any tracer changes. */
 43	if (work & SYSCALL_WORK_SECCOMP) {
 44		ret = __secure_computing();
 45		if (ret == -1L)
 46			return ret;
 47	}
 48
 49	/* Either of the above might have changed the syscall number */
 50	syscall = syscall_get_nr(current, regs);
 51
 52	if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT)) {
 53		trace_sys_enter(regs, syscall);
 54		/*
 55		 * Probes or BPF hooks in the tracepoint may have changed the
 56		 * system call number as well.
 57		 */
 58		syscall = syscall_get_nr(current, regs);
 59	}
 60
 61	syscall_enter_audit(regs, syscall);
 62
 63	return ret ? : syscall;
 64}
 65
 66/*
 67 * If SYSCALL_EMU is set, then the only reason to report is when
 68 * SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP).  This syscall
 69 * instruction has been already reported in syscall_enter_from_user_mode().
 70 */
 71static inline bool report_single_step(unsigned long work)
 72{
 73	if (work & SYSCALL_WORK_SYSCALL_EMU)
 74		return false;
 75
 76	return work & SYSCALL_WORK_SYSCALL_EXIT_TRAP;
 77}
 78
 79void syscall_exit_work(struct pt_regs *regs, unsigned long work)
 80{
 81	bool step;
 82
 83	/*
 84	 * If the syscall was rolled back due to syscall user dispatching,
 85	 * then the tracers below are not invoked for the same reason as
 86	 * the entry side was not invoked in syscall_trace_enter(): The ABI
 87	 * of these syscalls is unknown.
 88	 */
 89	if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) {
 90		if (unlikely(current->syscall_dispatch.on_dispatch)) {
 91			current->syscall_dispatch.on_dispatch = false;
 92			return;
 93		}
 94	}
 95
 96	audit_syscall_exit(regs);
 97
 98	if (work & SYSCALL_WORK_SYSCALL_TRACEPOINT)
 99		trace_sys_exit(regs, syscall_get_return_value(current, regs));
100
101	step = report_single_step(work);
102	if (step || work & SYSCALL_WORK_SYSCALL_TRACE)
103		ptrace_report_syscall_exit(regs, step);
104}
~/ Read-only file preview.