Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

seccomp: remove 2-phase API

Since nothing is using the 2-phase API, and it adds more complexity than
benefit, remove it.

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@kernel.org>

+41 -94
-6
include/linux/seccomp.h
··· 35 35 return __secure_computing(sd); 36 36 return 0; 37 37 } 38 - 39 - #define SECCOMP_PHASE1_OK 0 40 - #define SECCOMP_PHASE1_SKIP 1 41 - 42 - extern u32 seccomp_phase1(struct seccomp_data *sd); 43 - int seccomp_phase2(u32 phase1_result); 44 38 #else 45 39 extern void secure_computing_strict(int this_syscall); 46 40 #endif
+41 -88
kernel/seccomp.c
··· 173 173 * 174 174 * Returns valid seccomp BPF response codes. 175 175 */ 176 - static u32 seccomp_run_filters(struct seccomp_data *sd) 176 + static u32 seccomp_run_filters(const struct seccomp_data *sd) 177 177 { 178 178 struct seccomp_data sd_local; 179 179 u32 ret = SECCOMP_RET_ALLOW; ··· 554 554 BUG(); 555 555 } 556 556 #else 557 - int __secure_computing(const struct seccomp_data *sd) 558 - { 559 - u32 phase1_result = seccomp_phase1(sd); 560 - 561 - if (likely(phase1_result == SECCOMP_PHASE1_OK)) 562 - return 0; 563 - else if (likely(phase1_result == SECCOMP_PHASE1_SKIP)) 564 - return -1; 565 - else 566 - return seccomp_phase2(phase1_result); 567 - } 568 557 569 558 #ifdef CONFIG_SECCOMP_FILTER 570 - static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) 559 + static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) 571 560 { 572 561 u32 filter_ret, action; 573 562 int data; ··· 588 599 goto skip; 589 600 590 601 case SECCOMP_RET_TRACE: 591 - return filter_ret; /* Save the rest for phase 2. */ 602 + /* ENOSYS these calls if there is no tracer attached. */ 603 + if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { 604 + syscall_set_return_value(current, 605 + task_pt_regs(current), 606 + -ENOSYS, 0); 607 + goto skip; 608 + } 609 + 610 + /* Allow the BPF to provide the event message */ 611 + ptrace_event(PTRACE_EVENT_SECCOMP, data); 612 + /* 613 + * The delivery of a fatal signal during event 614 + * notification may silently skip tracer notification. 615 + * Terminating the task now avoids executing a system 616 + * call that may not be intended. 617 + */ 618 + if (fatal_signal_pending(current)) 619 + do_exit(SIGSYS); 620 + /* Check if the tracer forced the syscall to be skipped. */ 621 + this_syscall = syscall_get_nr(current, task_pt_regs(current)); 622 + if (this_syscall < 0) 623 + goto skip; 624 + 625 + return 0; 592 626 593 627 case SECCOMP_RET_ALLOW: 594 - return SECCOMP_PHASE1_OK; 628 + return 0; 595 629 596 630 case SECCOMP_RET_KILL: 597 631 default: ··· 626 614 627 615 skip: 628 616 audit_seccomp(this_syscall, 0, action); 629 - return SECCOMP_PHASE1_SKIP; 617 + return -1; 618 + } 619 + #else 620 + static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) 621 + { 622 + BUG(); 630 623 } 631 624 #endif 632 625 633 - /** 634 - * seccomp_phase1() - run fast path seccomp checks on the current syscall 635 - * @arg sd: The seccomp_data or NULL 636 - * 637 - * This only reads pt_regs via the syscall_xyz helpers. The only change 638 - * it will make to pt_regs is via syscall_set_return_value, and it will 639 - * only do that if it returns SECCOMP_PHASE1_SKIP. 640 - * 641 - * If sd is provided, it will not read pt_regs at all. 642 - * 643 - * It may also call do_exit or force a signal; these actions must be 644 - * safe. 645 - * 646 - * If it returns SECCOMP_PHASE1_OK, the syscall passes checks and should 647 - * be processed normally. 648 - * 649 - * If it returns SECCOMP_PHASE1_SKIP, then the syscall should not be 650 - * invoked. In this case, seccomp_phase1 will have set the return value 651 - * using syscall_set_return_value. 652 - * 653 - * If it returns anything else, then the return value should be passed 654 - * to seccomp_phase2 from a context in which ptrace hooks are safe. 655 - */ 656 - u32 seccomp_phase1(struct seccomp_data *sd) 626 + int __secure_computing(const struct seccomp_data *sd) 657 627 { 658 628 int mode = current->seccomp.mode; 659 - int this_syscall = sd ? sd->nr : 660 - syscall_get_nr(current, task_pt_regs(current)); 629 + int this_syscall; 661 630 662 631 if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && 663 632 unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) 664 - return SECCOMP_PHASE1_OK; 633 + return 0; 634 + 635 + this_syscall = sd ? sd->nr : 636 + syscall_get_nr(current, task_pt_regs(current)); 665 637 666 638 switch (mode) { 667 639 case SECCOMP_MODE_STRICT: 668 640 __secure_computing_strict(this_syscall); /* may call do_exit */ 669 - return SECCOMP_PHASE1_OK; 670 - #ifdef CONFIG_SECCOMP_FILTER 641 + return 0; 671 642 case SECCOMP_MODE_FILTER: 672 - return __seccomp_phase1_filter(this_syscall, sd); 673 - #endif 643 + return __seccomp_filter(this_syscall, sd); 674 644 default: 675 645 BUG(); 676 646 } 677 - } 678 - 679 - /** 680 - * seccomp_phase2() - finish slow path seccomp work for the current syscall 681 - * @phase1_result: The return value from seccomp_phase1() 682 - * 683 - * This must be called from a context in which ptrace hooks can be used. 684 - * 685 - * Returns 0 if the syscall should be processed or -1 to skip the syscall. 686 - */ 687 - int seccomp_phase2(u32 phase1_result) 688 - { 689 - struct pt_regs *regs = task_pt_regs(current); 690 - u32 action = phase1_result & SECCOMP_RET_ACTION; 691 - int data = phase1_result & SECCOMP_RET_DATA; 692 - 693 - BUG_ON(action != SECCOMP_RET_TRACE); 694 - 695 - audit_seccomp(syscall_get_nr(current, regs), 0, action); 696 - 697 - /* Skip these calls if there is no tracer. */ 698 - if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { 699 - syscall_set_return_value(current, regs, 700 - -ENOSYS, 0); 701 - return -1; 702 - } 703 - 704 - /* Allow the BPF to provide the event message */ 705 - ptrace_event(PTRACE_EVENT_SECCOMP, data); 706 - /* 707 - * The delivery of a fatal signal during event 708 - * notification may silently skip tracer notification. 709 - * Terminating the task now avoids executing a system 710 - * call that may not be intended. 711 - */ 712 - if (fatal_signal_pending(current)) 713 - do_exit(SIGSYS); 714 - if (syscall_get_nr(current, regs) < 0) 715 - return -1; /* Explicit request to skip. */ 716 - 717 - return 0; 718 647 } 719 648 #endif /* CONFIG_HAVE_ARCH_SECCOMP_FILTER */ 720 649