提交 ee67ae7e 编写于 作者: K Kees Cook

commoncap: Move cap_elevated calculation into bprm_set_creds

Instead of a separate function, open-code the cap_elevated test, which
lets us entirely remove bprm->cap_effective (to use the local "effective"
variable instead), and more accurately examine euid/egid changes via the
existing local "is_setid".

The following LTP tests were run to validate the changes:

	# ./runltp -f syscalls -s cap
	# ./runltp -f securebits
	# ./runltp -f cap_bounds
	# ./runltp -f filecaps

All kernel selftests for capabilities and exec continue to pass as well.
Signed-off-by: NKees Cook <keescook@chromium.org>
Reviewed-by: NJames Morris <james.l.morris@oracle.com>
Acked-by: NSerge Hallyn <serge@hallyn.com>
Reviewed-by: NAndy Lutomirski <luto@kernel.org>
上级 46d98eb4
...@@ -31,9 +31,6 @@ struct linux_binprm { ...@@ -31,9 +31,6 @@ struct linux_binprm {
* binfmt_script/misc). * binfmt_script/misc).
*/ */
called_set_creds:1, called_set_creds:1,
cap_effective:1,/* true if has elevated effective capabilities,
* false if not; except for init which inherits
* its parent's caps anyway */
/* /*
* True if most recent call to the commoncaps bprm_set_creds * True if most recent call to the commoncaps bprm_set_creds
* hook (due to multiple prepare_binprm() calls from the * hook (due to multiple prepare_binprm() calls from the
......
...@@ -285,15 +285,6 @@ int cap_capset(struct cred *new, ...@@ -285,15 +285,6 @@ int cap_capset(struct cred *new,
return 0; 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 * cap_inode_need_killpriv - Determine if inode change affects privileges
* @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV * @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 ...@@ -443,7 +434,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
int rc = 0; int rc = 0;
struct cpu_vfs_cap_data vcaps; struct cpu_vfs_cap_data vcaps;
bprm_clear_caps(bprm); cap_clear(bprm->cred->cap_permitted);
if (!file_caps_enabled) if (!file_caps_enabled)
return 0; return 0;
...@@ -476,13 +467,11 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c ...@@ -476,13 +467,11 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
out: out:
if (rc) if (rc)
bprm_clear_caps(bprm); cap_clear(bprm->cred->cap_permitted);
return rc; return rc;
} }
static int is_secureexec(struct linux_binprm *bprm);
/** /**
* cap_bprm_set_creds - Set up the proposed credentials for execve(). * cap_bprm_set_creds - Set up the proposed credentials for execve().
* @bprm: The execution parameters, including the proposed creds * @bprm: The execution parameters, including the proposed creds
...@@ -587,8 +576,6 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) ...@@ -587,8 +576,6 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
if (WARN_ON(!cap_ambient_invariant_ok(new))) if (WARN_ON(!cap_ambient_invariant_ok(new)))
return -EPERM; return -EPERM;
bprm->cap_effective = effective;
/* /*
* Audit candidate if current->cap_effective is set * Audit candidate if current->cap_effective is set
* *
...@@ -617,35 +604,16 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) ...@@ -617,35 +604,16 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
return -EPERM; return -EPERM;
/* Check for privilege-elevated exec. */ /* Check for privilege-elevated exec. */
bprm->cap_elevated = is_secureexec(bprm); bprm->cap_elevated = 0;
if (is_setid) {
return 0; bprm->cap_elevated = 1;
} } else if (!uid_eq(new->uid, root_uid)) {
if (effective ||
/** !cap_issubset(new->cap_permitted, new->cap_ambient))
* is_secureexec - Determine whether a secure execution is required bprm->cap_elevated = 1;
* @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.
*/
static int is_secureexec(struct linux_binprm *bprm)
{
const struct cred *cred = bprm->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;
} }
return (!uid_eq(cred->euid, cred->uid) || return 0;
!gid_eq(cred->egid, cred->gid));
} }
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册