diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-29 20:38:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-29 20:38:46 -0400 |
commit | 7a1e8b80fb1e8ead4cec15d1fc494ed290e4d2e9 (patch) | |
tree | 55a36d4256f1ae793b5c8e88c0f158737447193f /kernel | |
parent | a867d7349e94b6409b08629886a819f802377e91 (diff) | |
parent | 7616ac70d1bb4f2e9d25c1a82d283f3368a7b632 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"Highlights:
- TPM core and driver updates/fixes
- IPv6 security labeling (CALIPSO)
- Lots of Apparmor fixes
- Seccomp: remove 2-phase API, close hole where ptrace can change
syscall #"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (156 commits)
apparmor: fix SECURITY_APPARMOR_HASH_DEFAULT parameter handling
tpm: Add TPM 2.0 support to the Nuvoton i2c driver (NPCT6xx family)
tpm: Factor out common startup code
tpm: use devm_add_action_or_reset
tpm2_i2c_nuvoton: add irq validity check
tpm: read burstcount from TPM_STS in one 32-bit transaction
tpm: fix byte-order for the value read by tpm2_get_tpm_pt
tpm_tis_core: convert max timeouts from msec to jiffies
apparmor: fix arg_size computation for when setprocattr is null terminated
apparmor: fix oops, validate buffer size in apparmor_setprocattr()
apparmor: do not expose kernel stack
apparmor: fix module parameters can be changed after policy is locked
apparmor: fix oops in profile_unpack() when policy_db is not present
apparmor: don't check for vmalloc_addr if kvzalloc() failed
apparmor: add missing id bounds check on dfa verification
apparmor: allow SYS_CAP_RESOURCE to be sufficient to prlimit another task
apparmor: use list_next_entry instead of list_entry_next
apparmor: fix refcount race when finding a child profile
apparmor: fix ref count leak when profile sha1 hash is read
apparmor: check that xindex is in trans_table bounds
...
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/capability.c | 46 | ||||
-rw-r--r-- | kernel/seccomp.c | 144 |
2 files changed, 92 insertions, 98 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index 45432b54d5c6..00411c82dac5 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -361,6 +361,24 @@ bool has_capability_noaudit(struct task_struct *t, int cap) | |||
361 | return has_ns_capability_noaudit(t, &init_user_ns, cap); | 361 | return has_ns_capability_noaudit(t, &init_user_ns, cap); |
362 | } | 362 | } |
363 | 363 | ||
364 | static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit) | ||
365 | { | ||
366 | int capable; | ||
367 | |||
368 | if (unlikely(!cap_valid(cap))) { | ||
369 | pr_crit("capable() called with invalid cap=%u\n", cap); | ||
370 | BUG(); | ||
371 | } | ||
372 | |||
373 | capable = audit ? security_capable(current_cred(), ns, cap) : | ||
374 | security_capable_noaudit(current_cred(), ns, cap); | ||
375 | if (capable == 0) { | ||
376 | current->flags |= PF_SUPERPRIV; | ||
377 | return true; | ||
378 | } | ||
379 | return false; | ||
380 | } | ||
381 | |||
364 | /** | 382 | /** |
365 | * ns_capable - Determine if the current task has a superior capability in effect | 383 | * ns_capable - Determine if the current task has a superior capability in effect |
366 | * @ns: The usernamespace we want the capability in | 384 | * @ns: The usernamespace we want the capability in |
@@ -374,19 +392,27 @@ bool has_capability_noaudit(struct task_struct *t, int cap) | |||
374 | */ | 392 | */ |
375 | bool ns_capable(struct user_namespace *ns, int cap) | 393 | bool ns_capable(struct user_namespace *ns, int cap) |
376 | { | 394 | { |
377 | if (unlikely(!cap_valid(cap))) { | 395 | return ns_capable_common(ns, cap, true); |
378 | pr_crit("capable() called with invalid cap=%u\n", cap); | ||
379 | BUG(); | ||
380 | } | ||
381 | |||
382 | if (security_capable(current_cred(), ns, cap) == 0) { | ||
383 | current->flags |= PF_SUPERPRIV; | ||
384 | return true; | ||
385 | } | ||
386 | return false; | ||
387 | } | 396 | } |
388 | EXPORT_SYMBOL(ns_capable); | 397 | EXPORT_SYMBOL(ns_capable); |
389 | 398 | ||
399 | /** | ||
400 | * ns_capable_noaudit - Determine if the current task has a superior capability | ||
401 | * (unaudited) in effect | ||
402 | * @ns: The usernamespace we want the capability in | ||
403 | * @cap: The capability to be tested for | ||
404 | * | ||
405 | * Return true if the current task has the given superior capability currently | ||
406 | * available for use, false if not. | ||
407 | * | ||
408 | * This sets PF_SUPERPRIV on the task if the capability is available on the | ||
409 | * assumption that it's about to be used. | ||
410 | */ | ||
411 | bool ns_capable_noaudit(struct user_namespace *ns, int cap) | ||
412 | { | ||
413 | return ns_capable_common(ns, cap, false); | ||
414 | } | ||
415 | EXPORT_SYMBOL(ns_capable_noaudit); | ||
390 | 416 | ||
391 | /** | 417 | /** |
392 | * capable - Determine if the current task has a superior capability in effect | 418 | * capable - Determine if the current task has a superior capability in effect |
diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 7002796f14a4..54d15eb2b701 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c | |||
@@ -173,7 +173,7 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen) | |||
173 | * | 173 | * |
174 | * Returns valid seccomp BPF response codes. | 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 | struct seccomp_data sd_local; | 178 | struct seccomp_data sd_local; |
179 | u32 ret = SECCOMP_RET_ALLOW; | 179 | u32 ret = SECCOMP_RET_ALLOW; |
@@ -554,20 +554,10 @@ void secure_computing_strict(int this_syscall) | |||
554 | BUG(); | 554 | BUG(); |
555 | } | 555 | } |
556 | #else | 556 | #else |
557 | int __secure_computing(void) | ||
558 | { | ||
559 | u32 phase1_result = seccomp_phase1(NULL); | ||
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 | #ifdef CONFIG_SECCOMP_FILTER | 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, |
560 | const bool recheck_after_trace) | ||
571 | { | 561 | { |
572 | u32 filter_ret, action; | 562 | u32 filter_ret, action; |
573 | int data; | 563 | int data; |
@@ -599,10 +589,46 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) | |||
599 | goto skip; | 589 | goto skip; |
600 | 590 | ||
601 | case SECCOMP_RET_TRACE: | 591 | case SECCOMP_RET_TRACE: |
602 | return filter_ret; /* Save the rest for phase 2. */ | 592 | /* We've been put in this state by the ptracer already. */ |
593 | if (recheck_after_trace) | ||
594 | return 0; | ||
595 | |||
596 | /* ENOSYS these calls if there is no tracer attached. */ | ||
597 | if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { | ||
598 | syscall_set_return_value(current, | ||
599 | task_pt_regs(current), | ||
600 | -ENOSYS, 0); | ||
601 | goto skip; | ||
602 | } | ||
603 | |||
604 | /* Allow the BPF to provide the event message */ | ||
605 | ptrace_event(PTRACE_EVENT_SECCOMP, data); | ||
606 | /* | ||
607 | * The delivery of a fatal signal during event | ||
608 | * notification may silently skip tracer notification. | ||
609 | * Terminating the task now avoids executing a system | ||
610 | * call that may not be intended. | ||
611 | */ | ||
612 | if (fatal_signal_pending(current)) | ||
613 | do_exit(SIGSYS); | ||
614 | /* Check if the tracer forced the syscall to be skipped. */ | ||
615 | this_syscall = syscall_get_nr(current, task_pt_regs(current)); | ||
616 | if (this_syscall < 0) | ||
617 | goto skip; | ||
618 | |||
619 | /* | ||
620 | * Recheck the syscall, since it may have changed. This | ||
621 | * intentionally uses a NULL struct seccomp_data to force | ||
622 | * a reload of all registers. This does not goto skip since | ||
623 | * a skip would have already been reported. | ||
624 | */ | ||
625 | if (__seccomp_filter(this_syscall, NULL, true)) | ||
626 | return -1; | ||
627 | |||
628 | return 0; | ||
603 | 629 | ||
604 | case SECCOMP_RET_ALLOW: | 630 | case SECCOMP_RET_ALLOW: |
605 | return SECCOMP_PHASE1_OK; | 631 | return 0; |
606 | 632 | ||
607 | case SECCOMP_RET_KILL: | 633 | case SECCOMP_RET_KILL: |
608 | default: | 634 | default: |
@@ -614,96 +640,38 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) | |||
614 | 640 | ||
615 | skip: | 641 | skip: |
616 | audit_seccomp(this_syscall, 0, action); | 642 | audit_seccomp(this_syscall, 0, action); |
617 | return SECCOMP_PHASE1_SKIP; | 643 | return -1; |
644 | } | ||
645 | #else | ||
646 | static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, | ||
647 | const bool recheck_after_trace) | ||
648 | { | ||
649 | BUG(); | ||
618 | } | 650 | } |
619 | #endif | 651 | #endif |
620 | 652 | ||
621 | /** | 653 | int __secure_computing(const struct seccomp_data *sd) |
622 | * seccomp_phase1() - run fast path seccomp checks on the current syscall | ||
623 | * @arg sd: The seccomp_data or NULL | ||
624 | * | ||
625 | * This only reads pt_regs via the syscall_xyz helpers. The only change | ||
626 | * it will make to pt_regs is via syscall_set_return_value, and it will | ||
627 | * only do that if it returns SECCOMP_PHASE1_SKIP. | ||
628 | * | ||
629 | * If sd is provided, it will not read pt_regs at all. | ||
630 | * | ||
631 | * It may also call do_exit or force a signal; these actions must be | ||
632 | * safe. | ||
633 | * | ||
634 | * If it returns SECCOMP_PHASE1_OK, the syscall passes checks and should | ||
635 | * be processed normally. | ||
636 | * | ||
637 | * If it returns SECCOMP_PHASE1_SKIP, then the syscall should not be | ||
638 | * invoked. In this case, seccomp_phase1 will have set the return value | ||
639 | * using syscall_set_return_value. | ||
640 | * | ||
641 | * If it returns anything else, then the return value should be passed | ||
642 | * to seccomp_phase2 from a context in which ptrace hooks are safe. | ||
643 | */ | ||
644 | u32 seccomp_phase1(struct seccomp_data *sd) | ||
645 | { | 654 | { |
646 | int mode = current->seccomp.mode; | 655 | int mode = current->seccomp.mode; |
647 | int this_syscall = sd ? sd->nr : | 656 | int this_syscall; |
648 | syscall_get_nr(current, task_pt_regs(current)); | ||
649 | 657 | ||
650 | if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && | 658 | if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && |
651 | unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) | 659 | unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) |
652 | return SECCOMP_PHASE1_OK; | 660 | return 0; |
661 | |||
662 | this_syscall = sd ? sd->nr : | ||
663 | syscall_get_nr(current, task_pt_regs(current)); | ||
653 | 664 | ||
654 | switch (mode) { | 665 | switch (mode) { |
655 | case SECCOMP_MODE_STRICT: | 666 | case SECCOMP_MODE_STRICT: |
656 | __secure_computing_strict(this_syscall); /* may call do_exit */ | 667 | __secure_computing_strict(this_syscall); /* may call do_exit */ |
657 | return SECCOMP_PHASE1_OK; | 668 | return 0; |
658 | #ifdef CONFIG_SECCOMP_FILTER | ||
659 | case SECCOMP_MODE_FILTER: | 669 | case SECCOMP_MODE_FILTER: |
660 | return __seccomp_phase1_filter(this_syscall, sd); | 670 | return __seccomp_filter(this_syscall, sd, false); |
661 | #endif | ||
662 | default: | 671 | default: |
663 | BUG(); | 672 | BUG(); |
664 | } | 673 | } |
665 | } | 674 | } |
666 | |||
667 | /** | ||
668 | * seccomp_phase2() - finish slow path seccomp work for the current syscall | ||
669 | * @phase1_result: The return value from seccomp_phase1() | ||
670 | * | ||
671 | * This must be called from a context in which ptrace hooks can be used. | ||
672 | * | ||
673 | * Returns 0 if the syscall should be processed or -1 to skip the syscall. | ||
674 | */ | ||
675 | int seccomp_phase2(u32 phase1_result) | ||
676 | { | ||
677 | struct pt_regs *regs = task_pt_regs(current); | ||
678 | u32 action = phase1_result & SECCOMP_RET_ACTION; | ||
679 | int data = phase1_result & SECCOMP_RET_DATA; | ||
680 | |||
681 | BUG_ON(action != SECCOMP_RET_TRACE); | ||
682 | |||
683 | audit_seccomp(syscall_get_nr(current, regs), 0, action); | ||
684 | |||
685 | /* Skip these calls if there is no tracer. */ | ||
686 | if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { | ||
687 | syscall_set_return_value(current, regs, | ||
688 | -ENOSYS, 0); | ||
689 | return -1; | ||
690 | } | ||
691 | |||
692 | /* Allow the BPF to provide the event message */ | ||
693 | ptrace_event(PTRACE_EVENT_SECCOMP, data); | ||
694 | /* | ||
695 | * The delivery of a fatal signal during event | ||
696 | * notification may silently skip tracer notification. | ||
697 | * Terminating the task now avoids executing a system | ||
698 | * call that may not be intended. | ||
699 | */ | ||
700 | if (fatal_signal_pending(current)) | ||
701 | do_exit(SIGSYS); | ||
702 | if (syscall_get_nr(current, regs) < 0) | ||
703 | return -1; /* Explicit request to skip. */ | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | #endif /* CONFIG_HAVE_ARCH_SECCOMP_FILTER */ | 675 | #endif /* CONFIG_HAVE_ARCH_SECCOMP_FILTER */ |
708 | 676 | ||
709 | long prctl_get_seccomp(void) | 677 | long prctl_get_seccomp(void) |