aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Guy Briggs <rgb@redhat.com>2017-10-11 20:57:05 -0400
committerJames Morris <james.l.morris@oracle.com>2017-10-20 00:22:43 -0400
commitdb1a8922cf3f0b936595ba41774fe4b66adf091a (patch)
tree4037669ca131379ee303fa457b461e6ba8c542f7
parent33957a104c86985f087b08a363590a948c9ff08c (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.c76
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 */
710static 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 }
749skip:
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))