summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-07 20:35:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-07 20:35:29 -0700
commit828f4257d1d33aed0f9ef82982dcb8ace8b7fe86 (patch)
treece9e1fc4eaae2c66e8a5bba25579c32c229352b4 /security
parent44ccba3f7b230af1bd7ebe173cbf5803df1df486 (diff)
parentfe8993b3a05cbba6318a54e0f85901aaea6fc244 (diff)
downloadlinux-828f4257d1d33aed0f9ef82982dcb8ace8b7fe86.tar.bz2
Merge tag 'secureexec-v4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull secureexec update from Kees Cook: "This series has the ultimate goal of providing a sane stack rlimit when running set*id processes. To do this, the bprm_secureexec LSM hook is collapsed into the bprm_set_creds hook so the secureexec-ness of an exec can be determined early enough to make decisions about rlimits and the resulting memory layouts. Other logic acting on the secureexec-ness of an exec is similarly consolidated. Capabilities needed some special handling, but the refactoring removed other special handling, so that was a wash" * tag 'secureexec-v4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: exec: Consolidate pdeath_signal clearing exec: Use sane stack rlimit under secureexec exec: Consolidate dumpability logic smack: Remove redundant pdeath_signal clearing exec: Use secureexec for clearing pdeath_signal exec: Use secureexec for setting dumpability LSM: drop bprm_secureexec hook commoncap: Move cap_elevated calculation into bprm_set_creds commoncap: Refactor to remove bprm_secureexec hook smack: Refactor to remove bprm_secureexec hook selinux: Refactor to remove bprm_secureexec hook apparmor: Refactor to remove bprm_secureexec hook binfmt: Introduce secureexec flag exec: Correct comments about "point of no return" exec: Rename bprm->cred_prepared to called_set_creds
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/domain.c21
-rw-r--r--security/apparmor/include/domain.h1
-rw-r--r--security/apparmor/include/file.h3
-rw-r--r--security/apparmor/lsm.c1
-rw-r--r--security/commoncap.c50
-rw-r--r--security/security.c5
-rw-r--r--security/selinux/hooks.c26
-rw-r--r--security/smack/smack_lsm.c34
-rw-r--r--security/tomoyo/tomoyo.c2
9 files changed, 23 insertions, 120 deletions
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index d0594446ae3f..17a601c67b62 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -758,7 +758,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
file_inode(bprm->file)->i_mode
};
- if (bprm->cred_prepared)
+ if (bprm->called_set_creds)
return 0;
ctx = cred_ctx(bprm->cred);
@@ -807,7 +807,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
aa_label_printk(new, GFP_ATOMIC);
dbg_printk("\n");
}
- bprm->unsafe |= AA_SECURE_X_NEEDED;
+ bprm->secureexec = 1;
}
if (label->proxy != new->proxy) {
@@ -843,23 +843,6 @@ audit:
goto done;
}
-/**
- * apparmor_bprm_secureexec - determine if secureexec is needed
- * @bprm: binprm for exec (NOT NULL)
- *
- * Returns: %1 if secureexec is needed else %0
- */
-int apparmor_bprm_secureexec(struct linux_binprm *bprm)
-{
- /* the decision to use secure exec is computed in set_creds
- * and stored in bprm->unsafe.
- */
- if (bprm->unsafe & AA_SECURE_X_NEEDED)
- return 1;
-
- return 0;
-}
-
/*
* Functions for self directed profile change
*/
diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
index bab5810b6e9a..24c5976d6143 100644
--- a/security/apparmor/include/domain.h
+++ b/security/apparmor/include/domain.h
@@ -30,7 +30,6 @@ struct aa_domain {
#define AA_CHANGE_STACK 8
int apparmor_bprm_set_creds(struct linux_binprm *bprm);
-int apparmor_bprm_secureexec(struct linux_binprm *bprm);
void aa_free_domain_entries(struct aa_domain *domain);
int aa_change_hat(const char *hats[], int count, u64 token, int flags);
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
index 001e40073ff9..4c2c8ac8842f 100644
--- a/security/apparmor/include/file.h
+++ b/security/apparmor/include/file.h
@@ -101,9 +101,6 @@ static inline struct aa_label *aa_get_file_label(struct aa_file_ctx *ctx)
#define AA_X_INHERIT 0x4000
#define AA_X_UNCONFINED 0x8000
-/* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */
-#define AA_SECURE_X_NEEDED 0x8000
-
/* need to make conditional which ones are being set */
struct path_cond {
kuid_t uid;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 867bcd154c7e..7a82c0f61452 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -694,7 +694,6 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(bprm_set_creds, apparmor_bprm_set_creds),
LSM_HOOK_INIT(bprm_committing_creds, apparmor_bprm_committing_creds),
LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds),
- LSM_HOOK_INIT(bprm_secureexec, apparmor_bprm_secureexec),
LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
};
diff --git a/security/commoncap.c b/security/commoncap.c
index 7abebd782d5e..d8e26fb9781d 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -285,15 +285,6 @@ int cap_capset(struct cred *new,
return 0;
}
-/*
- * Clear proposed capability sets for execve().
- */
-static inline void bprm_clear_caps(struct linux_binprm *bprm)
-{
- cap_clear(bprm->cred->cap_permitted);
- bprm->cap_effective = false;
-}
-
/**
* cap_inode_need_killpriv - Determine if inode change affects privileges
* @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV
@@ -443,7 +434,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
int rc = 0;
struct cpu_vfs_cap_data vcaps;
- bprm_clear_caps(bprm);
+ cap_clear(bprm->cred->cap_permitted);
if (!file_caps_enabled)
return 0;
@@ -476,7 +467,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
out:
if (rc)
- bprm_clear_caps(bprm);
+ cap_clear(bprm->cred->cap_permitted);
return rc;
}
@@ -585,8 +576,6 @@ skip:
if (WARN_ON(!cap_ambient_invariant_ok(new)))
return -EPERM;
- bprm->cap_effective = effective;
-
/*
* Audit candidate if current->cap_effective is set
*
@@ -614,33 +603,17 @@ skip:
if (WARN_ON(!cap_ambient_invariant_ok(new)))
return -EPERM;
- return 0;
-}
-
-/**
- * cap_bprm_secureexec - Determine whether a secure execution is required
- * @bprm: The execution parameters
- *
- * Determine whether a secure execution is required, return 1 if it is, and 0
- * if it is not.
- *
- * The credentials have been committed by this point, and so are no longer
- * available through @bprm->cred.
- */
-int cap_bprm_secureexec(struct linux_binprm *bprm)
-{
- const struct cred *cred = current_cred();
- kuid_t root_uid = make_kuid(cred->user_ns, 0);
-
- if (!uid_eq(cred->uid, root_uid)) {
- if (bprm->cap_effective)
- return 1;
- if (!cap_issubset(cred->cap_permitted, cred->cap_ambient))
- return 1;
+ /* Check for privilege-elevated exec. */
+ bprm->cap_elevated = 0;
+ if (is_setid) {
+ bprm->cap_elevated = 1;
+ } else if (!uid_eq(new->uid, root_uid)) {
+ if (effective ||
+ !cap_issubset(new->cap_permitted, new->cap_ambient))
+ bprm->cap_elevated = 1;
}
- return (!uid_eq(cred->euid, cred->uid) ||
- !gid_eq(cred->egid, cred->gid));
+ return 0;
}
/**
@@ -1079,7 +1052,6 @@ struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(capget, cap_capget),
LSM_HOOK_INIT(capset, cap_capset),
LSM_HOOK_INIT(bprm_set_creds, cap_bprm_set_creds),
- LSM_HOOK_INIT(bprm_secureexec, cap_bprm_secureexec),
LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv),
LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv),
LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
diff --git a/security/security.c b/security/security.c
index 30132378d103..afc34f46c6c5 100644
--- a/security/security.c
+++ b/security/security.c
@@ -351,11 +351,6 @@ void security_bprm_committed_creds(struct linux_binprm *bprm)
call_void_hook(bprm_committed_creds, bprm);
}
-int security_bprm_secureexec(struct linux_binprm *bprm)
-{
- return call_int_hook(bprm_secureexec, 0, bprm);
-}
-
int security_sb_alloc(struct super_block *sb)
{
return call_int_hook(sb_alloc_security, 0, sb);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2f2e1338cd3d..ad3b0f53ede0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2356,7 +2356,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
/* SELinux context only depends on initial program or script and not
* the script interpreter */
- if (bprm->cred_prepared)
+ if (bprm->called_set_creds)
return 0;
old_tsec = current_security();
@@ -2442,30 +2442,17 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
/* Clear any possibly unsafe personality bits on exec: */
bprm->per_clear |= PER_CLEAR_ON_SETID;
- }
-
- return 0;
-}
-
-static int selinux_bprm_secureexec(struct linux_binprm *bprm)
-{
- const struct task_security_struct *tsec = current_security();
- u32 sid, osid;
- int atsecure = 0;
-
- sid = tsec->sid;
- osid = tsec->osid;
- if (osid != sid) {
/* Enable secure mode for SIDs transitions unless
the noatsecure permission is granted between
the two SIDs, i.e. ahp returns 0. */
- atsecure = avc_has_perm(osid, sid,
- SECCLASS_PROCESS,
- PROCESS__NOATSECURE, NULL);
+ rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
+ SECCLASS_PROCESS, PROCESS__NOATSECURE,
+ NULL);
+ bprm->secureexec |= !!rc;
}
- return !!atsecure;
+ return 0;
}
static int match_file(const void *p, struct file *file, unsigned fd)
@@ -6266,7 +6253,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
- LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 463af86812c7..319add31b4a4 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -917,7 +917,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
struct superblock_smack *sbsp;
int rc;
- if (bprm->cred_prepared)
+ if (bprm->called_set_creds)
return 0;
isp = inode->i_security;
@@ -950,35 +950,9 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
bsp->smk_task = isp->smk_task;
bprm->per_clear |= PER_CLEAR_ON_SETID;
- return 0;
-}
-
-/**
- * smack_bprm_committing_creds - Prepare to install the new credentials
- * from bprm.
- *
- * @bprm: binprm for exec
- */
-static void smack_bprm_committing_creds(struct linux_binprm *bprm)
-{
- struct task_smack *bsp = bprm->cred->security;
-
+ /* Decide if this is a secure exec. */
if (bsp->smk_task != bsp->smk_forked)
- current->pdeath_signal = 0;
-}
-
-/**
- * smack_bprm_secureexec - Return the decision to use secureexec.
- * @bprm: binprm for exec
- *
- * Returns 0 on success.
- */
-static int smack_bprm_secureexec(struct linux_binprm *bprm)
-{
- struct task_smack *tsp = current_security();
-
- if (tsp->smk_task != tsp->smk_forked)
- return 1;
+ bprm->secureexec = 1;
return 0;
}
@@ -4645,8 +4619,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(sb_parse_opts_str, smack_parse_opts_str),
LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds),
- LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds),
- LSM_HOOK_INIT(bprm_secureexec, smack_bprm_secureexec),
LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security),
LSM_HOOK_INIT(inode_free_security, smack_inode_free_security),
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 130b4fa4f65f..d25b705360e0 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -76,7 +76,7 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
* Do only if this function is called for the first time of an execve
* operation.
*/
- if (bprm->cred_prepared)
+ if (bprm->called_set_creds)
return 0;
#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
/*