Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1addc57e authored by Kees Cook's avatar Kees Cook
Browse files

powerpc/ptrace: run seccomp after ptrace



Close the hole where ptrace can change a syscall out from under seccomp.

Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
parent 0208b944
Loading
Loading
Loading
Loading
+23 −21
Original line number Diff line number Diff line
@@ -1788,7 +1788,7 @@ static int do_seccomp(struct pt_regs *regs)

	/*
	 * The syscall was allowed by seccomp, restore the register
	 * state to what ptrace and audit expect.
	 * state to what audit expects.
	 * Note that we use orig_gpr3, which means a seccomp tracer can
	 * modify the first syscall parameter (in orig_gpr3) and also
	 * allow the syscall to proceed.
@@ -1822,22 +1822,25 @@ static inline int do_seccomp(struct pt_regs *regs) { return 0; }
 */
long do_syscall_trace_enter(struct pt_regs *regs)
{
	bool abort = false;

	user_exit();

	if (do_seccomp(regs))
		return -1;

	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
	/*
	 * The tracer may decide to abort the syscall, if so tracehook
	 * will return !0. Note that the tracer may also just change
	 * regs->gpr[0] to an invalid syscall number, that is handled
	 * below on the exit path.
	 */
		abort = tracehook_report_syscall_entry(regs) != 0;
	}
	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
	    tracehook_report_syscall_entry(regs))
		goto skip;

	/* Run seccomp after ptrace; allow it to set gpr[3]. */
	if (do_seccomp(regs))
		return -1;

	/* Avoid trace and audit when syscall is invalid. */
	if (regs->gpr[0] >= NR_syscalls)
		goto skip;

	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
		trace_sys_enter(regs, regs->gpr[0]);
@@ -1854,7 +1857,10 @@ long do_syscall_trace_enter(struct pt_regs *regs)
				    regs->gpr[5] & 0xffffffff,
				    regs->gpr[6] & 0xffffffff);

	if (abort || regs->gpr[0] >= NR_syscalls) {
	/* Return the possibly modified but valid syscall number */
	return regs->gpr[0];

skip:
	/*
	 * If we are aborting explicitly, or if the syscall number is
	 * now invalid, set the return value to -ENOSYS.
@@ -1863,10 +1869,6 @@ long do_syscall_trace_enter(struct pt_regs *regs)
	return -1;
}

	/* Return the possibly modified but valid syscall number */
	return regs->gpr[0];
}

void do_syscall_trace_leave(struct pt_regs *regs)
{
	int step;