1 // SPDX-License-Identifier: GPL-2.0-only
3 * AppArmor security module
5 * This file contains AppArmor task related definitions and mediation
7 * Copyright 2017 Canonical Ltd.
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.
15 #include <linux/gfp.h>
16 #include <linux/ptrace.h>
18 #include "include/audit.h"
19 #include "include/cred.h"
20 #include "include/policy.h"
21 #include "include/task.h"
24 * aa_get_task_label - Get another task's label
25 * @task: task to query (NOT NULL)
27 * Returns: counted reference to @task's label
29 struct aa_label
*aa_get_task_label(struct task_struct
*task
)
34 p
= aa_get_newest_cred_label(__task_cred(task
));
41 * aa_replace_current_label - replace the current tasks label
42 * @label: new label (NOT NULL)
44 * Returns: 0 or error on failure
46 int aa_replace_current_label(struct aa_label
*label
)
48 struct aa_label
*old
= aa_current_raw_label();
49 struct aa_task_ctx
*ctx
= task_ctx(current
);
57 if (current_cred() != current_real_cred())
60 new = prepare_creds();
64 if (ctx
->nnp
&& label_is_stale(ctx
->nnp
)) {
65 struct aa_label
*tmp
= ctx
->nnp
;
67 ctx
->nnp
= aa_get_newest_label(tmp
);
70 if (unconfined(label
) || (labels_ns(old
) != labels_ns(label
)))
72 * if switching to unconfined or a different label namespace
73 * clear out context state
75 aa_clear_task_ctx_trans(task_ctx(current
));
78 * be careful switching cred label, when racing replacement it
79 * is possible that the cred labels's->proxy->label is the reference
80 * keeping @label valid, so make sure to get its reference before
81 * dropping the reference on the cred's label
84 aa_put_label(cred_label(new));
85 set_cred_label(new, label
);
93 * aa_set_current_onexec - set the tasks change_profile to happen onexec
94 * @label: system label to set at exec (MAYBE NULL to clear value)
95 * @stack: whether stacking should be done
97 void 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
);
108 * aa_set_current_hat - set the current tasks hat
109 * @label: label to set as the current hat (NOT NULL)
110 * @token: token value that must be specified to change from the hat
112 * Do switch of tasks hat. If the task is currently in a hat
113 * validate the token to match.
115 * Returns: 0 or error on failure
117 int aa_set_current_hat(struct aa_label
*label
, u64 token
)
119 struct aa_task_ctx
*ctx
= task_ctx(current
);
122 new = prepare_creds();
127 if (!ctx
->previous
) {
128 /* transfer refcount */
129 ctx
->previous
= cred_label(new);
131 } else if (ctx
->token
== token
) {
132 aa_put_label(cred_label(new));
134 /* previous_profile && ctx->token != token */
139 set_cred_label(new, aa_get_newest_label(label
));
140 /* clear exec on switching context */
141 aa_put_label(ctx
->onexec
);
149 * aa_restore_previous_label - exit from hat context restoring previous label
150 * @token: the token that must be matched to exit hat context
152 * Attempt to return out of a hat to the previous label. The token
153 * must match the stored token value.
155 * Returns: 0 or error of failure
157 int aa_restore_previous_label(u64 token
)
159 struct aa_task_ctx
*ctx
= task_ctx(current
);
162 if (ctx
->token
!= token
)
164 /* ignore restores when there is no saved label */
168 new = prepare_creds();
172 aa_put_label(cred_label(new));
173 set_cred_label(new, aa_get_newest_label(ctx
->previous
));
174 AA_BUG(!cred_label(new));
175 /* clear exec && prev information when restoring to previous context */
176 aa_clear_task_ctx_trans(ctx
);
184 * audit_ptrace_mask - convert mask to permission string
185 * @mask: permission mask to convert
187 * Returns: pointer to static string
189 static const char *audit_ptrace_mask(u32 mask
)
198 case AA_MAY_BE_TRACED
:
204 /* call back to audit ptrace fields */
205 static void audit_ptrace_cb(struct audit_buffer
*ab
, void *va
)
207 struct common_audit_data
*sa
= va
;
208 struct apparmor_audit_data
*ad
= aad(sa
);
210 if (ad
->request
& AA_PTRACE_PERM_MASK
) {
211 audit_log_format(ab
, " requested_mask=\"%s\"",
212 audit_ptrace_mask(ad
->request
));
214 if (ad
->denied
& AA_PTRACE_PERM_MASK
) {
215 audit_log_format(ab
, " denied_mask=\"%s\"",
216 audit_ptrace_mask(ad
->denied
));
219 audit_log_format(ab
, " peer=");
220 aa_label_xaudit(ab
, labels_ns(ad
->subj_label
), ad
->peer
,
221 FLAGS_NONE
, GFP_ATOMIC
);
224 /* assumes check for RULE_MEDIATES is already done */
225 /* TODO: conditionals */
226 static int profile_ptrace_perm(const struct cred
*cred
,
227 struct aa_profile
*profile
,
228 struct aa_label
*peer
, u32 request
,
229 struct apparmor_audit_data
*ad
)
231 struct aa_ruleset
*rules
= list_first_entry(&profile
->rules
,
232 typeof(*rules
), list
);
233 struct aa_perms perms
= { };
235 ad
->subj_cred
= cred
;
237 aa_profile_match_label(profile
, rules
, peer
, AA_CLASS_PTRACE
, request
,
239 aa_apply_modes_to_perms(profile
, &perms
);
240 return aa_check_perms(profile
, &perms
, request
, ad
, audit_ptrace_cb
);
243 static int profile_tracee_perm(const struct cred
*cred
,
244 struct aa_profile
*tracee
,
245 struct aa_label
*tracer
, u32 request
,
246 struct apparmor_audit_data
*ad
)
248 if (profile_unconfined(tracee
) || unconfined(tracer
) ||
249 !ANY_RULE_MEDIATES(&tracee
->rules
, AA_CLASS_PTRACE
))
252 return profile_ptrace_perm(cred
, tracee
, tracer
, request
, ad
);
255 static int profile_tracer_perm(const struct cred
*cred
,
256 struct aa_profile
*tracer
,
257 struct aa_label
*tracee
, u32 request
,
258 struct apparmor_audit_data
*ad
)
260 if (profile_unconfined(tracer
))
263 if (ANY_RULE_MEDIATES(&tracer
->rules
, AA_CLASS_PTRACE
))
264 return profile_ptrace_perm(cred
, tracer
, tracee
, request
, ad
);
266 /* profile uses the old style capability check for ptrace */
267 if (&tracer
->label
== tracee
)
270 ad
->subj_label
= &tracer
->label
;
273 ad
->error
= aa_capable(cred
, &tracer
->label
, CAP_SYS_PTRACE
,
276 return aa_audit(AUDIT_APPARMOR_AUTO
, tracer
, ad
, audit_ptrace_cb
);
280 * aa_may_ptrace - test if tracer task can trace the tracee
281 * @tracer_cred: cred of task doing the tracing (NOT NULL)
282 * @tracer: label of the task doing the tracing (NOT NULL)
283 * @tracee_cred: cred of task to be traced
284 * @tracee: task label to be traced
285 * @request: permission request
287 * Returns: %0 else error code if permission denied or error
289 int aa_may_ptrace(const struct cred
*tracer_cred
, struct aa_label
*tracer
,
290 const struct cred
*tracee_cred
, struct aa_label
*tracee
,
293 struct aa_profile
*profile
;
294 u32 xrequest
= request
<< PTRACE_PERM_SHIFT
;
295 DEFINE_AUDIT_DATA(sa
, LSM_AUDIT_DATA_NONE
, AA_CLASS_PTRACE
, OP_PTRACE
);
297 return xcheck_labels(tracer
, tracee
, profile
,
298 profile_tracer_perm(tracer_cred
, profile
, tracee
,
300 profile_tracee_perm(tracee_cred
, profile
, tracer
,
304 /* call back to audit ptrace fields */
305 static void audit_ns_cb(struct audit_buffer
*ab
, void *va
)
307 struct apparmor_audit_data
*ad
= aad_of_va(va
);
309 if (ad
->request
& AA_USERNS_CREATE
)
310 audit_log_format(ab
, " requested=\"userns_create\"");
312 if (ad
->denied
& AA_USERNS_CREATE
)
313 audit_log_format(ab
, " denied=\"userns_create\"");
316 int aa_profile_ns_perm(struct aa_profile
*profile
,
317 struct apparmor_audit_data
*ad
,
320 struct aa_perms perms
= { };
323 ad
->subj_label
= &profile
->label
;
324 ad
->request
= request
;
326 if (!profile_unconfined(profile
)) {
327 struct aa_ruleset
*rules
= list_first_entry(&profile
->rules
,
332 state
= RULE_MEDIATES(rules
, ad
->class);
334 /* TODO: add flag to complain about unmediated */
336 perms
= *aa_lookup_perms(rules
->policy
, state
);
337 aa_apply_modes_to_perms(profile
, &perms
);
338 error
= aa_check_perms(profile
, &perms
, request
, ad
,