}
}
+static void update_syscall_orig_x0_after_ptrace(struct pt_regs *regs)
+{
+ /*
+ * Keep orig_x0 authoritative so that seccomp (via
+ * syscall_get_arguments()), audit and the restart path all see the same
+ * first argument the syscall is dispatched with, even if it has been
+ * updated by a tracer. Skip this for NO_SYSCALL (set either by the user
+ * or the tracer), as regs[0] holds the return value (see the comment in
+ * el0_svc_common()) and can be unwound using syscall_rollback().
+ * For compat tasks, orig_r0 is provided directly through GPR index 17.
+ */
+ if (!is_compat_task() && regs->syscallno != NO_SYSCALL)
+ regs->orig_x0 = regs->regs[0];
+}
+
int syscall_trace_enter(struct pt_regs *regs)
{
unsigned long flags = read_thread_flags();
ret = report_syscall_entry(regs);
if (ret || (flags & _TIF_SYSCALL_EMU))
return NO_SYSCALL;
+
+ /*
+ * Ensure ptrace changes to x0 during a regular
+ * syscall-enter-stop (PTRACE_SYSCALL) are visible to
+ * subsequent seccomp checks, tracepoints and audit.
+ */
+ update_syscall_orig_x0_after_ptrace(regs);
}
/* Do the secure computing after ptrace; failures should be fast. */
if (secure_computing() == -1)
return NO_SYSCALL;
+ /*
+ * Ensure tracer changes to x0 during seccomp ptrace exit
+ * processing (SECCOMP_RET_TRACE) are visible to tracepoints and
+ * audit.
+ */
+ update_syscall_orig_x0_after_ptrace(regs);
+
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, regs->syscallno);