diff mbox

[09/11] powerpc/kernel: Enable seccomp filter

Message ID 1437646871-3195-9-git-send-email-mpe@ellerman.id.au (mailing list archive)
State Superseded
Delegated to: Michael Ellerman
Headers show

Commit Message

Michael Ellerman July 23, 2015, 10:21 a.m. UTC
This commit enables seccomp filter on powerpc, now that we have all the
necessary pieces in place.

To support seccomp's desire to modify the syscall return value under
some circumstances, we use a different ABI to the ptrace ABI. That is we
use r3 as the syscall return value, and orig_gpr3 is the first syscall
parameter.

This means the seccomp code, or a ptracer via SECCOMP_RET_TRACE, will
see -ENOSYS preloaded in r3. This is identical to the behaviour on x86,
and allows seccomp or the ptracer to either leave the -ENOSYS or change
it to something else, as well as rejecting or not the syscall by
modifying r0.

If seccomp does not reject the syscall, we restore the register state to
match what ptrace and audit expect, ie. r3 is the first syscall
parameter again. We do this restore using orig_gpr3, which may have been
modified by seccomp, which allows seccomp to modify the first syscall
paramater and allow the syscall to proceed.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/Kconfig         |  1 +
 arch/powerpc/kernel/ptrace.c | 28 +++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

Comments

Kees Cook July 27, 2015, 6:56 p.m. UTC | #1
On Thu, Jul 23, 2015 at 3:21 AM, Michael Ellerman <mpe@ellerman.id.au> wrote:
> This commit enables seccomp filter on powerpc, now that we have all the
> necessary pieces in place.
>
> To support seccomp's desire to modify the syscall return value under
> some circumstances, we use a different ABI to the ptrace ABI. That is we
> use r3 as the syscall return value, and orig_gpr3 is the first syscall
> parameter.
>
> This means the seccomp code, or a ptracer via SECCOMP_RET_TRACE, will
> see -ENOSYS preloaded in r3. This is identical to the behaviour on x86,
> and allows seccomp or the ptracer to either leave the -ENOSYS or change
> it to something else, as well as rejecting or not the syscall by
> modifying r0.
>
> If seccomp does not reject the syscall, we restore the register state to
> match what ptrace and audit expect, ie. r3 is the first syscall
> parameter again. We do this restore using orig_gpr3, which may have been
> modified by seccomp, which allows seccomp to modify the first syscall
> paramater and allow the syscall to proceed.
>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

Reviewed-by: Kees Cook <keescook@chromium.org>

-Kees

> ---
>  arch/powerpc/Kconfig         |  1 +
>  arch/powerpc/kernel/ptrace.c | 28 +++++++++++++++++++++++++++-
>  2 files changed, 28 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 5ef27113b898..b6cb6a87b7a2 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -155,6 +155,7 @@ config PPC
>         select HAVE_PERF_EVENTS_NMI if PPC64
>         select EDAC_SUPPORT
>         select EDAC_ATOMIC_SCRUB
> +       select HAVE_ARCH_SECCOMP_FILTER
>
>  config GENERIC_CSUM
>         def_bool CPU_LITTLE_ENDIAN
> diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
> index 7484221bb3f8..de79eb5218c6 100644
> --- a/arch/powerpc/kernel/ptrace.c
> +++ b/arch/powerpc/kernel/ptrace.c
> @@ -1787,7 +1787,33 @@ long do_syscall_trace_enter(struct pt_regs *regs)
>
>         user_exit();
>
> -       secure_computing_strict(regs->gpr[0]);
> +       if (test_thread_flag(TIF_SECCOMP)) {
> +               /*
> +                * The ABI we present to seccomp tracers is that r3 contains
> +                * the syscall return value and orig_gpr3 contains the first
> +                * syscall parameter. This is different to the ptrace ABI where
> +                * both r3 and orig_gpr3 contain the first syscall parameter.
> +                */
> +               regs->gpr[3] = -ENOSYS;
> +
> +               /*
> +                * We use the __ version here because we have already checked
> +                * TIF_SECCOMP. If this fails, there is nothing left to do, we
> +                * have already loaded -ENOSYS into r3, or seccomp has put
> +                * something else in r3 (via SECCOMP_RET_ERRNO/TRACE).
> +                */
> +               if (__secure_computing())
> +                       return -1;
> +
> +               /*
> +                * The syscall was allowed by seccomp, restore the register
> +                * state to what ptrace and audit expect.
> +                * 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.
> +                */
> +               regs->gpr[3] = regs->orig_gpr3;
> +       }
>
>         if (test_thread_flag(TIF_SYSCALL_TRACE)) {
>                 /*
> --
> 2.1.0
>
diff mbox

Patch

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 5ef27113b898..b6cb6a87b7a2 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -155,6 +155,7 @@  config PPC
 	select HAVE_PERF_EVENTS_NMI if PPC64
 	select EDAC_SUPPORT
 	select EDAC_ATOMIC_SCRUB
+	select HAVE_ARCH_SECCOMP_FILTER
 
 config GENERIC_CSUM
 	def_bool CPU_LITTLE_ENDIAN
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 7484221bb3f8..de79eb5218c6 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1787,7 +1787,33 @@  long do_syscall_trace_enter(struct pt_regs *regs)
 
 	user_exit();
 
-	secure_computing_strict(regs->gpr[0]);
+	if (test_thread_flag(TIF_SECCOMP)) {
+		/*
+		 * The ABI we present to seccomp tracers is that r3 contains
+		 * the syscall return value and orig_gpr3 contains the first
+		 * syscall parameter. This is different to the ptrace ABI where
+		 * both r3 and orig_gpr3 contain the first syscall parameter.
+		 */
+		regs->gpr[3] = -ENOSYS;
+
+		/*
+		 * We use the __ version here because we have already checked
+		 * TIF_SECCOMP. If this fails, there is nothing left to do, we
+		 * have already loaded -ENOSYS into r3, or seccomp has put
+		 * something else in r3 (via SECCOMP_RET_ERRNO/TRACE).
+		 */
+		if (__secure_computing())
+			return -1;
+
+		/*
+		 * The syscall was allowed by seccomp, restore the register
+		 * state to what ptrace and audit expect.
+		 * 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.
+		 */
+		regs->gpr[3] = regs->orig_gpr3;
+	}
 
 	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
 		/*