diff options
author | Richard Guy Briggs <rgb@redhat.com> | 2017-10-11 20:57:05 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2017-10-20 00:22:43 -0400 |
commit | db1a8922cf3f0b936595ba41774fe4b66adf091a (patch) | |
tree | 4037669ca131379ee303fa457b461e6ba8c542f7 | |
parent | 33957a104c86985f087b08a363590a948c9ff08c (diff) |
capabilities: factor out cap_bprm_set_creds privileged root
Factor out the case of privileged root from the function
cap_bprm_set_creds() to make the latter easier to read and analyse.
Suggested-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Acked-by: James Morris <james.l.morris@oracle.com>
Acked-by: Kees Cook <keescook@chromium.org>
Okay-ished-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
-rw-r--r-- | security/commoncap.c | 76 |
1 files changed, 48 insertions, 28 deletions
diff --git a/security/commoncap.c b/security/commoncap.c index c25e0d27537f..be9bca50c312 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -695,6 +695,52 @@ out: | |||
695 | return rc; | 695 | return rc; |
696 | } | 696 | } |
697 | 697 | ||
698 | /* | ||
699 | * handle_privileged_root - Handle case of privileged root | ||
700 | * @bprm: The execution parameters, including the proposed creds | ||
701 | * @has_fcap: Are any file capabilities set? | ||
702 | * @effective: Do we have effective root privilege? | ||
703 | * @root_uid: This namespace' root UID WRT initial USER namespace | ||
704 | * | ||
705 | * Handle the case where root is privileged and hasn't been neutered by | ||
706 | * SECURE_NOROOT. If file capabilities are set, they won't be combined with | ||
707 | * set UID root and nothing is changed. If we are root, cap_permitted is | ||
708 | * updated. If we have become set UID root, the effective bit is set. | ||
709 | */ | ||
710 | static void handle_privileged_root(struct linux_binprm *bprm, bool has_cap, | ||
711 | bool *effective, kuid_t root_uid) | ||
712 | { | ||
713 | const struct cred *old = current_cred(); | ||
714 | struct cred *new = bprm->cred; | ||
715 | |||
716 | if (issecure(SECURE_NOROOT)) | ||
717 | return; | ||
718 | /* | ||
719 | * If the legacy file capability is set, then don't set privs | ||
720 | * for a setuid root binary run by a non-root user. Do set it | ||
721 | * for a root user just to cause least surprise to an admin. | ||
722 | */ | ||
723 | if (has_cap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) { | ||
724 | warn_setuid_and_fcaps_mixed(bprm->filename); | ||
725 | return; | ||
726 | } | ||
727 | /* | ||
728 | * To support inheritance of root-permissions and suid-root | ||
729 | * executables under compatibility mode, we override the | ||
730 | * capability sets for the file. | ||
731 | */ | ||
732 | if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) { | ||
733 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ | ||
734 | new->cap_permitted = cap_combine(old->cap_bset, | ||
735 | old->cap_inheritable); | ||
736 | } | ||
737 | /* | ||
738 | * If only the real uid is 0, we do not set the effective bit. | ||
739 | */ | ||
740 | if (uid_eq(new->euid, root_uid)) | ||
741 | *effective = true; | ||
742 | } | ||
743 | |||
698 | /** | 744 | /** |
699 | * cap_bprm_set_creds - Set up the proposed credentials for execve(). | 745 | * cap_bprm_set_creds - Set up the proposed credentials for execve(). |
700 | * @bprm: The execution parameters, including the proposed creds | 746 | * @bprm: The execution parameters, including the proposed creds |
@@ -707,46 +753,20 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) | |||
707 | { | 753 | { |
708 | const struct cred *old = current_cred(); | 754 | const struct cred *old = current_cred(); |
709 | struct cred *new = bprm->cred; | 755 | struct cred *new = bprm->cred; |
710 | bool effective, has_cap = false, is_setid; | 756 | bool effective = false, has_cap = false, is_setid; |
711 | int ret; | 757 | int ret; |
712 | kuid_t root_uid; | 758 | kuid_t root_uid; |
713 | 759 | ||
714 | if (WARN_ON(!cap_ambient_invariant_ok(old))) | 760 | if (WARN_ON(!cap_ambient_invariant_ok(old))) |
715 | return -EPERM; | 761 | return -EPERM; |
716 | 762 | ||
717 | effective = false; | ||
718 | ret = get_file_caps(bprm, &effective, &has_cap); | 763 | ret = get_file_caps(bprm, &effective, &has_cap); |
719 | if (ret < 0) | 764 | if (ret < 0) |
720 | return ret; | 765 | return ret; |
721 | 766 | ||
722 | root_uid = make_kuid(new->user_ns, 0); | 767 | root_uid = make_kuid(new->user_ns, 0); |
723 | 768 | ||
724 | if (!issecure(SECURE_NOROOT)) { | 769 | handle_privileged_root(bprm, has_cap, &effective, root_uid); |
725 | /* | ||
726 | * If the legacy file capability is set, then don't set privs | ||
727 | * for a setuid root binary run by a non-root user. Do set it | ||
728 | * for a root user just to cause least surprise to an admin. | ||
729 | */ | ||
730 | if (has_cap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) { | ||
731 | warn_setuid_and_fcaps_mixed(bprm->filename); | ||
732 | goto skip; | ||
733 | } | ||
734 | /* | ||
735 | * To support inheritance of root-permissions and suid-root | ||
736 | * executables under compatibility mode, we override the | ||
737 | * capability sets for the file. | ||
738 | * | ||
739 | * If only the real uid is 0, we do not set the effective bit. | ||
740 | */ | ||
741 | if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) { | ||
742 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ | ||
743 | new->cap_permitted = cap_combine(old->cap_bset, | ||
744 | old->cap_inheritable); | ||
745 | } | ||
746 | if (uid_eq(new->euid, root_uid)) | ||
747 | effective = true; | ||
748 | } | ||
749 | skip: | ||
750 | 770 | ||
751 | /* if we have fs caps, clear dangerous personality flags */ | 771 | /* if we have fs caps, clear dangerous personality flags */ |
752 | if (!cap_issubset(new->cap_permitted, old->cap_permitted)) | 772 | if (!cap_issubset(new->cap_permitted, old->cap_permitted)) |