diff options
-rw-r--r-- | security/commoncap.c | 28 |
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 | ||
698 | static inline bool root_privileged(void) { return !issecure(SECURE_NOROOT); } | 698 | static inline bool root_privileged(void) { return !issecure(SECURE_NOROOT); } |
699 | 699 | ||
700 | static inline bool __is_real(kuid_t uid, struct cred *cred) | ||
701 | { return uid_eq(cred->uid, uid); } | ||
702 | |||
703 | static inline bool __is_eff(kuid_t uid, struct cred *cred) | ||
704 | { return uid_eq(cred->euid, uid); } | ||
705 | |||
706 | static 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 | |||
762 | static inline bool __is_setuid(struct cred *new, const struct cred *old) | ||
763 | { return !uid_eq(new->euid, old->uid); } | ||
764 | |||
765 | static 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; |