diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/apparmor/domain.c | 4 | ||||
-rw-r--r-- | security/commoncap.c | 7 | ||||
-rw-r--r-- | security/selinux/hooks.c | 10 |
3 files changed, 18 insertions, 3 deletions
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 6327685c101e..18c88d06e881 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -360,6 +360,10 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) if (bprm->cred_prepared) return 0; + /* XXX: no_new_privs is not usable with AppArmor yet */ + if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) + return -EPERM; + cxt = bprm->cred->security; BUG_ON(!cxt); diff --git a/security/commoncap.c b/security/commoncap.c index 0cf4b53480a7..edd3918fac02 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -506,14 +506,17 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) skip: /* Don't let someone trace a set[ug]id/setpcap binary with the revised - * credentials unless they have the appropriate permit + * credentials unless they have the appropriate permit. + * + * In addition, if NO_NEW_PRIVS, then ensure we get no new privs. */ if ((new->euid != old->uid || new->egid != old->gid || !cap_issubset(new->cap_permitted, old->cap_permitted)) && bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { /* downgrade; they get no more than they had, and maybe less */ - if (!capable(CAP_SETUID)) { + if (!capable(CAP_SETUID) || + (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) { new->euid = new->uid; new->egid = new->gid; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d85b793c9321..0b06685787b9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2016,6 +2016,13 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) new_tsec->sid = old_tsec->exec_sid; /* Reset exec SID on execve. */ new_tsec->exec_sid = 0; + + /* + * Minimize confusion: if no_new_privs and a transition is + * explicitly requested, then fail the exec. + */ + if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) + return -EPERM; } else { /* Check for a default transition on this program. */ rc = security_transition_sid(old_tsec->sid, isec->sid, @@ -2029,7 +2036,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) ad.selinux_audit_data = &sad; ad.u.path = bprm->file->f_path; - if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) + if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || + (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) new_tsec->sid = old_tsec->sid; if (new_tsec->sid == old_tsec->sid) { |