aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Guy Briggs <rgb@redhat.com>2017-10-11 20:57:14 -0400
committerJames Morris <james.l.morris@oracle.com>2017-10-20 00:22:46 -0400
commitdbbbe1105ea6aa0c49d78a4ea0d924e0c02307eb (patch)
treeba8713777af7834790c7589e508baee56da4b47a
parent588fb2c7e294753d3090a1dc2e7c34e7e3ce5aff (diff)
capabilities: audit log other surprising conditions
The existing condition tested for process effective capabilities set by file attributes but intended to ignore the change if the result was unsurprisingly an effective full set in the case root is special with a setuid root executable file and we are root. Stated again: - When you execute a setuid root application, it is no surprise and expected that it got all capabilities, so we do not want capabilities recorded. if (pE_grew && !(pE_fullset && (eff_root || real_root) && root_priveleged) ) Now make sure we cover other cases: - If something prevented a setuid root app getting all capabilities and it wound up with one capability only, then it is a surprise and should be logged. When it is a setuid root file, we only want capabilities when the process does not get full capabilities.. root_priveleged && setuid_root && !pE_fullset - Similarly if a non-setuid program does pick up capabilities due to file system based capabilities, then we want to know what capabilities were picked up. When it has file system based capabilities we want the capabilities. !is_setuid && (has_fcap && pP_gained) - If it is a non-setuid file and it gets ambient capabilities, we want the capabilities. !is_setuid && pA_gained - These last two are combined into one due to the common first parameter. Related: https://github.com/linux-audit/audit-kernel/issues/16 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> Acked-by: Paul Moore <paul@paul-moore.com> Signed-off-by: James Morris <james.l.morris@oracle.com>
-rw-r--r--security/commoncap.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index ad7536d76820..5fa839c7fb3f 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -766,7 +766,7 @@ static inline bool __is_setgid(struct cred *new, const struct cred *old)
766{ return !gid_eq(new->egid, old->gid); } 766{ return !gid_eq(new->egid, old->gid); }
767 767
768/* 768/*
769 * Audit candidate if current->cap_effective is set 769 * 1) Audit candidate if current->cap_effective is set
770 * 770 *
771 * We do not bother to audit if 3 things are true: 771 * We do not bother to audit if 3 things are true:
772 * 1) cap_effective has all caps 772 * 1) cap_effective has all caps
@@ -776,16 +776,31 @@ static inline bool __is_setgid(struct cred *new, const struct cred *old)
776 * 776 *
777 * Number 1 above might fail if you don't have a full bset, but I think 777 * Number 1 above might fail if you don't have a full bset, but I think
778 * that is interesting information to audit. 778 * that is interesting information to audit.
779 *
780 * A number of other conditions require logging:
781 * 2) something prevented setuid root getting all caps
782 * 3) non-setuid root gets fcaps
783 * 4) non-setuid root gets ambient
779 */ 784 */
780static inline bool nonroot_raised_pE(struct cred *cred, kuid_t root) 785static inline bool nonroot_raised_pE(struct cred *new, const struct cred *old,
786 kuid_t root, bool has_fcap)
781{ 787{
782 bool ret = false; 788 bool ret = false;
783 789
784 if (__cap_grew(effective, ambient, cred) && 790 if ((__cap_grew(effective, ambient, new) &&
785 !(__cap_full(effective, cred) && 791 !(__cap_full(effective, new) &&
786 (__is_eff(root, cred) || __is_real(root, cred)) && 792 (__is_eff(root, new) || __is_real(root, new)) &&
787 root_privileged())) 793 root_privileged())) ||
794 (root_privileged() &&
795 __is_suid(root, new) &&
796 !__cap_full(effective, new)) ||
797 (!__is_setuid(new, old) &&
798 ((has_fcap &&
799 __cap_gained(permitted, new, old)) ||
800 __cap_gained(ambient, new, old))))
801
788 ret = true; 802 ret = true;
803
789 return ret; 804 return ret;
790} 805}
791 806
@@ -865,7 +880,7 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
865 if (WARN_ON(!cap_ambient_invariant_ok(new))) 880 if (WARN_ON(!cap_ambient_invariant_ok(new)))
866 return -EPERM; 881 return -EPERM;
867 882
868 if (nonroot_raised_pE(new, root_uid)) { 883 if (nonroot_raised_pE(new, old, root_uid, has_fcap)) {
869 ret = audit_log_bprm_fcaps(bprm, new, old); 884 ret = audit_log_bprm_fcaps(bprm, new, old);
870 if (ret < 0) 885 if (ret < 0)
871 return ret; 886 return ret;