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

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
...@@ -1788,7 +1788,7 @@ static int do_seccomp(struct pt_regs *regs) ...@@ -1788,7 +1788,7 @@ static int do_seccomp(struct pt_regs *regs)
/* /*
* The syscall was allowed by seccomp, restore the register * 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 * Note that we use orig_gpr3, which means a seccomp tracer can
* modify the first syscall parameter (in orig_gpr3) and also * modify the first syscall parameter (in orig_gpr3) and also
* allow the syscall to proceed. * allow the syscall to proceed.
...@@ -1822,22 +1822,25 @@ static inline int do_seccomp(struct pt_regs *regs) { return 0; } ...@@ -1822,22 +1822,25 @@ static inline int do_seccomp(struct pt_regs *regs) { return 0; }
*/ */
long do_syscall_trace_enter(struct pt_regs *regs) long do_syscall_trace_enter(struct pt_regs *regs)
{ {
bool abort = false;
user_exit(); user_exit();
/*
* 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.
*/
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)) if (do_seccomp(regs))
return -1; return -1;
if (test_thread_flag(TIF_SYSCALL_TRACE)) { /* Avoid trace and audit when syscall is invalid. */
/* if (regs->gpr[0] >= NR_syscalls)
* The tracer may decide to abort the syscall, if so tracehook goto skip;
* 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 (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_enter(regs, regs->gpr[0]); trace_sys_enter(regs, regs->gpr[0]);
...@@ -1854,17 +1857,16 @@ long do_syscall_trace_enter(struct pt_regs *regs) ...@@ -1854,17 +1857,16 @@ long do_syscall_trace_enter(struct pt_regs *regs)
regs->gpr[5] & 0xffffffff, regs->gpr[5] & 0xffffffff,
regs->gpr[6] & 0xffffffff); regs->gpr[6] & 0xffffffff);
if (abort || regs->gpr[0] >= NR_syscalls) {
/*
* If we are aborting explicitly, or if the syscall number is
* now invalid, set the return value to -ENOSYS.
*/
regs->gpr[3] = -ENOSYS;
return -1;
}
/* Return the possibly modified but valid syscall number */ /* Return the possibly modified but valid syscall number */
return regs->gpr[0]; return regs->gpr[0];
skip:
/*
* If we are aborting explicitly, or if the syscall number is
* now invalid, set the return value to -ENOSYS.
*/
regs->gpr[3] = -ENOSYS;
return -1;
} }
void do_syscall_trace_leave(struct pt_regs *regs) void do_syscall_trace_leave(struct pt_regs *regs)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment