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();
if (do_seccomp(regs))
return -1;
if (test_thread_flag(TIF_SYSCALL_TRACE)) {
/* /*
* The tracer may decide to abort the syscall, if so tracehook * The tracer may decide to abort the syscall, if so tracehook
* will return !0. Note that the tracer may also just change * will return !0. Note that the tracer may also just change
* regs->gpr[0] to an invalid syscall number, that is handled * regs->gpr[0] to an invalid syscall number, that is handled
* below on the exit path. * 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))) 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) { /* Return the possibly modified but valid syscall number */
return regs->gpr[0];
skip:
/* /*
* If we are aborting explicitly, or if the syscall number is * If we are aborting explicitly, or if the syscall number is
* now invalid, set the return value to -ENOSYS. * now invalid, set the return value to -ENOSYS.
*/ */
regs->gpr[3] = -ENOSYS; regs->gpr[3] = -ENOSYS;
return -1; return -1;
}
/* Return the possibly modified but valid syscall number */
return regs->gpr[0];
} }
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