]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'seccomp-next' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux...
authorJames Morris <james.l.morris@oracle.com>
Mon, 20 Jul 2015 07:19:19 +0000 (17:19 +1000)
committerJames Morris <james.l.morris@oracle.com>
Mon, 20 Jul 2015 07:19:19 +0000 (17:19 +1000)
include/linux/ptrace.h
include/linux/seccomp.h
include/uapi/linux/ptrace.h
kernel/ptrace.c
kernel/seccomp.c

index 987a73a40ef8465ee8290f1ab628bf4c70ae58f8..061265f9287676afce057892572222a477a47505 100644 (file)
@@ -34,6 +34,7 @@
 #define PT_TRACE_SECCOMP       PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP)
 
 #define PT_EXITKILL            (PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT)
+#define PT_SUSPEND_SECCOMP     (PTRACE_O_SUSPEND_SECCOMP << PT_OPT_FLAG_SHIFT)
 
 /* single stepping state bits (used on ARM and PA-RISC) */
 #define PT_SINGLESTEP_BIT      31
index a19ddacdac30ae8d180c8b3358b18564bfbff564..f4265039a94c8f655a6a2d340bfbda547eb97704 100644 (file)
@@ -78,7 +78,7 @@ static inline long prctl_set_seccomp(unsigned long arg2, char __user *arg3)
 
 static inline int seccomp_mode(struct seccomp *s)
 {
-       return 0;
+       return SECCOMP_MODE_DISABLED;
 }
 #endif /* CONFIG_SECCOMP */
 
index cf1019e15f5bc57c0fbf6120a96deb2340465294..a7a69798661440b33f13c74e6560aabdb335ed1a 100644 (file)
@@ -89,9 +89,11 @@ struct ptrace_peeksiginfo_args {
 #define PTRACE_O_TRACESECCOMP  (1 << PTRACE_EVENT_SECCOMP)
 
 /* eventless options */
-#define PTRACE_O_EXITKILL      (1 << 20)
+#define PTRACE_O_EXITKILL              (1 << 20)
+#define PTRACE_O_SUSPEND_SECCOMP       (1 << 21)
 
-#define PTRACE_O_MASK          (0x000000ff | PTRACE_O_EXITKILL)
+#define PTRACE_O_MASK          (\
+       0x000000ff | PTRACE_O_EXITKILL | PTRACE_O_SUSPEND_SECCOMP)
 
 #include <asm/ptrace.h>
 
index c8e0e050a36afb0ccb875e13d9f2b526b0af4d29..787320de68e02425e8506363681b8875b6ee6d57 100644 (file)
@@ -556,6 +556,19 @@ static int ptrace_setoptions(struct task_struct *child, unsigned long data)
        if (data & ~(unsigned long)PTRACE_O_MASK)
                return -EINVAL;
 
+       if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
+               if (!config_enabled(CONFIG_CHECKPOINT_RESTORE) ||
+                   !config_enabled(CONFIG_SECCOMP))
+                       return -EINVAL;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               if (seccomp_mode(&current->seccomp) != SECCOMP_MODE_DISABLED ||
+                   current->ptrace & PT_SUSPEND_SECCOMP)
+                       return -EPERM;
+       }
+
        /* Avoid intermediate state when all opts are cleared */
        flags = child->ptrace;
        flags &= ~(PTRACE_O_MASK << PT_OPT_FLAG_SHIFT);
index 245df6b32b81f8eef778a203c2edb8432a52abd6..5bd4779282df00e8831d07ec09b80f9e07b73ad7 100644 (file)
@@ -175,17 +175,16 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
  */
 static u32 seccomp_run_filters(struct seccomp_data *sd)
 {
-       struct seccomp_filter *f = ACCESS_ONCE(current->seccomp.filter);
        struct seccomp_data sd_local;
        u32 ret = SECCOMP_RET_ALLOW;
+       /* Make sure cross-thread synced filter points somewhere sane. */
+       struct seccomp_filter *f =
+                       lockless_dereference(current->seccomp.filter);
 
        /* Ensure unexpected behavior doesn't result in failing open. */
        if (unlikely(WARN_ON(f == NULL)))
                return SECCOMP_RET_KILL;
 
-       /* Make sure cross-thread synced filter points somewhere sane. */
-       smp_read_barrier_depends();
-
        if (!sd) {
                populate_seccomp_data(&sd_local);
                sd = &sd_local;
@@ -549,7 +548,11 @@ void secure_computing_strict(int this_syscall)
 {
        int mode = current->seccomp.mode;
 
-       if (mode == 0)
+       if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
+           unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
+               return;
+
+       if (mode == SECCOMP_MODE_DISABLED)
                return;
        else if (mode == SECCOMP_MODE_STRICT)
                __secure_computing_strict(this_syscall);
@@ -650,6 +653,10 @@ u32 seccomp_phase1(struct seccomp_data *sd)
        int this_syscall = sd ? sd->nr :
                syscall_get_nr(current, task_pt_regs(current));
 
+       if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
+           unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
+               return SECCOMP_PHASE1_OK;
+
        switch (mode) {
        case SECCOMP_MODE_STRICT:
                __secure_computing_strict(this_syscall);  /* may call do_exit */