aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/commoncap.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 9b8a6e79d858..421f7438d3c8 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -697,6 +697,15 @@ out:
697 697
698static inline bool root_privileged(void) { return !issecure(SECURE_NOROOT); } 698static inline bool root_privileged(void) { return !issecure(SECURE_NOROOT); }
699 699
700static inline bool __is_real(kuid_t uid, struct cred *cred)
701{ return uid_eq(cred->uid, uid); }
702
703static inline bool __is_eff(kuid_t uid, struct cred *cred)
704{ return uid_eq(cred->euid, uid); }
705
706static inline bool __is_suid(kuid_t uid, struct cred *cred)
707{ return !__is_real(uid, cred) && __is_eff(uid, cred); }
708
700/* 709/*
701 * handle_privileged_root - Handle case of privileged root 710 * handle_privileged_root - Handle case of privileged root
702 * @bprm: The execution parameters, including the proposed creds 711 * @bprm: The execution parameters, including the proposed creds
@@ -722,7 +731,7 @@ static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap,
722 * for a setuid root binary run by a non-root user. Do set it 731 * for a setuid root binary run by a non-root user. Do set it
723 * for a root user just to cause least surprise to an admin. 732 * for a root user just to cause least surprise to an admin.
724 */ 733 */
725 if (has_fcap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) { 734 if (has_fcap && __is_suid(root_uid, new)) {
726 warn_setuid_and_fcaps_mixed(bprm->filename); 735 warn_setuid_and_fcaps_mixed(bprm->filename);
727 return; 736 return;
728 } 737 }
@@ -731,7 +740,7 @@ static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap,
731 * executables under compatibility mode, we override the 740 * executables under compatibility mode, we override the
732 * capability sets for the file. 741 * capability sets for the file.
733 */ 742 */
734 if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) { 743 if (__is_eff(root_uid, new) || __is_real(root_uid, new)) {
735 /* pP' = (cap_bset & ~0) | (pI & ~0) */ 744 /* pP' = (cap_bset & ~0) | (pI & ~0) */
736 new->cap_permitted = cap_combine(old->cap_bset, 745 new->cap_permitted = cap_combine(old->cap_bset,
737 old->cap_inheritable); 746 old->cap_inheritable);
@@ -739,7 +748,7 @@ static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap,
739 /* 748 /*
740 * If only the real uid is 0, we do not set the effective bit. 749 * If only the real uid is 0, we do not set the effective bit.
741 */ 750 */
742 if (uid_eq(new->euid, root_uid)) 751 if (__is_eff(root_uid, new))
743 *effective = true; 752 *effective = true;
744} 753}
745 754
@@ -749,6 +758,13 @@ static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap,
749 !cap_issubset(cred->cap_##target, cred->cap_##source) 758 !cap_issubset(cred->cap_##target, cred->cap_##source)
750#define __cap_full(field, cred) \ 759#define __cap_full(field, cred) \
751 cap_issubset(CAP_FULL_SET, cred->cap_##field) 760 cap_issubset(CAP_FULL_SET, cred->cap_##field)
761
762static inline bool __is_setuid(struct cred *new, const struct cred *old)
763{ return !uid_eq(new->euid, old->uid); }
764
765static inline bool __is_setgid(struct cred *new, const struct cred *old)
766{ return !gid_eq(new->egid, old->gid); }
767
752/** 768/**
753 * cap_bprm_set_creds - Set up the proposed credentials for execve(). 769 * cap_bprm_set_creds - Set up the proposed credentials for execve().
754 * @bprm: The execution parameters, including the proposed creds 770 * @bprm: The execution parameters, including the proposed creds
@@ -785,7 +801,7 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
785 * 801 *
786 * In addition, if NO_NEW_PRIVS, then ensure we get no new privs. 802 * In addition, if NO_NEW_PRIVS, then ensure we get no new privs.
787 */ 803 */
788 is_setid = !uid_eq(new->euid, old->uid) || !gid_eq(new->egid, old->gid); 804 is_setid = __is_setuid(new, old) || __is_setgid(new, old);
789 805
790 if ((is_setid || __cap_gained(permitted, new, old)) && 806 if ((is_setid || __cap_gained(permitted, new, old)) &&
791 ((bprm->unsafe & ~LSM_UNSAFE_PTRACE) || 807 ((bprm->unsafe & ~LSM_UNSAFE_PTRACE) ||
@@ -839,7 +855,7 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
839 */ 855 */
840 if (__cap_grew(effective, ambient, new)) { 856 if (__cap_grew(effective, ambient, new)) {
841 if (!__cap_full(effective, new) || 857 if (!__cap_full(effective, new) ||
842 !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) || 858 !__is_eff(root_uid, new) || !__is_real(root_uid, new) ||
843 !root_privileged()) { 859 !root_privileged()) {
844 ret = audit_log_bprm_fcaps(bprm, new, old); 860 ret = audit_log_bprm_fcaps(bprm, new, old);
845 if (ret < 0) 861 if (ret < 0)
@@ -856,7 +872,7 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
856 bprm->cap_elevated = 0; 872 bprm->cap_elevated = 0;
857 if (is_setid) { 873 if (is_setid) {
858 bprm->cap_elevated = 1; 874 bprm->cap_elevated = 1;
859 } else if (!uid_eq(new->uid, root_uid)) { 875 } else if (!__is_real(root_uid, new)) {
860 if (effective || 876 if (effective ||
861 __cap_grew(permitted, ambient, new)) 877 __cap_grew(permitted, ambient, new))
862 bprm->cap_elevated = 1; 878 bprm->cap_elevated = 1;