Unified · Split
| @@ -34,6 +34,7 @@ · 33 unmodified lines | |||
| 34 | #define PT_TRACE_SECCOMP PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP) | 34 | #define PT_TRACE_SECCOMP PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP) |
| 35 | 35 | ||
| 36 | #define PT_EXITKILL (PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT) | 36 | #define PT_EXITKILL (PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT) |
| 37 | #define PT_SUSPEND_SECCOMP (PTRACE_O_SUSPEND_SECCOMP << PT_OPT_FLAG_SHIFT) | ||
| 37 | 38 | ||
| 38 | /* single stepping state bits (used on ARM and PA-RISC) */ | 39 | /* single stepping state bits (used on ARM and PA-RISC) */ |
| 39 | #define PT_SINGLESTEP_BIT 31 | 40 | #define PT_SINGLESTEP_BIT 31 |
| @@ -78,7 +78,7 @@ static inline long prctl_set_seccomp(unsigned long arg2, char __user *arg3) · 77 unmodified lines | |||
| 78 | 78 | ||
| 79 | static inline int seccomp_mode(struct seccomp *s) | 79 | static inline int seccomp_mode(struct seccomp *s) |
| 80 | { | 80 | { |
| 81 | return 0; | 81 | return SECCOMP_MODE_DISABLED; |
| 82 | } | 82 | } |
| 83 | #endif /* CONFIG_SECCOMP */ | 83 | #endif /* CONFIG_SECCOMP */ |
| 84 | 84 | ||
| @@ -89,9 +89,11 @@ struct ptrace_peeksiginfo_args { · 88 unmodified lines | |||
| 89 | #define PTRACE_O_TRACESECCOMP (1 << PTRACE_EVENT_SECCOMP) | 89 | #define PTRACE_O_TRACESECCOMP (1 << PTRACE_EVENT_SECCOMP) |
| 90 | 90 | ||
| 91 | /* eventless options */ | 91 | /* eventless options */ |
| 92 | #define PTRACE_O_EXITKILL (1 << 20) | 92 | #define PTRACE_O_EXITKILL (1 << 20) |
| 93 | #define PTRACE_O_SUSPEND_SECCOMP (1 << 21) | ||
| 93 | 94 | ||
| 94 | #define PTRACE_O_MASK (0x000000ff | PTRACE_O_EXITKILL) | 95 | #define PTRACE_O_MASK (\ |
| 96 | 0x000000ff | PTRACE_O_EXITKILL | PTRACE_O_SUSPEND_SECCOMP) | ||
| 95 | 97 | ||
| 96 | #include <asm/ptrace.h> | 98 | #include <asm/ptrace.h> |
| 97 | 99 | ||
| @@ -556,6 +556,19 @@ static int ptrace_setoptions(struct task_struct *child, unsigned long data) · 555 unmodified lines | |||
| 556 | if (data & ~(unsigned long)PTRACE_O_MASK) | 556 | if (data & ~(unsigned long)PTRACE_O_MASK) |
| 557 | return -EINVAL; | 557 | return -EINVAL; |
| 558 | 558 | ||
| 559 | if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) { | ||
| 560 | if (!config_enabled(CONFIG_CHECKPOINT_RESTORE) || | ||
| 561 | !config_enabled(CONFIG_SECCOMP)) | ||
| 562 | return -EINVAL; | ||
| 563 | |||
| 564 | if (!capable(CAP_SYS_ADMIN)) | ||
| 565 | return -EPERM; | ||
| 566 | |||
| 567 | if (seccomp_mode(¤t->seccomp) != SECCOMP_MODE_DISABLED || | ||
| 568 | current->ptrace & PT_SUSPEND_SECCOMP) | ||
| 569 | return -EPERM; | ||
| 570 | } | ||
| 571 | |||
| 559 | /* Avoid intermediate state when all opts are cleared */ | 572 | /* Avoid intermediate state when all opts are cleared */ |
| 560 | flags = child->ptrace; | 573 | flags = child->ptrace; |
| 561 | flags &= ~(PTRACE_O_MASK << PT_OPT_FLAG_SHIFT); | 574 | flags &= ~(PTRACE_O_MASK << PT_OPT_FLAG_SHIFT); |
| @@ -175,17 +175,16 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen) · 174 unmodified lines | |||
| 175 | */ | 175 | */ |
| 176 | static u32 seccomp_run_filters(struct seccomp_data *sd) | 176 | static u32 seccomp_run_filters(struct seccomp_data *sd) |
| 177 | { | 177 | { |
| 178 | struct seccomp_filter *f = ACCESS_ONCE(current->seccomp.filter); | ||
| 179 | struct seccomp_data sd_local; | 178 | struct seccomp_data sd_local; |
| 180 | u32 ret = SECCOMP_RET_ALLOW; | 179 | u32 ret = SECCOMP_RET_ALLOW; |
| 180 | /* Make sure cross-thread synced filter points somewhere sane. */ | ||
| 181 | struct seccomp_filter *f = | ||
| 182 | lockless_dereference(current->seccomp.filter); | ||
| 181 | 183 | ||
| 182 | /* Ensure unexpected behavior doesn't result in failing open. */ | 184 | /* Ensure unexpected behavior doesn't result in failing open. */ |
| 183 | if (unlikely(WARN_ON(f == NULL))) | 185 | if (unlikely(WARN_ON(f == NULL))) |
| 184 | return SECCOMP_RET_KILL; | 186 | return SECCOMP_RET_KILL; |
| 185 | 187 | ||
| 186 | /* Make sure cross-thread synced filter points somewhere sane. */ | ||
| 187 | smp_read_barrier_depends(); | ||
| 188 | |||
| 189 | if (!sd) { | 188 | if (!sd) { |
| 190 | populate_seccomp_data(&sd_local); | 189 | populate_seccomp_data(&sd_local); |
| 191 | sd = &sd_local; | 190 | sd = &sd_local; |
| @@ -549,7 +548,11 @@ void secure_computing_strict(int this_syscall) · 357 unmodified lines | |||
| 549 | { | 548 | { |
| 550 | int mode = current->seccomp.mode; | 549 | int mode = current->seccomp.mode; |
| 551 | 550 | ||
| 552 | if (mode == 0) | 551 | if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && |
| 552 | unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) | ||
| 553 | return; | ||
| 554 | |||
| 555 | if (mode == SECCOMP_MODE_DISABLED) | ||
| 553 | return; | 556 | return; |
| 554 | else if (mode == SECCOMP_MODE_STRICT) | 557 | else if (mode == SECCOMP_MODE_STRICT) |
| 555 | __secure_computing_strict(this_syscall); | 558 | __secure_computing_strict(this_syscall); |
| @@ -650,6 +653,10 @@ u32 seccomp_phase1(struct seccomp_data *sd) · 94 unmodified lines | |||
| 650 | int this_syscall = sd ? sd->nr : | 653 | int this_syscall = sd ? sd->nr : |
| 651 | syscall_get_nr(current, task_pt_regs(current)); | 654 | syscall_get_nr(current, task_pt_regs(current)); |
| 652 | 655 | ||
| 656 | if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && | ||
| 657 | unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) | ||
| 658 | return SECCOMP_PHASE1_OK; | ||
| 659 | |||
| 653 | switch (mode) { | 660 | switch (mode) { |
| 654 | case SECCOMP_MODE_STRICT: | 661 | case SECCOMP_MODE_STRICT: |
| 655 | __secure_computing_strict(this_syscall); /* may call do_exit */ | 662 | __secure_computing_strict(this_syscall); /* may call do_exit */ |