diff options
Diffstat (limited to 'security/apparmor/context.c')
| -rw-r--r-- | security/apparmor/context.c | 56 | 
1 files changed, 31 insertions, 25 deletions
diff --git a/security/apparmor/context.c b/security/apparmor/context.c index 8a9b5027c81..3064c6ced87 100644 --- a/security/apparmor/context.c +++ b/security/apparmor/context.c @@ -69,6 +69,23 @@ void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)  }  /** + * aa_get_task_profile - Get another task's profile + * @task: task to query  (NOT NULL) + * + * Returns: counted reference to @task's profile + */ +struct aa_profile *aa_get_task_profile(struct task_struct *task) +{ +	struct aa_profile *p; + +	rcu_read_lock(); +	p = aa_get_profile(__aa_task_profile(task)); +	rcu_read_unlock(); + +	return p; +} + +/**   * aa_replace_current_profile - replace the current tasks profiles   * @profile: new profile  (NOT NULL)   * @@ -76,7 +93,7 @@ void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)   */  int aa_replace_current_profile(struct aa_profile *profile)  { -	struct aa_task_cxt *cxt = current_cred()->security; +	struct aa_task_cxt *cxt = current_cxt();  	struct cred *new;  	BUG_ON(!profile); @@ -87,21 +104,17 @@ int aa_replace_current_profile(struct aa_profile *profile)  	if (!new)  		return -ENOMEM; -	cxt = new->security; -	if (unconfined(profile) || (cxt->profile->ns != profile->ns)) { +	cxt = cred_cxt(new); +	if (unconfined(profile) || (cxt->profile->ns != profile->ns))  		/* if switching to unconfined or a different profile namespace  		 * clear out context state  		 */ -		aa_put_profile(cxt->previous); -		aa_put_profile(cxt->onexec); -		cxt->previous = NULL; -		cxt->onexec = NULL; -		cxt->token = 0; -	} +		aa_clear_task_cxt_trans(cxt); +  	/* be careful switching cxt->profile, when racing replacement it -	 * is possible that cxt->profile->replacedby is the reference keeping -	 * @profile valid, so make sure to get its reference before dropping -	 * the reference on cxt->profile */ +	 * is possible that cxt->profile->replacedby->profile is the reference +	 * keeping @profile valid, so make sure to get its reference before +	 * dropping the reference on cxt->profile */  	aa_get_profile(profile);  	aa_put_profile(cxt->profile);  	cxt->profile = profile; @@ -123,7 +136,7 @@ int aa_set_current_onexec(struct aa_profile *profile)  	if (!new)  		return -ENOMEM; -	cxt = new->security; +	cxt = cred_cxt(new);  	aa_get_profile(profile);  	aa_put_profile(cxt->onexec);  	cxt->onexec = profile; @@ -150,7 +163,7 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token)  		return -ENOMEM;  	BUG_ON(!profile); -	cxt = new->security; +	cxt = cred_cxt(new);  	if (!cxt->previous) {  		/* transfer refcount */  		cxt->previous = cxt->profile; @@ -162,7 +175,7 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token)  		abort_creds(new);  		return -EACCES;  	} -	cxt->profile = aa_get_profile(aa_newest_version(profile)); +	cxt->profile = aa_get_newest_profile(profile);  	/* clear exec on switching context */  	aa_put_profile(cxt->onexec);  	cxt->onexec = NULL; @@ -187,7 +200,7 @@ int aa_restore_previous_profile(u64 token)  	if (!new)  		return -ENOMEM; -	cxt = new->security; +	cxt = cred_cxt(new);  	if (cxt->token != token) {  		abort_creds(new);  		return -EACCES; @@ -199,17 +212,10 @@ int aa_restore_previous_profile(u64 token)  	}  	aa_put_profile(cxt->profile); -	cxt->profile = aa_newest_version(cxt->previous); +	cxt->profile = aa_get_newest_profile(cxt->previous);  	BUG_ON(!cxt->profile); -	if (unlikely(cxt->profile != cxt->previous)) { -		aa_get_profile(cxt->profile); -		aa_put_profile(cxt->previous); -	}  	/* clear exec && prev information when restoring to previous context */ -	cxt->previous = NULL; -	cxt->token = 0; -	aa_put_profile(cxt->onexec); -	cxt->onexec = NULL; +	aa_clear_task_cxt_trans(cxt);  	commit_creds(new);  	return 0;  | 
