diff options
Diffstat (limited to 'security/apparmor/domain.c')
| -rw-r--r-- | security/apparmor/domain.c | 35 | 
1 files changed, 35 insertions, 0 deletions
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 6327685c101..b81ea10a17a 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -394,6 +394,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)  			new_profile = find_attach(ns, &ns->base.profiles, name);  		if (!new_profile)  			goto cleanup; +		/* +		 * NOTE: Domain transitions from unconfined are allowed +		 * even when no_new_privs is set because this aways results +		 * in a further reduction of permissions. +		 */  		goto apply;  	} @@ -455,6 +460,16 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)  		/* fail exec */  		error = -EACCES; +	/* +	 * Policy has specified a domain transition, if no_new_privs then +	 * fail the exec. +	 */ +	if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) { +		aa_put_profile(new_profile); +		error = -EPERM; +		goto cleanup; +	} +  	if (!new_profile)  		goto audit; @@ -609,6 +624,14 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)  	const char *target = NULL, *info = NULL;  	int error = 0; +	/* +	 * Fail explicitly requested domain transitions if no_new_privs. +	 * There is no exception for unconfined as change_hat is not +	 * available. +	 */ +	if (current->no_new_privs) +		return -EPERM; +  	/* released below */  	cred = get_current_cred();  	cxt = cred->security; @@ -750,6 +773,18 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,  	cxt = cred->security;  	profile = aa_cred_profile(cred); +	/* +	 * Fail explicitly requested domain transitions if no_new_privs +	 * and not unconfined. +	 * Domain transitions from unconfined are allowed even when +	 * no_new_privs is set because this aways results in a reduction +	 * of permissions. +	 */ +	if (current->no_new_privs && !unconfined(profile)) { +		put_cred(cred); +		return -EPERM; +	} +  	if (ns_name) {  		/* released below */  		ns = aa_find_namespace(profile->ns, ns_name);  |