Here is the "one swell foop" patch to cut out the old seccomp stuff, clean
up the config, and replace it with the utrace-based one.  The
kernel/seccomp.c patch looks like a patch because it found some trivia in
common, but actually it's wholly replaced with the file I posted before.

I still haven't tested it in the slightest, and only compiled it on x86-64.

This presumably actually ought to be done in several smaller patches.
If it should even be done this way at all.  (That is, eagerly cutting out
the old seccomp and leaving no seccomp option without utrace.)

But here's a completeish proof of concept.  
Maybe someone wants to pick it up.


Thanks,
Roland
---
[PATCH] utraceify seccomp

Signed-off-by: Roland McGrath <rol...@redhat.com>
---
 arch/Kconfig                            |    4 +
 arch/mips/Kconfig                       |   18 +----
 arch/mips/kernel/ptrace.c               |    5 -
 arch/powerpc/Kconfig                    |   18 +----
 arch/powerpc/include/asm/thread_info.h  |    4 +-
 arch/powerpc/kernel/ptrace.c            |    3 -
 arch/sh/Kconfig                         |   17 +----
 arch/sh/include/asm/thread_info.h       |    4 +-
 arch/sh/kernel/ptrace_32.c              |    3 -
 arch/sh/kernel/ptrace_64.c              |    3 -
 arch/sparc/include/asm/thread_info_64.h |    3 +-
 arch/x86/Kconfig                        |   17 +----
 arch/x86/kernel/entry_32.S              |    8 +-
 arch/x86/kernel/ptrace.c                |    4 -
 include/linux/sched.h                   |    2 -
 include/linux/seccomp.h                 |   14 ---
 init/Kconfig                            |   18 ++++
 kernel/seccomp.c                        |  146 ++++++++++++++++++-------------
 18 files changed, 116 insertions(+), 175 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 550dab2..f809f07 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -78,6 +78,10 @@ config HAVE_KPROBES
 config HAVE_KRETPROBES
        bool
 
+# select this if the arch has the asm/seccomp.h file.
+config HAVE_SECCOMP
+       bool
+
 #
 # An arch should select this if it provides all these things:
 #
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 206cb79..b7c124e 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -4,6 +4,7 @@ config MIPS
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_ARCH_KGDB
+       select HAVE_SECCOMP
        # Horrible source of confusion.  Die, die, die ...
        select EMBEDDED
        select RTC_LIB
@@ -1949,23 +1950,6 @@ config KEXEC
          support.  As of this writing the exact hardware interface is
          strongly in flux, so no good recommendation can be made.
 
-config SECCOMP
-       bool "Enable seccomp to safely compute untrusted bytecode"
-       depends on PROC_FS
-       default y
-       help
-         This kernel feature is useful for number crunching applications
-         that may need to compute untrusted bytecode during their
-         execution. By using pipes or other transports made available to
-         the process as file descriptors supporting the read/write
-         syscalls, it's possible to isolate those applications in
-         their own address space using seccomp. Once seccomp is
-         enabled via /proc/<pid>/seccomp, it cannot be disabled
-         and the task is only allowed to execute a few safe syscalls
-         defined by each seccomp mode.
-
-         If unsure, say Y. Only embedded should say N here.
-
 endmenu
 
 config RWSEM_GENERIC_SPINLOCK
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 054861c..2c19cfd 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -24,7 +24,6 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
-#include <linux/seccomp.h>
 
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
@@ -564,10 +563,6 @@ static inline int audit_arch(void)
  */
 asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
-       /* do the secure computing check first */
-       if (!entryexit)
-               secure_computing(regs->regs[0]);
-
        if (unlikely(current->audit_context) && entryexit)
                audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]),
                                   regs->regs[2]);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 74cc312..c71ac02 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -119,6 +119,7 @@ config PPC
        select HAVE_ARCH_KGDB
        select HAVE_KRETPROBES
        select HAVE_ARCH_TRACEHOOK
+       select HAVE_SECCOMP
        select HAVE_LMB
        select HAVE_DMA_ATTRS if PPC64
        select USE_GENERIC_SMP_HELPERS if SMP
@@ -531,23 +532,6 @@ config ARCH_WANTS_FREEZER_CONTROL
 source kernel/power/Kconfig
 endif
 
-config SECCOMP
-       bool "Enable seccomp to safely compute untrusted bytecode"
-       depends on PROC_FS
-       default y
-       help
-         This kernel feature is useful for number crunching applications
-         that may need to compute untrusted bytecode during their
-         execution. By using pipes or other transports made available to
-         the process as file descriptors supporting the read/write
-         syscalls, it's possible to isolate those applications in
-         their own address space using seccomp. Once seccomp is
-         enabled via /proc/<pid>/seccomp, it cannot be disabled
-         and the task is only allowed to execute a few safe syscalls
-         defined by each seccomp mode.
-
-         If unsure, say Y. Only embedded should say N here.
-
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/include/asm/thread_info.h 
b/arch/powerpc/include/asm/thread_info.h
index 9665a26..4d30be8 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -105,7 +105,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
 #define TIF_SINGLESTEP         8       /* singlestepping active */
 #define TIF_MEMDIE             9
-#define TIF_SECCOMP            10      /* secure computing */
 #define TIF_RESTOREALL         11      /* Restore all regs (implies NOERROR) */
 #define TIF_NOERROR            12      /* Force successful syscall return */
 #define TIF_NOTIFY_RESUME      13      /* callback before returning to user */
@@ -123,14 +122,13 @@ static inline struct thread_info 
*current_thread_info(void)
 #define _TIF_PERFMON_CTXSW     (1<<TIF_PERFMON_CTXSW)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
-#define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_RESTOREALL                (1<<TIF_RESTOREALL)
 #define _TIF_NOERROR           (1<<TIF_NOERROR)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_FREEZE            (1<<TIF_FREEZE)
 #define _TIF_RUNLATCH          (1<<TIF_RUNLATCH)
 #define _TIF_ABI_PENDING       (1<<TIF_ABI_PENDING)
-#define _TIF_SYSCALL_T_OR_A    
(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
+#define _TIF_SYSCALL_T_OR_A    (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
 
 #define _TIF_USER_WORK_MASK    (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                                 _TIF_NOTIFY_RESUME)
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 3635be6..f5657c3 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -27,7 +27,6 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/signal.h>
-#include <linux/seccomp.h>
 #include <linux/audit.h>
 #ifdef CONFIG_PPC32
 #include <linux/module.h>
@@ -1021,8 +1020,6 @@ long do_syscall_trace_enter(struct pt_regs *regs)
 {
        long ret = 0;
 
-       secure_computing(regs->gpr[0]);
-
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
            tracehook_report_syscall_entry(regs))
                /*
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index ebabe51..5786e77 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -14,6 +14,7 @@ config SUPERH
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_IOREMAP_PROT if MMU
        select HAVE_ARCH_TRACEHOOK
+       select HAVE_SECCOMP
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
@@ -521,22 +522,6 @@ config CRASH_DUMP
 
          For more details see Documentation/kdump/kdump.txt
 
-config SECCOMP
-       bool "Enable seccomp to safely compute untrusted bytecode"
-       depends on PROC_FS
-       help
-         This kernel feature is useful for number crunching applications
-         that may need to compute untrusted bytecode during their
-         execution. By using pipes or other transports made available to
-         the process as file descriptors supporting the read/write
-         syscalls, it's possible to isolate those applications in
-         their own address space using seccomp. Once seccomp is
-         enabled via prctl, it cannot be disabled and the task is only
-         allowed to execute a few safe syscalls defined by each seccomp
-         mode.
-
-         If unsure, say N.
-
 config SMP
        bool "Symmetric multi-processing support"
        depends on SYS_SUPPORTS_SMP
diff --git a/arch/sh/include/asm/thread_info.h 
b/arch/sh/include/asm/thread_info.h
index f09ac48..e1da51a 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -114,7 +114,6 @@ extern void free_thread_info(struct thread_info *ti);
 #define TIF_RESTORE_SIGMASK    3       /* restore signal mask in do_signal() */
 #define TIF_SINGLESTEP         4       /* singlestepping active */
 #define TIF_SYSCALL_AUDIT      5       /* syscall auditing active */
-#define TIF_SECCOMP            6       /* secure computing */
 #define TIF_NOTIFY_RESUME      7       /* callback before returning to user */
 #define TIF_USEDFPU            16      /* FPU was used by this task this 
quantum (SMP) */
 #define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling 
TIF_NEED_RESCHED */
@@ -127,7 +126,6 @@ extern void free_thread_info(struct thread_info *ti);
 #define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
-#define _TIF_SECCOMP           (1 << TIF_SECCOMP)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_USEDFPU           (1 << TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
@@ -141,7 +139,7 @@ extern void free_thread_info(struct thread_info *ti);
 
 /* work to do in syscall trace */
 #define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
-                                _TIF_SYSCALL_AUDIT | _TIF_SECCOMP)
+                                _TIF_SYSCALL_AUDIT)
 
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK      (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING      | \
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 29ca09d..c83d0fe 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -22,7 +22,6 @@
 #include <linux/signal.h>
 #include <linux/io.h>
 #include <linux/audit.h>
-#include <linux/seccomp.h>
 #include <linux/tracehook.h>
 #include <linux/elf.h>
 #include <linux/regset.h>
@@ -438,8 +437,6 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
 {
        long ret = 0;
 
-       secure_computing(regs->regs[0]);
-
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
            tracehook_report_syscall_entry(regs))
                /*
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c
index 6950974..e65dbe0 100644
--- a/arch/sh/kernel/ptrace_64.c
+++ b/arch/sh/kernel/ptrace_64.c
@@ -27,7 +27,6 @@
 #include <linux/signal.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
-#include <linux/seccomp.h>
 #include <linux/tracehook.h>
 #include <linux/elf.h>
 #include <linux/regset.h>
@@ -427,8 +426,6 @@ asmlinkage long long do_syscall_trace_enter(struct pt_regs 
*regs)
 {
        long long ret = 0;
 
-       secure_computing(regs->regs[9]);
-
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
            tracehook_report_syscall_entry(regs))
                /*
diff --git a/arch/sparc/include/asm/thread_info_64.h 
b/arch/sparc/include/asm/thread_info_64.h
index 639ac80..b303b93 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -227,7 +227,7 @@ register struct thread_info *current_thread_info_reg 
asm("g6");
 /* flag bit 6 is available */
 #define TIF_32BIT              7       /* 32-bit binary */
 /* flag bit 8 is available */
-#define TIF_SECCOMP            9       /* secure computing */
+/* flag bit 9 is available */
 #define TIF_SYSCALL_AUDIT      10      /* syscall auditing active */
 /* flag bit 11 is available */
 /* NOTE: Thread flags >= 12 should be ones we have no interest
@@ -246,7 +246,6 @@ register struct thread_info *current_thread_info_reg 
asm("g6");
 #define _TIF_PERFCTR           (1<<TIF_PERFCTR)
 #define _TIF_UNALIGNED         (1<<TIF_UNALIGNED)
 #define _TIF_32BIT             (1<<TIF_32BIT)
-#define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_ABI_PENDING       (1<<TIF_ABI_PENDING)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bc2fbad..25ec433 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -37,6 +37,7 @@ config X86
        select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && 
!X86_NUMAQ) || X86_64)
        select HAVE_ARCH_KGDB if !X86_VOYAGER
        select HAVE_ARCH_TRACEHOOK
+       select HAVE_SECCOMP
        select HAVE_GENERIC_DMA_COHERENT if X86_32
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
        select USER_STACKTRACE_SUPPORT
@@ -1324,22 +1325,6 @@ config EFI
        resultant kernel should continue to boot on existing non-EFI
        platforms.
 
-config SECCOMP
-       def_bool y
-       prompt "Enable seccomp to safely compute untrusted bytecode"
-       help
-         This kernel feature is useful for number crunching applications
-         that may need to compute untrusted bytecode during their
-         execution. By using pipes or other transports made available to
-         the process as file descriptors supporting the read/write
-         syscalls, it's possible to isolate those applications in
-         their own address space using seccomp. Once seccomp is
-         enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
-         and the task is only allowed to execute a few safe syscalls
-         defined by each seccomp mode.
-
-         If unsure, say Y. Only embedded should say N here.
-
 config CC_STACKPROTECTOR
        bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
        depends on X86_64 && EXPERIMENTAL && BROKEN
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 4646902..21e7046 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -341,8 +341,7 @@ sysenter_past_esp:
 
        GET_THREAD_INFO(%ebp)
 
-       /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not 
testb */
-       testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+       testb $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
        jnz sysenter_audit
 sysenter_do_call:
        cmpl $(nr_syscalls), %eax
@@ -366,7 +365,7 @@ sysenter_exit:
 
 #ifdef CONFIG_AUDITSYSCALL
 sysenter_audit:
-       testw $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+       testb $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
        jnz syscall_trace_entry
        addl $4,%esp
        CFI_ADJUST_CFA_OFFSET -4
@@ -420,8 +419,7 @@ ENTRY(system_call)
        SAVE_ALL
        GET_THREAD_INFO(%ebp)
                                        # system call tracing in operation / 
emulation
-       /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not 
testb */
-       testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+       testb $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
        jnz syscall_trace_entry
        cmpl $(nr_syscalls), %eax
        jae syscall_badsys
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 06ca07f..0d6bcff 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -19,7 +19,6 @@
 #include <linux/elf.h>
 #include <linux/security.h>
 #include <linux/audit.h>
-#include <linux/seccomp.h>
 #include <linux/signal.h>
 
 #include <asm/uaccess.h>
@@ -1411,9 +1410,6 @@ asmregparm long syscall_trace_enter(struct pt_regs *regs)
        if (test_thread_flag(TIF_SINGLESTEP))
                regs->flags |= X86_EFLAGS_TF;
 
-       /* do the secure computing check first */
-       secure_computing(regs->orig_ax);
-
        if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
                ret = -1L;
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 786ef2d..4a22d98 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -76,7 +76,6 @@ struct sched_param {
 #include <linux/percpu.h>
 #include <linux/topology.h>
 #include <linux/proportions.h>
-#include <linux/seccomp.h>
 #include <linux/rcupdate.h>
 #include <linux/rtmutex.h>
 
@@ -1286,7 +1285,6 @@ struct task_struct {
        uid_t loginuid;
        unsigned int sessionid;
 #endif
-       seccomp_t seccomp;
 
 #ifdef CONFIG_UTRACE
        struct utrace utrace;
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 262a8dc..02d7adb 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -4,27 +4,13 @@
 
 #ifdef CONFIG_SECCOMP
 
-#include <linux/thread_info.h>
 #include <asm/seccomp.h>
 
-typedef struct { int mode; } seccomp_t;
-
-extern void __secure_computing(int);
-static inline void secure_computing(int this_syscall)
-{
-       if (unlikely(test_thread_flag(TIF_SECCOMP)))
-               __secure_computing(this_syscall);
-}
-
 extern long prctl_get_seccomp(void);
 extern long prctl_set_seccomp(unsigned long);
 
 #else /* CONFIG_SECCOMP */
 
-typedef struct { } seccomp_t;
-
-#define secure_computing(x) do { } while (0)
-
 static inline long prctl_get_seccomp(void)
 {
        return -EINVAL;
diff --git a/init/Kconfig b/init/Kconfig
index 4b5ab3e..bc90ad3 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1069,6 +1069,24 @@ menuconfig UTRACE
          kernel interface exported to kernel modules, to track events in
          user threads, extract and change user thread state.
 
+config SECCOMP
+       bool "Enable seccomp to safely compute untrusted bytecode"
+       default y if UTRACE
+       depends on UTRACE
+       depends on HAVE_SECCOMP
+       help
+         This kernel feature is useful for number crunching applications
+         that may need to compute untrusted bytecode during their
+         execution. By using pipes or other transports made available to
+         the process as file descriptors supporting the read/write
+         syscalls, it's possible to isolate those applications in
+         their own address space using seccomp. Once seccomp is
+         enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+         and the task is only allowed to execute a few safe syscalls
+         defined by each seccomp mode.
+
+         If unsure, say Y. Only embedded should say N here.
+
 source "block/Kconfig"
 
 config PREEMPT_NOTIFIERS
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 57d4b13..f14d1fd 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1,86 +1,108 @@
-/*
- * linux/kernel/seccomp.c
- *
- * Copyright 2004-2005  Andrea Arcangeli <and...@cpushare.com>
- *
- * This defines a simple but solid secure-computing mode.
- */
-
 #include <linux/seccomp.h>
-#include <linux/sched.h>
+#include <linux/utrace.h>
+#include <linux/signal.h>
+#include <linux/err.h>
 #include <linux/compat.h>
-
-/* #define SECCOMP_DEBUG 1 */
-#define NR_SECCOMP_MODES 1
+#include <linux/prctl.h>
+#include <asm/syscall.h>
 
 /*
- * Secure computing mode 1 allows only read/write/exit/sigreturn.
- * To be fully secure this must be combined with rlimit
- * to limit the stack allocations too.
+ * If it's an accepted syscall, run it normally.
+ * If not, send ourselves a SIGKILL and abort the syscall.
  */
-static int mode1_syscalls[] = {
-       __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, 
__NR_seccomp_sigreturn,
-       0, /* null terminated */
-};
+static u32 secure_syscall_entry(u32 action,
+                               struct utrace_engine *engine,
+                               struct task_struct *task,
+                               struct pt_regs *regs)
+{
+       int callno = syscall_get_nr(task, regs);
 
 #ifdef CONFIG_COMPAT
-static int mode1_syscalls_32[] = {
-       __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, 
__NR_seccomp_sigreturn_32,
-       0, /* null terminated */
-};
+       if (is_compat_task())
+               switch (callno) {
+               case __NR_seccomp_read_32:
+               case __NR_seccomp_write_32:
+               case __NR_seccomp_exit_32:
+               case __NR_seccomp_sigreturn_32:
+                       return UTRACE_RESUME | UTRACE_SYSCALL_RUN;
+               }
+       else
 #endif
+               switch (callno) {
+               case __NR_seccomp_read:
+               case __NR_seccomp_write:
+               case __NR_seccomp_exit:
+               case __NR_seccomp_sigreturn:
+                       return UTRACE_RESUME | UTRACE_SYSCALL_RUN;
+               }
 
-void __secure_computing(int this_syscall)
+       force_sig(SIGKILL, task);
+       return UTRACE_RESUME | UTRACE_SYSCALL_ABORT;
+}
+
+static const struct utrace_engine_ops secure_syscall_ops =
 {
-       int mode = current->seccomp.mode;
-       int * syscall;
+       .report_syscall_entry = secure_syscall_entry
+};
 
-       switch (mode) {
-       case 1:
-               syscall = mode1_syscalls;
-#ifdef CONFIG_COMPAT
-               if (is_compat_task())
-                       syscall = mode1_syscalls_32;
-#endif
-               do {
-                       if (*syscall == this_syscall)
-                               return;
-               } while (*++syscall);
-               break;
-       default:
-               BUG();
+/*
+ * Set up a utrace engine to call secure_syscall_entry() for each system call.
+ * Also act like prctl(PR_SET_TSC, PR_TSC_SIGSEGV).
+ */
+static int enable_secure_syscall(void)
+{
+       struct utrace_engine *engine;
+       int ret;
+
+       engine = utrace_attach_task(current,
+                                   UTRACE_ATTACH_CREATE |
+                                   UTRACE_ATTACH_EXCLUSIVE |
+                                   UTRACE_ATTACH_MATCH_OPS,
+                                   &secure_syscall_ops, NULL);
+       if (IS_ERR(engine)) {
+               ret = PTR_ERR(engine);
+               return ret == -EEXIST ? -EPERM : ret;
        }
 
-#ifdef SECCOMP_DEBUG
-       dump_stack();
+       ret = utrace_set_events(current, engine, UTRACE_EVENT(SYSCALL_ENTRY));
+       WARN_ON(ret);           /* Should never happen on current.  */
+
+       /*
+        * This is the only outside ref on the engine.
+        * The engine dies automatically when this task gets reaped.
+        */
+       utrace_engine_put(engine);
+
+#ifdef SET_TSC_CTL
+       if (!ret)
+               SET_TSC_CTL(PR_TSC_SIGSEGV);
 #endif
-       do_exit(SIGKILL);
+
+       return ret;
 }
 
 long prctl_get_seccomp(void)
 {
-       return current->seccomp.mode;
+       struct utrace_engine *engine = utrace_attach_task(
+               current, UTRACE_ATTACH_MATCH_OPS, &secure_syscall_ops, NULL);
+
+       if (engine == ERR_PTR(-ENOENT))
+               return 0;
+
+       if (!IS_ERR(engine))
+               /*
+                * I wonder how he managed to call prctl() with it enabled.
+                * That should be impossible.
+                */
+               return 1;
+
+       return PTR_ERR(engine);
 }
 
 long prctl_set_seccomp(unsigned long seccomp_mode)
 {
-       long ret;
-
-       /* can set it only once to be even more secure */
-       ret = -EPERM;
-       if (unlikely(current->seccomp.mode))
-               goto out;
-
-       ret = -EINVAL;
-       if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
-               current->seccomp.mode = seccomp_mode;
-               set_thread_flag(TIF_SECCOMP);
-#ifdef TIF_NOTSC
-               disable_TSC();
-#endif
-               ret = 0;
-       }
+       if (seccomp_mode != 1)
+               return -EINVAL;
 
- out:
-       return ret;
+       return enable_secure_syscall();
 }

Reply via email to