Unified · Split
| @@ -34,6 +34,7 @@ · 33 unmodified lines | ||
| 34 | 34 | #define PT_TRACE_SECCOMP PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP) |
| 35 | 35 | |
| 36 | 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 | 39 | /* single stepping state bits (used on ARM and PA-RISC) */ |
| 39 | 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 | 79 | static inline int seccomp_mode(struct seccomp *s) |
| 80 | 80 | { |
| 81 | − return 0; | |
| 81 | + return SECCOMP_MODE_DISABLED; | |
| 82 | 82 | } |
| 83 | 83 | #endif /* CONFIG_SECCOMP */ |
| 84 | 84 | |
| @@ -89,9 +89,11 @@ struct ptrace_peeksiginfo_args { · 88 unmodified lines | ||
| 89 | 89 | #define PTRACE_O_TRACESECCOMP (1 << PTRACE_EVENT_SECCOMP) |
| 90 | 90 | |
| 91 | 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 | 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 | 556 | if (data & ~(unsigned long)PTRACE_O_MASK) |
| 557 | 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 | 572 | /* Avoid intermediate state when all opts are cleared */ |
| 560 | 573 | flags = child->ptrace; |
| 561 | 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 | 176 | static u32 seccomp_run_filters(struct seccomp_data *sd) |
| 177 | 177 | { |
| 178 | − struct seccomp_filter *f = ACCESS_ONCE(current->seccomp.filter); | |
| 179 | 178 | struct seccomp_data sd_local; |
| 180 | 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 | 184 | /* Ensure unexpected behavior doesn't result in failing open. */ |
| 183 | 185 | if (unlikely(WARN_ON(f == NULL))) |
| 184 | 186 | return SECCOMP_RET_KILL; |
| 185 | 187 | |
| 186 | − /* Make sure cross-thread synced filter points somewhere sane. */ | |
| 187 | − smp_read_barrier_depends(); | |
| 188 | − | |
| 189 | 188 | if (!sd) { |
| 190 | 189 | populate_seccomp_data(&sd_local); |
| 191 | 190 | sd = &sd_local; |
| @@ -549,7 +548,11 @@ void secure_computing_strict(int this_syscall) · 357 unmodified lines | ||
| 549 | 548 | { |
| 550 | 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 | 556 | return; |
| 554 | 557 | else if (mode == SECCOMP_MODE_STRICT) |
| 555 | 558 | __secure_computing_strict(this_syscall); |
| @@ -650,6 +653,10 @@ u32 seccomp_phase1(struct seccomp_data *sd) · 94 unmodified lines | ||
| 650 | 653 | int this_syscall = sd ? sd->nr : |
| 651 | 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 | 660 | switch (mode) { |
| 654 | 661 | case SECCOMP_MODE_STRICT: |
| 655 | 662 | __secure_computing_strict(this_syscall); /* may call do_exit */ |