2 * AppArmor security module
4 * This file contains AppArmor task related definitions and mediation
6 * Copyright 2017 Canonical Ltd.
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
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.
19 #include "include/cred.h"
20 #include "include/task.h"
23 * aa_get_task_label - Get another task's label
24 * @task: task to query (NOT NULL)
26 * Returns: counted reference to @task's label
28 struct aa_label
*aa_get_task_label(struct task_struct
*task
)
33 p
= aa_get_newest_label(__aa_task_raw_label(task
));
40 * aa_replace_current_label - replace the current tasks label
41 * @label: new label (NOT NULL)
43 * Returns: 0 or error on failure
45 int aa_replace_current_label(struct aa_label
*label
)
47 struct aa_label
*old
= aa_current_raw_label();
48 struct aa_task_ctx
*ctx
= task_ctx(current
);
56 if (current_cred() != current_real_cred())
59 new = prepare_creds();
63 if (ctx
->nnp
&& label_is_stale(ctx
->nnp
)) {
64 struct aa_label
*tmp
= ctx
->nnp
;
66 ctx
->nnp
= aa_get_newest_label(tmp
);
69 if (unconfined(label
) || (labels_ns(old
) != labels_ns(label
)))
71 * if switching to unconfined or a different label namespace
72 * clear out context state
74 aa_clear_task_ctx_trans(task_ctx(current
));
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
83 aa_put_label(cred_label(new));
84 cred_label(new) = label
;
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
97 int aa_set_current_onexec(struct aa_label
*label
, bool stack
)
99 struct aa_task_ctx
*ctx
= task_ctx(current
);
102 aa_put_label(ctx
->onexec
);
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
114 * Do switch of tasks hat. If the task is currently in a hat
115 * validate the token to match.
117 * Returns: 0 or error on failure
119 int aa_set_current_hat(struct aa_label
*label
, u64 token
)
121 struct aa_task_ctx
*ctx
= task_ctx(current
);
124 new = prepare_creds();
129 if (!ctx
->previous
) {
130 /* transfer refcount */
131 ctx
->previous
= cred_label(new);
133 } else if (ctx
->token
== token
) {
134 aa_put_label(cred_label(new));
136 /* previous_profile && ctx->token != token */
141 cred_label(new) = aa_get_newest_label(label
);
142 /* clear exec on switching context */
143 aa_put_label(ctx
->onexec
);
151 * aa_restore_previous_label - exit from hat context restoring previous label
152 * @token: the token that must be matched to exit hat context
154 * Attempt to return out of a hat to the previous label. The token
155 * must match the stored token value.
157 * Returns: 0 or error of failure
159 int aa_restore_previous_label(u64 token
)
161 struct aa_task_ctx
*ctx
= task_ctx(current
);
164 if (ctx
->token
!= token
)
166 /* ignore restores when there is no saved label */
170 new = prepare_creds();
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
);