Linux Audio

Check our new training course

Loading...
v4.17
 
  1/*
  2 * AppArmor security module
  3 *
  4 * This file contains AppArmor task related definitions and mediation
  5 *
  6 * Copyright 2017 Canonical Ltd.
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License as
 10 * published by the Free Software Foundation, version 2 of the
 11 * License.
 12 *
 13 * TODO
 14 * If a task uses change_hat it currently does not return to the old
 15 * cred or task context but instead creates a new one.  Ideally the task
 16 * should return to the previous cred if it has not been modified.
 17 */
 18
 19#include "include/cred.h"
 20#include "include/task.h"
 21
 22/**
 23 * aa_get_task_label - Get another task's label
 24 * @task: task to query  (NOT NULL)
 25 *
 26 * Returns: counted reference to @task's label
 27 */
 28struct aa_label *aa_get_task_label(struct task_struct *task)
 29{
 30	struct aa_label *p;
 31
 32	rcu_read_lock();
 33	p = aa_get_newest_label(__aa_task_raw_label(task));
 34	rcu_read_unlock();
 35
 36	return p;
 37}
 38
 39/**
 40 * aa_replace_current_label - replace the current tasks label
 41 * @label: new label  (NOT NULL)
 42 *
 43 * Returns: 0 or error on failure
 44 */
 45int aa_replace_current_label(struct aa_label *label)
 46{
 47	struct aa_label *old = aa_current_raw_label();
 48	struct aa_task_ctx *ctx = task_ctx(current);
 49	struct cred *new;
 50
 51	AA_BUG(!label);
 52
 53	if (old == label)
 54		return 0;
 55
 56	if (current_cred() != current_real_cred())
 57		return -EBUSY;
 58
 59	new  = prepare_creds();
 60	if (!new)
 61		return -ENOMEM;
 62
 63	if (ctx->nnp && label_is_stale(ctx->nnp)) {
 64		struct aa_label *tmp = ctx->nnp;
 65
 66		ctx->nnp = aa_get_newest_label(tmp);
 67		aa_put_label(tmp);
 68	}
 69	if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
 70		/*
 71		 * if switching to unconfined or a different label namespace
 72		 * clear out context state
 73		 */
 74		aa_clear_task_ctx_trans(task_ctx(current));
 75
 76	/*
 77	 * be careful switching cred label, when racing replacement it
 78	 * is possible that the cred labels's->proxy->label is the reference
 79	 * keeping @label valid, so make sure to get its reference before
 80	 * dropping the reference on the cred's label
 81	 */
 82	aa_get_label(label);
 83	aa_put_label(cred_label(new));
 84	cred_label(new) = label;
 85
 86	commit_creds(new);
 87	return 0;
 88}
 89
 90
 91/**
 92 * aa_set_current_onexec - set the tasks change_profile to happen onexec
 93 * @label: system label to set at exec  (MAYBE NULL to clear value)
 94 * @stack: whether stacking should be done
 95 * Returns: 0 or error on failure
 96 */
 97int aa_set_current_onexec(struct aa_label *label, bool stack)
 98{
 99	struct aa_task_ctx *ctx = task_ctx(current);
100
101	aa_get_label(label);
102	aa_put_label(ctx->onexec);
103	ctx->onexec = label;
104	ctx->token = stack;
105
106	return 0;
107}
108
109/**
110 * aa_set_current_hat - set the current tasks hat
111 * @label: label to set as the current hat  (NOT NULL)
112 * @token: token value that must be specified to change from the hat
113 *
114 * Do switch of tasks hat.  If the task is currently in a hat
115 * validate the token to match.
116 *
117 * Returns: 0 or error on failure
118 */
119int aa_set_current_hat(struct aa_label *label, u64 token)
120{
121	struct aa_task_ctx *ctx = task_ctx(current);
122	struct cred *new;
123
124	new = prepare_creds();
125	if (!new)
126		return -ENOMEM;
127	AA_BUG(!label);
128
129	if (!ctx->previous) {
130		/* transfer refcount */
131		ctx->previous = cred_label(new);
132		ctx->token = token;
133	} else if (ctx->token == token) {
134		aa_put_label(cred_label(new));
135	} else {
136		/* previous_profile && ctx->token != token */
137		abort_creds(new);
138		return -EACCES;
139	}
140
141	cred_label(new) = aa_get_newest_label(label);
142	/* clear exec on switching context */
143	aa_put_label(ctx->onexec);
144	ctx->onexec = NULL;
145
146	commit_creds(new);
147	return 0;
148}
149
150/**
151 * aa_restore_previous_label - exit from hat context restoring previous label
152 * @token: the token that must be matched to exit hat context
153 *
154 * Attempt to return out of a hat to the previous label.  The token
155 * must match the stored token value.
156 *
157 * Returns: 0 or error of failure
158 */
159int aa_restore_previous_label(u64 token)
160{
161	struct aa_task_ctx *ctx = task_ctx(current);
162	struct cred *new;
163
164	if (ctx->token != token)
165		return -EACCES;
166	/* ignore restores when there is no saved label */
167	if (!ctx->previous)
168		return 0;
169
170	new = prepare_creds();
171	if (!new)
172		return -ENOMEM;
173
174	aa_put_label(cred_label(new));
175	cred_label(new) = aa_get_newest_label(ctx->previous);
176	AA_BUG(!cred_label(new));
177	/* clear exec && prev information when restoring to previous context */
178	aa_clear_task_ctx_trans(ctx);
179
180	commit_creds(new);
181
182	return 0;
183}
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * AppArmor security module
  4 *
  5 * This file contains AppArmor task related definitions and mediation
  6 *
  7 * Copyright 2017 Canonical Ltd.
  8 *
 
 
 
 
 
  9 * TODO
 10 * If a task uses change_hat it currently does not return to the old
 11 * cred or task context but instead creates a new one.  Ideally the task
 12 * should return to the previous cred if it has not been modified.
 13 */
 14
 15#include "include/cred.h"
 16#include "include/task.h"
 17
 18/**
 19 * aa_get_task_label - Get another task's label
 20 * @task: task to query  (NOT NULL)
 21 *
 22 * Returns: counted reference to @task's label
 23 */
 24struct aa_label *aa_get_task_label(struct task_struct *task)
 25{
 26	struct aa_label *p;
 27
 28	rcu_read_lock();
 29	p = aa_get_newest_label(__aa_task_raw_label(task));
 30	rcu_read_unlock();
 31
 32	return p;
 33}
 34
 35/**
 36 * aa_replace_current_label - replace the current tasks label
 37 * @label: new label  (NOT NULL)
 38 *
 39 * Returns: 0 or error on failure
 40 */
 41int aa_replace_current_label(struct aa_label *label)
 42{
 43	struct aa_label *old = aa_current_raw_label();
 44	struct aa_task_ctx *ctx = task_ctx(current);
 45	struct cred *new;
 46
 47	AA_BUG(!label);
 48
 49	if (old == label)
 50		return 0;
 51
 52	if (current_cred() != current_real_cred())
 53		return -EBUSY;
 54
 55	new  = prepare_creds();
 56	if (!new)
 57		return -ENOMEM;
 58
 59	if (ctx->nnp && label_is_stale(ctx->nnp)) {
 60		struct aa_label *tmp = ctx->nnp;
 61
 62		ctx->nnp = aa_get_newest_label(tmp);
 63		aa_put_label(tmp);
 64	}
 65	if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
 66		/*
 67		 * if switching to unconfined or a different label namespace
 68		 * clear out context state
 69		 */
 70		aa_clear_task_ctx_trans(task_ctx(current));
 71
 72	/*
 73	 * be careful switching cred label, when racing replacement it
 74	 * is possible that the cred labels's->proxy->label is the reference
 75	 * keeping @label valid, so make sure to get its reference before
 76	 * dropping the reference on the cred's label
 77	 */
 78	aa_get_label(label);
 79	aa_put_label(cred_label(new));
 80	set_cred_label(new, label);
 81
 82	commit_creds(new);
 83	return 0;
 84}
 85
 86
 87/**
 88 * aa_set_current_onexec - set the tasks change_profile to happen onexec
 89 * @label: system label to set at exec  (MAYBE NULL to clear value)
 90 * @stack: whether stacking should be done
 91 * Returns: 0 or error on failure
 92 */
 93int aa_set_current_onexec(struct aa_label *label, bool stack)
 94{
 95	struct aa_task_ctx *ctx = task_ctx(current);
 96
 97	aa_get_label(label);
 98	aa_put_label(ctx->onexec);
 99	ctx->onexec = label;
100	ctx->token = stack;
101
102	return 0;
103}
104
105/**
106 * aa_set_current_hat - set the current tasks hat
107 * @label: label to set as the current hat  (NOT NULL)
108 * @token: token value that must be specified to change from the hat
109 *
110 * Do switch of tasks hat.  If the task is currently in a hat
111 * validate the token to match.
112 *
113 * Returns: 0 or error on failure
114 */
115int aa_set_current_hat(struct aa_label *label, u64 token)
116{
117	struct aa_task_ctx *ctx = task_ctx(current);
118	struct cred *new;
119
120	new = prepare_creds();
121	if (!new)
122		return -ENOMEM;
123	AA_BUG(!label);
124
125	if (!ctx->previous) {
126		/* transfer refcount */
127		ctx->previous = cred_label(new);
128		ctx->token = token;
129	} else if (ctx->token == token) {
130		aa_put_label(cred_label(new));
131	} else {
132		/* previous_profile && ctx->token != token */
133		abort_creds(new);
134		return -EACCES;
135	}
136
137	set_cred_label(new, aa_get_newest_label(label));
138	/* clear exec on switching context */
139	aa_put_label(ctx->onexec);
140	ctx->onexec = NULL;
141
142	commit_creds(new);
143	return 0;
144}
145
146/**
147 * aa_restore_previous_label - exit from hat context restoring previous label
148 * @token: the token that must be matched to exit hat context
149 *
150 * Attempt to return out of a hat to the previous label.  The token
151 * must match the stored token value.
152 *
153 * Returns: 0 or error of failure
154 */
155int aa_restore_previous_label(u64 token)
156{
157	struct aa_task_ctx *ctx = task_ctx(current);
158	struct cred *new;
159
160	if (ctx->token != token)
161		return -EACCES;
162	/* ignore restores when there is no saved label */
163	if (!ctx->previous)
164		return 0;
165
166	new = prepare_creds();
167	if (!new)
168		return -ENOMEM;
169
170	aa_put_label(cred_label(new));
171	set_cred_label(new, aa_get_newest_label(ctx->previous));
172	AA_BUG(!cred_label(new));
173	/* clear exec && prev information when restoring to previous context */
174	aa_clear_task_ctx_trans(ctx);
175
176	commit_creds(new);
177
178	return 0;
179}