aboutsummaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2012-01-30 08:17:26 -0800
committerJohn Rigby <john.rigby@linaro.org>2012-06-20 20:12:38 -0600
commitc72530d447f1a53bf3f7e4972d0e95e67edaacdc (patch)
tree547ddcea7bb7cf23e9d8ff9fbec5fe02bbd7393f /security
parent658ebafb7414784597cb1dc6c3fdd868ae3fb728 (diff)
UBUNTU: SAUCE: SECCOMP: Add PR_{GET,SET}_NO_NEW_PRIVS to prevent execve from granting privs
With this set, a lot of dangerous operations (chroot, unshare, etc) become a lot less dangerous because there is no possibility of subverting privileged binaries. This patch completely breaks apparmor. Someone who understands (and uses) apparmor should fix it or at least give me a hint. Signed-off-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Kees Cook <kees@ubuntu.com>
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/domain.c4
-rw-r--r--security/commoncap.c7
-rw-r--r--security/selinux/hooks.c10
3 files changed, 18 insertions, 3 deletions
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 6327685c101..18c88d06e88 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 5d63aac4b90..5bedc1288cb 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -512,14 +512,17 @@ 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 d85b793c932..0b06685787b 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) {