powerpc/kernel: Enable seccomp filter
[firefly-linux-kernel-4.4.55.git] / arch / powerpc / kernel / ptrace.c
index 7484221bb3f8fa3fcfb3b3a4323722fd9afe2a20..737c0d0b53ac43dcdc41f09b0a3177cf8b4e389b 100644 (file)
@@ -1762,6 +1762,44 @@ long arch_ptrace(struct task_struct *child, long request,
        return ret;
 }
 
+#ifdef CONFIG_SECCOMP
+static int do_seccomp(struct pt_regs *regs)
+{
+       if (!test_thread_flag(TIF_SECCOMP))
+               return 0;
+
+       /*
+        * 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;
+
+       return 0;
+}
+#else
+static inline int do_seccomp(struct pt_regs *regs) { return 0; }
+#endif /* CONFIG_SECCOMP */
+
 /**
  * do_syscall_trace_enter() - Do syscall tracing on kernel entry.
  * @regs: the pt_regs of the task to trace (current)
@@ -1787,7 +1825,8 @@ long do_syscall_trace_enter(struct pt_regs *regs)
 
        user_exit();
 
-       secure_computing_strict(regs->gpr[0]);
+       if (do_seccomp(regs))
+               return -1;
 
        if (test_thread_flag(TIF_SYSCALL_TRACE)) {
                /*