powerpc/ptrace: run seccomp after ptrace
Close the hole where ptrace can change a syscall out from under seccomp. Signed-off-by: Kees 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
This commit is contained in:
parent
0208b9445b
commit
1addc57e11
|
@ -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; }
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue