xref: /linux/security/apparmor/domain.c (revision 8fefe68784ae1606e11a5c65c04167c3b95051a0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * AppArmor security module
4  *
5  * This file contains AppArmor policy attachment and domain transitions
6  *
7  * Copyright (C) 2002-2008 Novell/SUSE
8  * Copyright 2009-2010 Canonical Ltd.
9  */
10 
11 #include <linux/errno.h>
12 #include <linux/fs.h>
13 #include <linux/file.h>
14 #include <linux/mount.h>
15 #include <linux/mutex.h>
16 #include <linux/syscalls.h>
17 #include <linux/personality.h>
18 #include <linux/xattr.h>
19 #include <linux/user_namespace.h>
20 
21 #include "include/audit.h"
22 #include "include/apparmorfs.h"
23 #include "include/cred.h"
24 #include "include/domain.h"
25 #include "include/file.h"
26 #include "include/ipc.h"
27 #include "include/lib.h"
28 #include "include/match.h"
29 #include "include/path.h"
30 #include "include/policy.h"
31 #include "include/policy_ns.h"
32 
33 static const char * const CONFLICTING_ATTACH_STR = "conflicting profile attachments";
34 static const char * const CONFLICTING_ATTACH_STR_IX =
35 	"conflicting profile attachments - ix fallback";
36 static const char * const CONFLICTING_ATTACH_STR_UX =
37 	"conflicting profile attachments - ux fallback";
38 
39 /**
40  * may_change_ptraced_domain - check if can change profile on ptraced task
41  * @to_cred: cred of task changing domain
42  * @to_label: profile to change to  (NOT NULL)
43  * @info: message if there is an error
44  *
45  * Check if current is ptraced and if so if the tracing task is allowed
46  * to trace the new domain
47  *
48  * Returns: %0 or error if change not allowed
49  */
may_change_ptraced_domain(const struct cred * to_cred,struct aa_label * to_label,const char ** info)50 static int may_change_ptraced_domain(const struct cred *to_cred,
51 				     struct aa_label *to_label,
52 				     const char **info)
53 {
54 	struct task_struct *tracer;
55 	struct aa_label *tracerl = NULL;
56 	const struct cred *tracer_cred = NULL;
57 
58 	int error = 0;
59 
60 	rcu_read_lock();
61 	tracer = ptrace_parent(current);
62 	if (tracer) {
63 		/* released below */
64 		tracerl = aa_get_task_label(tracer);
65 		tracer_cred = get_task_cred(tracer);
66 	}
67 	/* not ptraced */
68 	if (!tracer || unconfined(tracerl))
69 		goto out;
70 
71 	error = aa_may_ptrace(tracer_cred, tracerl, to_cred, to_label,
72 			      PTRACE_MODE_ATTACH);
73 
74 out:
75 	rcu_read_unlock();
76 	aa_put_label(tracerl);
77 	put_cred(tracer_cred);
78 
79 	if (error)
80 		*info = "ptrace prevents transition";
81 	return error;
82 }
83 
84 /**** TODO: dedup to aa_label_match - needs perm and dfa, merging
85  * specifically this is an exact copy of aa_label_match except
86  * aa_compute_perms is replaced with aa_compute_fperms
87  * and policy->dfa with file->dfa
88  ****/
89 /* match a profile and its associated ns component if needed
90  * Assumes visibility test has already been done.
91  * If a subns profile is not to be matched should be prescreened with
92  * visibility test.
93  */
match_component(const struct aa_profile * profile,const struct aa_profile * tp,bool stack,aa_state_t state)94 static inline aa_state_t match_component(const struct aa_profile *profile,
95 					 const struct aa_profile *tp,
96 					 bool stack, aa_state_t state)
97 {
98 	struct aa_ruleset *rules = profile->label.rules[0];
99 	const char *ns_name;
100 
101 	if (stack)
102 		state = aa_dfa_match(rules->file->dfa, state, "&");
103 	if (profile->ns == tp->ns)
104 		return aa_dfa_match(rules->file->dfa, state, tp->base.hname);
105 
106 	/* try matching with namespace name and then profile */
107 	ns_name = aa_ns_name(profile->ns, tp->ns, true);
108 	state = aa_dfa_match_len(rules->file->dfa, state, ":", 1);
109 	state = aa_dfa_match(rules->file->dfa, state, ns_name);
110 	state = aa_dfa_match_len(rules->file->dfa, state, ":", 1);
111 	return aa_dfa_match(rules->file->dfa, state, tp->base.hname);
112 }
113 
114 /**
115  * label_compound_match - find perms for full compound label
116  * @profile: profile to find perms for
117  * @label: label to check access permissions for
118  * @stack: whether this is a stacking request
119  * @state: state to start match in
120  * @inview: whether to match labels in view or only in scope
121  * @request: permissions to request
122  * @perms: perms struct to set
123  *
124  * Returns: 0 on success else ERROR
125  *
126  * For the label A//&B//&C this does the perm match for A//&B//&C
127  * @perms should be preinitialized with allperms OR a previous permission
128  *        check to be stacked.
129  */
label_compound_match(const struct aa_profile * profile,struct aa_label * label,bool stack,aa_state_t state,bool inview,u32 request,struct aa_perms * perms)130 static int label_compound_match(const struct aa_profile *profile,
131 				struct aa_label *label, bool stack,
132 				aa_state_t state, bool inview, u32 request,
133 				struct aa_perms *perms)
134 {
135 	struct aa_ruleset *rules = profile->label.rules[0];
136 	struct aa_profile *tp;
137 	struct label_it i;
138 	struct path_cond cond = { };
139 
140 	/* find first subcomponent that is in view and going to be interacted with */
141 	label_for_each(i, label, tp) {
142 		if (!aa_ns_visible(profile->ns, tp->ns, inview))
143 			continue;
144 		state = match_component(profile, tp, stack, state);
145 		if (!state)
146 			goto fail;
147 		goto next;
148 	}
149 
150 	/* no component visible */
151 	*perms = allperms;
152 	return 0;
153 
154 next:
155 	label_for_each_cont(i, label, tp) {
156 		if (!aa_ns_visible(profile->ns, tp->ns, inview))
157 			continue;
158 		state = aa_dfa_match(rules->file->dfa, state, "//&");
159 		state = match_component(profile, tp, false, state);
160 		if (!state)
161 			goto fail;
162 	}
163 	*perms = *(aa_lookup_condperms(current_fsuid(), rules->file, state,
164 				       &cond));
165 	aa_apply_modes_to_perms(profile, perms);
166 	if ((perms->allow & request) != request)
167 		return -EACCES;
168 
169 	return 0;
170 
171 fail:
172 	*perms = nullperms;
173 	return -EACCES;
174 }
175 
176 /**
177  * label_components_match - find perms for all subcomponents of a label
178  * @profile: profile to find perms for
179  * @label: label to check access permissions for
180  * @stack: whether this is a stacking request
181  * @start: state to start match in
182  * @inview: whether to match labels in view or only in scope
183  * @request: permissions to request
184  * @perms: an initialized perms struct to add accumulation to
185  *
186  * Returns: 0 on success else ERROR
187  *
188  * For the label A//&B//&C this does the perm match for each of A and B and C
189  * @perms should be preinitialized with allperms OR a previous permission
190  *        check to be stacked.
191  */
label_components_match(const struct aa_profile * profile,struct aa_label * label,bool stack,aa_state_t start,bool inview,u32 request,struct aa_perms * perms)192 static int label_components_match(const struct aa_profile *profile,
193 				  struct aa_label *label, bool stack,
194 				  aa_state_t start, bool inview, u32 request,
195 				  struct aa_perms *perms)
196 {
197 	struct aa_ruleset *rules = profile->label.rules[0];
198 	struct aa_profile *tp;
199 	struct label_it i;
200 	struct aa_perms tmp;
201 	struct path_cond cond = { };
202 	aa_state_t state = 0;
203 
204 	/* find first subcomponent to test */
205 	label_for_each(i, label, tp) {
206 		if (!aa_ns_visible(profile->ns, tp->ns, inview))
207 			continue;
208 		state = match_component(profile, tp, stack, start);
209 		if (!state)
210 			goto fail;
211 		goto next;
212 	}
213 
214 	/* no subcomponents visible - no change in perms */
215 	return 0;
216 
217 next:
218 	tmp = *(aa_lookup_condperms(current_fsuid(), rules->file, state,
219 				    &cond));
220 	aa_apply_modes_to_perms(profile, &tmp);
221 	aa_perms_accum(perms, &tmp);
222 	label_for_each_cont(i, label, tp) {
223 		if (!aa_ns_visible(profile->ns, tp->ns, inview))
224 			continue;
225 		state = match_component(profile, tp, stack, start);
226 		if (!state)
227 			goto fail;
228 		tmp = *(aa_lookup_condperms(current_fsuid(), rules->file, state,
229 					    &cond));
230 		aa_apply_modes_to_perms(profile, &tmp);
231 		aa_perms_accum(perms, &tmp);
232 	}
233 
234 	if ((perms->allow & request) != request)
235 		return -EACCES;
236 
237 	return 0;
238 
239 fail:
240 	*perms = nullperms;
241 	return -EACCES;
242 }
243 
244 /**
245  * label_match - do a multi-component label match
246  * @profile: profile to match against (NOT NULL)
247  * @label: label to match (NOT NULL)
248  * @stack: whether this is a stacking request
249  * @state: state to start in
250  * @inview: whether to match labels in view or only in scope
251  * @request: permission request
252  * @perms: Returns computed perms (NOT NULL)
253  *
254  * Returns: the state the match finished in, may be the none matching state
255  */
label_match(const struct aa_profile * profile,struct aa_label * label,bool stack,aa_state_t state,bool inview,u32 request,struct aa_perms * perms)256 static int label_match(const struct aa_profile *profile, struct aa_label *label,
257 		       bool stack, aa_state_t state, bool inview, u32 request,
258 		       struct aa_perms *perms)
259 {
260 	int error;
261 
262 	*perms = nullperms;
263 	error = label_compound_match(profile, label, stack, state, inview,
264 				     request, perms);
265 	if (!error)
266 		return error;
267 
268 	*perms = allperms;
269 	return label_components_match(profile, label, stack, state, inview,
270 				      request, perms);
271 }
272 
273 /******* end TODO: dedup *****/
274 
275 /**
276  * change_profile_perms - find permissions for change_profile
277  * @profile: the current profile  (NOT NULL)
278  * @target: label to transition to (NOT NULL)
279  * @stack: whether this is a stacking request
280  * @request: requested perms
281  * @start: state to start matching in
282  * @perms: Returns computed perms (NOT NULL)
283  *
284  *
285  * Returns: permission set
286  *
287  * currently only matches full label A//&B//&C or individual components A, B, C
288  * not arbitrary combinations. Eg. A//&B, C
289  */
change_profile_perms(const struct aa_profile * profile,struct aa_label * target,bool stack,u32 request,aa_state_t start,struct aa_perms * perms)290 static int change_profile_perms(const struct aa_profile *profile,
291 				struct aa_label *target, bool stack,
292 				u32 request, aa_state_t start,
293 				struct aa_perms *perms)
294 {
295 	if (profile_unconfined(profile)) {
296 		perms->allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
297 		perms->audit = perms->quiet = perms->kill = 0;
298 		return 0;
299 	}
300 
301 	/* TODO: add profile in ns screening */
302 	return label_match(profile, target, stack, start, true, request, perms);
303 }
304 
305 /**
306  * aa_xattrs_match - check whether a file matches the xattrs defined in profile
307  * @path: path for file being matched (NOT NULL)
308  * @profile: profile to match against (NOT NULL)
309  * @state: state to start match in
310  *
311  * Returns: number of extended attributes that matched, or < 0 on error
312  */
aa_xattrs_match(const struct path * path,const struct aa_profile * profile,aa_state_t state)313 static int aa_xattrs_match(const struct path *path,
314 			   const struct aa_profile *profile, aa_state_t state)
315 {
316 	AA_BUG(!path);
317 	AA_BUG(!profile);
318 
319 	int i;
320 	struct dentry *d;
321 	char *value = NULL;
322 	const struct aa_attachment *attach = &profile->attach;
323 	int size, value_size = 0, ret = attach->xattr_count;
324 
325 	if (!attach->xattr_count)
326 		return 0;
327 	might_sleep();
328 
329 	/* transition from exec match to xattr set */
330 	state = aa_dfa_outofband_transition(attach->xmatch->dfa, state);
331 	d = path->dentry;
332 
333 	for (i = 0; i < attach->xattr_count; i++) {
334 		size = vfs_getxattr_alloc(&nop_mnt_idmap, d, attach->xattrs[i],
335 					  &value, value_size, GFP_KERNEL);
336 		if (size >= 0) {
337 			struct aa_perms *perms;
338 
339 			/*
340 			 * Check the xattr presence before value. This ensure
341 			 * that not present xattr can be distinguished from a 0
342 			 * length value or rule that matches any value
343 			 */
344 			state = aa_dfa_null_transition(attach->xmatch->dfa,
345 						       state);
346 			/* Check xattr value */
347 			state = aa_dfa_match_len(attach->xmatch->dfa, state,
348 						 value, size);
349 			perms = aa_lookup_perms(attach->xmatch, state);
350 			if (!(perms->allow & MAY_EXEC)) {
351 				ret = -EINVAL;
352 				goto out;
353 			}
354 		}
355 		/* transition to next element */
356 		state = aa_dfa_outofband_transition(attach->xmatch->dfa, state);
357 		if (size < 0) {
358 			/*
359 			 * No xattr match, so verify if transition to
360 			 * next element was valid. IFF so the xattr
361 			 * was optional.
362 			 */
363 			if (!state) {
364 				ret = -EINVAL;
365 				goto out;
366 			}
367 			/* don't count missing optional xattr as matched */
368 			ret--;
369 		}
370 	}
371 
372 out:
373 	kfree(value);
374 	return ret;
375 }
376 
377 /**
378  * find_attach - do attachment search for unconfined processes
379  * @path: path of file in question (NOT NULL)
380  * @ns: the current namespace  (NOT NULL)
381  * @head: profile list to walk  (NOT NULL)
382  * @name: to match against  (NOT NULL)
383  * @info: info message if there was an error (NOT NULL)
384  *
385  * Do a linear search on the profiles in the list.  There is a matching
386  * preference where an exact match is preferred over a name which uses
387  * expressions to match, and matching expressions with the greatest
388  * xmatch_len are preferred.
389  *
390  * Requires: @head not be shared or have appropriate locks held
391  *
392  * Returns: label or NULL if no match found
393  */
find_attach(const struct path * path,struct aa_ns * ns,struct list_head * head,const char * name,const char ** info)394 static struct aa_label *find_attach(const struct path *path,
395 				    struct aa_ns *ns, struct list_head *head,
396 				    const char *name, const char **info)
397 {
398 	int candidate_len = 0, candidate_xattrs = 0;
399 	bool conflict = false;
400 	struct aa_profile *profile, *candidate = NULL;
401 
402 	AA_BUG(!path);
403 	AA_BUG(!name);
404 	AA_BUG(!head);
405 
406 	rcu_read_lock();
407 restart:
408 	list_for_each_entry_rcu(profile, head, base.list) {
409 		struct aa_attachment *attach = &profile->attach;
410 
411 		if (profile->label.flags & FLAG_NULL &&
412 		    &profile->label == ns_unconfined(profile->ns))
413 			continue;
414 
415 		/* Find the "best" matching profile. Profiles must
416 		 * match the path and extended attributes (if any)
417 		 * associated with the file. A more specific path
418 		 * match will be preferred over a less specific one,
419 		 * and a match with more matching extended attributes
420 		 * will be preferred over one with fewer. If the best
421 		 * match has both the same level of path specificity
422 		 * and the same number of matching extended attributes
423 		 * as another profile, signal a conflict and refuse to
424 		 * match.
425 		 */
426 		if (attach->xmatch->dfa) {
427 			unsigned int count;
428 			aa_state_t state;
429 			struct aa_perms *perms;
430 
431 			state = aa_dfa_leftmatch(attach->xmatch->dfa,
432 					attach->xmatch->start[AA_CLASS_XMATCH],
433 					name, &count);
434 			perms = aa_lookup_perms(attach->xmatch, state);
435 			/* any accepting state means a valid match. */
436 			if (perms->allow & MAY_EXEC) {
437 				int ret = 0;
438 
439 				if (count < candidate_len)
440 					continue;
441 
442 				if (attach->xattr_count) {
443 					long rev = READ_ONCE(ns->revision);
444 
445 					if (!aa_get_profile_not0(profile))
446 						goto restart;
447 					rcu_read_unlock();
448 					ret = aa_xattrs_match(path, profile,
449 							      state);
450 					rcu_read_lock();
451 					aa_put_profile(profile);
452 					if (rev !=
453 					    READ_ONCE(ns->revision))
454 						/* policy changed */
455 						goto restart;
456 					/*
457 					 * Fail matching if the xattrs don't
458 					 * match
459 					 */
460 					if (ret < 0)
461 						continue;
462 				}
463 				/*
464 				 * TODO: allow for more flexible best match
465 				 *
466 				 * The new match isn't more specific
467 				 * than the current best match
468 				 */
469 				if (count == candidate_len &&
470 				    ret <= candidate_xattrs) {
471 					/* Match is equivalent, so conflict */
472 					if (ret == candidate_xattrs)
473 						conflict = true;
474 					continue;
475 				}
476 
477 				/* Either the same length with more matching
478 				 * xattrs, or a longer match
479 				 */
480 				candidate = profile;
481 				candidate_len = max(count, attach->xmatch_len);
482 				candidate_xattrs = ret;
483 				conflict = false;
484 			}
485 		} else if (!strcmp(profile->base.name, name)) {
486 			/*
487 			 * old exact non-re match, without conditionals such
488 			 * as xattrs. no more searching required
489 			 */
490 			candidate = profile;
491 			goto out;
492 		}
493 	}
494 
495 	if (!candidate || conflict) {
496 		if (conflict)
497 			*info = CONFLICTING_ATTACH_STR;
498 		rcu_read_unlock();
499 		return NULL;
500 	}
501 
502 out:
503 	candidate = aa_get_newest_profile(candidate);
504 	rcu_read_unlock();
505 
506 	return &candidate->label;
507 }
508 
next_name(int xtype,const char * name)509 static const char *next_name(int xtype, const char *name)
510 {
511 	return NULL;
512 }
513 
514 /**
515  * x_table_lookup - lookup an x transition name via transition table
516  * @profile: current profile (NOT NULL)
517  * @xindex: index into x transition table
518  * @name: returns: name tested to find label (NOT NULL)
519  *
520  * Returns: refcounted label, or NULL on failure (MAYBE NULL)
521  *          @name will always be set with the last name tried
522  */
x_table_lookup(struct aa_profile * profile,u32 xindex,const char ** name)523 struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
524 				const char **name)
525 {
526 	struct aa_ruleset *rules = profile->label.rules[0];
527 	struct aa_label *label = NULL;
528 	u32 xtype = xindex & AA_X_TYPE_MASK;
529 	int index = xindex & AA_X_INDEX_MASK;
530 	const char *next;
531 
532 	AA_BUG(!name);
533 
534 	/* index is guaranteed to be in range, validated at load time */
535 	/* TODO: move lookup parsing to unpack time so this is a straight
536 	 *       index into the resultant label
537 	 */
538 	for (next = rules->file->trans.table[index].strs; next;
539 	     next = next_name(xtype, next)) {
540 		const char *lookup = (*next == '&') ? next + 1 : next;
541 		*name = next;
542 		if (xindex & AA_X_CHILD) {
543 			/* TODO: switich to parse to get stack of child */
544 			struct aa_profile *new = aa_find_child(profile, lookup);
545 
546 			if (new)
547 				/* release by caller */
548 				return &new->label;
549 			continue;
550 		}
551 		label = aa_label_parse(&profile->label, lookup, GFP_KERNEL,
552 				       true, false);
553 		if (!IS_ERR_OR_NULL(label))
554 			/* release by caller */
555 			return label;
556 	}
557 
558 	return NULL;
559 }
560 
561 /**
562  * x_to_label - get target label for a given xindex
563  * @profile: current profile  (NOT NULL)
564  * @path: path of file in question
565  * @name: name to lookup (NOT NULL)
566  * @xindex: index into x transition table
567  * @lookupname: returns: name used in lookup if one was specified (NOT NULL)
568  * @info: info message if there was an error (NOT NULL)
569  *
570  * find label for a transition index
571  *
572  * Returns: refcounted label or NULL if not found available
573  */
x_to_label(struct aa_profile * profile,const struct path * path,const char * name,u32 xindex,const char ** lookupname,const char ** info)574 static struct aa_label *x_to_label(struct aa_profile *profile,
575 				   const struct path *path,
576 				   const char *name, u32 xindex,
577 				   const char **lookupname,
578 				   const char **info)
579 {
580 	struct aa_label *new = NULL;
581 	struct aa_label *stack = NULL;
582 	struct aa_ns *ns = profile->ns;
583 	u32 xtype = xindex & AA_X_TYPE_MASK;
584 	/* Used for info checks during fallback handling */
585 	const char *old_info = NULL;
586 
587 	switch (xtype) {
588 	case AA_X_NONE:
589 		/* fail exec unless ix || ux fallback - handled by caller */
590 		*lookupname = NULL;
591 		break;
592 	case AA_X_TABLE:
593 		/* TODO: fix when perm mapping done at unload */
594 		/* released by caller
595 		 * if null for both stack and direct want to try fallback
596 		 */
597 		new = x_table_lookup(profile, xindex, lookupname);
598 		if (!new || **lookupname != '&')
599 			break;
600 		stack = new;
601 		new = NULL;
602 		fallthrough;	/* to X_NAME */
603 	case AA_X_NAME:
604 		if (xindex & AA_X_CHILD)
605 			/* released by caller */
606 			new = find_attach(path, ns, &profile->base.profiles,
607 					  name, info);
608 		else
609 			/* released by caller */
610 			new = find_attach(path, ns, &ns->base.profiles,
611 					  name, info);
612 		*lookupname = name;
613 		break;
614 	}
615 
616 	/* fallback transition check */
617 	if (!new) {
618 		if (xindex & AA_X_INHERIT) {
619 			/* (p|c|n)ix - don't change profile but do
620 			 * use the newest version
621 			 */
622 			if (*info == CONFLICTING_ATTACH_STR) {
623 				*info = CONFLICTING_ATTACH_STR_IX;
624 			} else {
625 				old_info = *info;
626 				*info = "ix fallback";
627 			}
628 			/* no profile && no error */
629 			new = aa_get_newest_label(&profile->label);
630 		} else if (xindex & AA_X_UNCONFINED) {
631 			new = aa_get_newest_label(ns_unconfined(profile->ns));
632 			if (*info == CONFLICTING_ATTACH_STR) {
633 				*info = CONFLICTING_ATTACH_STR_UX;
634 			} else {
635 				old_info = *info;
636 				*info = "ux fallback";
637 			}
638 		}
639 		/* We set old_info on the code paths above where overwriting
640 		 * could have happened, so now check if info was set by
641 		 * find_attach as well (i.e. whether we actually overwrote)
642 		 * and warn accordingly.
643 		 */
644 		if (old_info && old_info != CONFLICTING_ATTACH_STR) {
645 			pr_warn_ratelimited(
646 				"AppArmor: find_attach (from profile %s) audit info \"%s\" dropped",
647 				profile->base.hname, old_info);
648 		}
649 	}
650 
651 	if (new && stack) {
652 		/* base the stack on post domain transition */
653 		struct aa_label *base = new;
654 
655 		new = aa_label_merge(base, stack, GFP_KERNEL);
656 		/* null on error */
657 		aa_put_label(base);
658 	}
659 
660 	aa_put_label(stack);
661 	/* released by caller */
662 	return new;
663 }
664 
profile_transition(const struct cred * subj_cred,struct aa_profile * profile,const struct linux_binprm * bprm,char * buffer,struct path_cond * cond,bool * secure_exec)665 static struct aa_label *profile_transition(const struct cred *subj_cred,
666 					   struct aa_profile *profile,
667 					   const struct linux_binprm *bprm,
668 					   char *buffer, struct path_cond *cond,
669 					   bool *secure_exec)
670 {
671 	struct aa_ruleset *rules = profile->label.rules[0];
672 	struct aa_label *new = NULL;
673 	struct aa_profile *new_profile = NULL;
674 	const char *info = NULL, *name = NULL, *target = NULL;
675 	aa_state_t state = rules->file->start[AA_CLASS_FILE];
676 	struct aa_perms perms = {};
677 	bool nonewprivs = false;
678 	int error = 0;
679 
680 	AA_BUG(!profile);
681 	AA_BUG(!bprm);
682 	AA_BUG(!buffer);
683 
684 	error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer,
685 			     &name, &info, profile->disconnected);
686 	if (error) {
687 		if (profile_unconfined(profile) ||
688 		    (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) {
689 			AA_DEBUG(DEBUG_DOMAIN, "name lookup ix on error");
690 			error = 0;
691 			new = aa_get_newest_label(&profile->label);
692 		}
693 		name = bprm->filename;
694 		goto audit;
695 	}
696 
697 	if (profile_unconfined(profile)) {
698 		new = find_attach(&bprm->file->f_path, profile->ns,
699 				  &profile->ns->base.profiles, name, &info);
700 		/* info set -> something unusual that we should report
701 		 * Currently this is only conflicting attachments, but other
702 		 * infos added in the future should also be logged by default
703 		 * and only excluded on a case-by-case basis
704 		 */
705 		if (info) {
706 			/* Because perms is never used again after this audit
707 			 * we don't need to care about clobbering it
708 			 */
709 			perms.audit |= MAY_EXEC;
710 			perms.allow |= MAY_EXEC;
711 			/* Don't cause error if auditing fails */
712 			(void) aa_audit_file(subj_cred, profile, &perms,
713 				OP_EXEC, MAY_EXEC, name, target, new, cond->uid,
714 				info, error);
715 		}
716 		if (new) {
717 			AA_DEBUG(DEBUG_DOMAIN, "unconfined attached to new label");
718 			return new;
719 		}
720 		AA_DEBUG(DEBUG_DOMAIN, "unconfined exec no attachment");
721 		return aa_get_newest_label(&profile->label);
722 	}
723 
724 	/* find exec permissions for name */
725 	state = aa_str_perms(rules->file, state, name, cond, &perms);
726 	if (perms.allow & MAY_EXEC) {
727 		/* exec permission determine how to transition */
728 		new = x_to_label(profile, &bprm->file->f_path, name,
729 				 perms.xindex, &target, &info);
730 		if (new && new->proxy == profile->label.proxy && info) {
731 			/* Force audit on conflicting attachment fallback
732 			 * Because perms is never used again after this audit
733 			 * we don't need to care about clobbering it
734 			 */
735 			if (info == CONFLICTING_ATTACH_STR_IX
736 			    || info == CONFLICTING_ATTACH_STR_UX)
737 				perms.audit |= MAY_EXEC;
738 			/* hack ix fallback - improve how this is detected */
739 			goto audit;
740 		} else if (!new) {
741 			if (info) {
742 				pr_warn_ratelimited(
743 					"AppArmor: %s (from profile %s) audit info \"%s\" dropped on missing transition",
744 					__func__, profile->base.hname, info);
745 			}
746 			info = "profile transition not found";
747 			/* remove MAY_EXEC to audit as failure or complaint */
748 			perms.allow &= ~MAY_EXEC;
749 			if (COMPLAIN_MODE(profile)) {
750 				/* create null profile instead of failing */
751 				goto create_learning_profile;
752 			}
753 			error = -EACCES;
754 		}
755 	} else if (COMPLAIN_MODE(profile)) {
756 create_learning_profile:
757 		/* no exec permission - learning mode */
758 		new_profile = aa_new_learning_profile(profile, false, name,
759 						      GFP_KERNEL);
760 		if (!new_profile) {
761 			error = -ENOMEM;
762 			info = "could not create null profile";
763 		} else {
764 			error = -EACCES;
765 			new = &new_profile->label;
766 		}
767 		perms.xindex |= AA_X_UNSAFE;
768 	} else
769 		/* fail exec */
770 		error = -EACCES;
771 
772 	if (!new)
773 		goto audit;
774 
775 
776 	if (!(perms.xindex & AA_X_UNSAFE)) {
777 		if (DEBUG_ON) {
778 			dbg_printk("apparmor: setting AT_SECURE for %s profile=",
779 				   name);
780 			aa_label_printk(new, GFP_KERNEL);
781 			dbg_printk("\n");
782 		}
783 		*secure_exec = true;
784 	}
785 
786 audit:
787 	aa_audit_file(subj_cred, profile, &perms, OP_EXEC, MAY_EXEC, name,
788 		      target, new,
789 		      cond->uid, info, error);
790 	if (!new || nonewprivs) {
791 		aa_put_label(new);
792 		return ERR_PTR(error);
793 	}
794 
795 	return new;
796 }
797 
profile_onexec(const struct cred * subj_cred,struct aa_profile * profile,struct aa_label * onexec,bool stack,const struct linux_binprm * bprm,char * buffer,struct path_cond * cond,bool * secure_exec)798 static int profile_onexec(const struct cred *subj_cred,
799 			  struct aa_profile *profile, struct aa_label *onexec,
800 			  bool stack, const struct linux_binprm *bprm,
801 			  char *buffer, struct path_cond *cond,
802 			  bool *secure_exec)
803 {
804 	struct aa_ruleset *rules = profile->label.rules[0];
805 	aa_state_t state = rules->file->start[AA_CLASS_FILE];
806 	struct aa_perms perms = {};
807 	const char *xname = NULL, *info = "change_profile onexec";
808 	int error = -EACCES;
809 
810 	AA_BUG(!profile);
811 	AA_BUG(!onexec);
812 	AA_BUG(!bprm);
813 	AA_BUG(!buffer);
814 
815 	if (profile_unconfined(profile)) {
816 		/* change_profile on exec already granted */
817 		/*
818 		 * NOTE: Domain transitions from unconfined are allowed
819 		 * even when no_new_privs is set because this always results
820 		 * in a further reduction of permissions.
821 		 */
822 		return 0;
823 	}
824 
825 	error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer,
826 			     &xname, &info, profile->disconnected);
827 	if (error) {
828 		if (profile_unconfined(profile) ||
829 		    (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) {
830 			AA_DEBUG(DEBUG_DOMAIN, "name lookup ix on error");
831 			error = 0;
832 		}
833 		xname = bprm->filename;
834 		goto audit;
835 	}
836 
837 	/* find exec permissions for name */
838 	state = aa_str_perms(rules->file, state, xname, cond, &perms);
839 	if (!(perms.allow & AA_MAY_ONEXEC)) {
840 		info = "no change_onexec valid for executable";
841 		goto audit;
842 	}
843 	/* test if this exec can be paired with change_profile onexec.
844 	 * onexec permission is linked to exec with a standard pairing
845 	 * exec\0change_profile
846 	 */
847 	state = aa_dfa_null_transition(rules->file->dfa, state);
848 	error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC,
849 				     state, &perms);
850 	if (error) {
851 		perms.allow &= ~AA_MAY_ONEXEC;
852 		goto audit;
853 	}
854 
855 	if (!(perms.xindex & AA_X_UNSAFE)) {
856 		if (DEBUG_ON) {
857 			dbg_printk("apparmor: setting AT_SECURE for %s label=",
858 				   xname);
859 			aa_label_printk(onexec, GFP_KERNEL);
860 			dbg_printk("\n");
861 		}
862 		*secure_exec = true;
863 	}
864 
865 audit:
866 	return aa_audit_file(subj_cred, profile, &perms, OP_EXEC,
867 			     AA_MAY_ONEXEC, xname,
868 			     NULL, onexec, cond->uid, info, error);
869 }
870 
871 /* ensure none ns domain transitions are correctly applied with onexec */
label_merge_wrap(struct aa_label * a,struct aa_label * b,gfp_t gfp)872 static struct aa_label *label_merge_wrap(struct aa_label *a, struct aa_label *b,
873 					 gfp_t gfp)
874 {
875 	struct aa_label *label = aa_label_merge(a, b, gfp);
876 
877 	if (!label)
878 		return ERR_PTR(-ENOMEM);
879 	return label;
880 }
881 
is_profile_priv_restricted_to_stack(const struct cred * subj_cred,struct aa_profile * profile)882 static bool is_profile_priv_restricted_to_stack(const struct cred *subj_cred,
883 						struct aa_profile *profile)
884 {
885 	if (profile_unconfined(profile) && profile == profile->ns->unconfined &&
886 	    aa_unprivileged_unconfined_restricted &&
887 	    /* cap_capable returns false (0) if true, hence true here means
888 	     * doesn't have capability and the stack will be restricted
889 	     */
890 	    cap_capable(current_cred(), &init_user_ns, CAP_MAC_OVERRIDE,
891 			CAP_OPT_NOAUDIT))
892 		return true;
893 	return false;
894 }
895 
896 static const char *stack_msg = "change_profile unprivileged unconfined converted to stacking";
897 
priv_restricted_transition(const struct cred * subj_cred,struct aa_profile * profile,const char * op,u32 request,const char * name,struct aa_label * transition,gfp_t gfp)898 static struct aa_label *priv_restricted_transition(const struct cred *subj_cred,
899 						   struct aa_profile *profile,
900 						   const char *op, u32 request,
901 						   const char *name,
902 						   struct aa_label *transition,
903 						   gfp_t gfp)
904 {
905 	if (!is_profile_priv_restricted_to_stack(subj_cred, profile))
906 		return aa_get_newest_label(transition);
907 
908 	/* transition allowed but only via stack */
909 	struct aa_label *target = label_merge_wrap(&profile->label,
910 						      transition, gfp);
911 	if (IS_ERR_OR_NULL(target))
912 		return target;
913 
914 	/* doing this here is less than optimal but good enough until the
915 	 * fs mediation rework lands
916 	 */
917 	struct aa_perms perms = {
918 		.allow = request,
919 		.audit = request,
920 	};
921 	aa_audit_file(subj_cred, profile, &perms, op,
922 		      request, name, NULL, target,
923 		      subj_cred->euid, stack_msg, 0);
924 
925 	return target;
926 }
927 
handle_onexec(const struct cred * subj_cred,struct aa_label * label,struct aa_label * onexec,bool stack,const struct linux_binprm * bprm,char * buffer,struct path_cond * cond,bool * unsafe)928 static struct aa_label *handle_onexec(const struct cred *subj_cred,
929 				      struct aa_label *label,
930 				      struct aa_label *onexec, bool stack,
931 				      const struct linux_binprm *bprm,
932 				      char *buffer, struct path_cond *cond,
933 				      bool *unsafe)
934 {
935 	struct aa_profile *profile;
936 	struct aa_label *new;
937 	int error;
938 
939 	AA_BUG(!label);
940 	AA_BUG(!onexec);
941 	AA_BUG(!bprm);
942 	AA_BUG(!buffer);
943 
944 	/* TODO: determine how much we want to loosen this
945 	 * only check profiles in scope for permission to change at exec
946 	 */
947 	error = fn_for_each_in_scope(label, profile,
948 			profile_onexec(subj_cred, profile, onexec, stack,
949 				       bprm, buffer, cond, unsafe));
950 	if (error)
951 		return ERR_PTR(error);
952 
953 	new = fn_label_build_in_scope(label, profile, GFP_KERNEL,
954 			stack ? label_merge_wrap(&profile->label, onexec,
955 						 GFP_KERNEL)
956 			      : priv_restricted_transition(subj_cred, profile,
957 						OP_CHANGE_ONEXEC, AA_MAY_ONEXEC,
958 						bprm->filename, onexec,
959 						GFP_KERNEL),
960 			profile_transition(subj_cred, profile, bprm,
961 					   buffer, cond, unsafe));
962 	AA_BUG(!new);
963 	if (!IS_ERR(new))
964 		return new;
965 
966 	/* TODO: get rid of GLOBAL_ROOT_UID */
967 	error = fn_for_each_in_scope(label, profile,
968 			aa_audit_file(subj_cred, profile, &nullperms,
969 				      OP_CHANGE_ONEXEC,
970 				      AA_MAY_ONEXEC, bprm->filename, NULL,
971 				      onexec, GLOBAL_ROOT_UID,
972 				      "failed to build target label",
973 				      PTR_ERR(new)));
974 	return ERR_PTR(error);
975 }
976 
977 /**
978  * apparmor_bprm_creds_for_exec - Update the new creds on the bprm struct
979  * @bprm: binprm for the exec  (NOT NULL)
980  *
981  * Returns: %0 or error on failure
982  *
983  * TODO: once the other paths are done see if we can't refactor into a fn
984  */
apparmor_bprm_creds_for_exec(struct linux_binprm * bprm)985 int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
986 {
987 	struct aa_task_ctx *ctx;
988 	struct aa_label *label, *new = NULL;
989 	const struct cred *subj_cred;
990 	struct aa_profile *profile;
991 	char *buffer = NULL;
992 	const char *info = NULL;
993 	int error = 0;
994 	bool unsafe = false;
995 	vfsuid_t vfsuid = i_uid_into_vfsuid(file_mnt_idmap(bprm->file),
996 					    file_inode(bprm->file));
997 	struct path_cond cond = {
998 		vfsuid_into_kuid(vfsuid),
999 		file_inode(bprm->file)->i_mode
1000 	};
1001 
1002 	subj_cred = current_cred();
1003 	ctx = task_ctx(current);
1004 	AA_BUG(!cred_label(bprm->cred));
1005 	AA_BUG(!ctx);
1006 
1007 	label = aa_get_newest_label(cred_label(bprm->cred));
1008 
1009 	/*
1010 	 * Detect no new privs being set, and store the label it
1011 	 * occurred under. Ideally this would happen when nnp
1012 	 * is set but there isn't a good way to do that yet.
1013 	 *
1014 	 * Testing for unconfined must be done before the subset test
1015 	 */
1016 	if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && !unconfined(label) &&
1017 	    !ctx->nnp)
1018 		ctx->nnp = aa_get_label(label);
1019 
1020 	/* buffer freed below, name is pointer into buffer */
1021 	buffer = aa_get_buffer(false);
1022 	if (!buffer) {
1023 		error = -ENOMEM;
1024 		goto done;
1025 	}
1026 
1027 	/* Test for onexec first as onexec override other x transitions. */
1028 	if (ctx->onexec)
1029 		new = handle_onexec(subj_cred, label, ctx->onexec, ctx->token,
1030 				    bprm, buffer, &cond, &unsafe);
1031 	else
1032 		new = fn_label_build(label, profile, GFP_KERNEL,
1033 				profile_transition(subj_cred, profile, bprm,
1034 						   buffer,
1035 						   &cond, &unsafe));
1036 	AA_BUG(!new);
1037 	if (IS_ERR(new)) {
1038 		error = PTR_ERR(new);
1039 		goto done;
1040 	}
1041 
1042 	/* Policy has specified a domain transitions. If no_new_privs and
1043 	 * confined ensure the transition is to confinement that is subset
1044 	 * of the confinement when the task entered no new privs.
1045 	 *
1046 	 * NOTE: Domain transitions from unconfined and to stacked
1047 	 * subsets are allowed even when no_new_privs is set because this
1048 	 * always results in a further reduction of permissions.
1049 	 */
1050 	if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) &&
1051 	    !unconfined(label) &&
1052 	    !aa_label_is_unconfined_subset(new, ctx->nnp)) {
1053 		error = -EPERM;
1054 		info = "no new privs";
1055 		goto audit;
1056 	}
1057 
1058 	if (bprm->unsafe & LSM_UNSAFE_SHARE) {
1059 		/* FIXME: currently don't mediate shared state */
1060 		;
1061 	}
1062 
1063 	if (bprm->unsafe & (LSM_UNSAFE_PTRACE)) {
1064 		/* TODO: test needs to be profile of label to new */
1065 		error = may_change_ptraced_domain(bprm->cred, new, &info);
1066 		if (error)
1067 			goto audit;
1068 	}
1069 
1070 	if (unsafe) {
1071 		if (DEBUG_ON) {
1072 			dbg_printk("setting AT_SECURE for %s label=",
1073 				   bprm->filename);
1074 			aa_label_printk(new, GFP_KERNEL);
1075 			dbg_printk("\n");
1076 		}
1077 		bprm->secureexec = 1;
1078 	}
1079 
1080 	if (label->proxy != new->proxy) {
1081 		/* when transitioning clear unsafe personality bits */
1082 		if (DEBUG_ON) {
1083 			dbg_printk("apparmor: clearing unsafe personality bits. %s label=",
1084 				   bprm->filename);
1085 			aa_label_printk(new, GFP_KERNEL);
1086 			dbg_printk("\n");
1087 		}
1088 		bprm->per_clear |= PER_CLEAR_ON_SETID;
1089 	}
1090 	aa_put_label(cred_label(bprm->cred));
1091 	/* transfer reference, released when cred is freed */
1092 	set_cred_label(bprm->cred, new);
1093 
1094 done:
1095 	aa_put_label(label);
1096 	aa_put_buffer(buffer);
1097 
1098 	return error;
1099 
1100 audit:
1101 	error = fn_for_each(label, profile,
1102 			aa_audit_file(current_cred(), profile, &nullperms,
1103 				      OP_EXEC, MAY_EXEC,
1104 				      bprm->filename, NULL, new,
1105 				      vfsuid_into_kuid(vfsuid), info, error));
1106 	aa_put_label(new);
1107 	goto done;
1108 }
1109 
1110 /*
1111  * Functions for self directed profile change
1112  */
1113 
1114 
1115 /* helper fn for change_hat
1116  *
1117  * Returns: label for hat transition OR ERR_PTR.  Does NOT return NULL
1118  */
build_change_hat(const struct cred * subj_cred,struct aa_profile * profile,const char * name,bool sibling)1119 static struct aa_label *build_change_hat(const struct cred *subj_cred,
1120 					 struct aa_profile *profile,
1121 					 const char *name, bool sibling)
1122 {
1123 	struct aa_profile *root, *hat = NULL;
1124 	const char *info = NULL;
1125 	int error = 0;
1126 
1127 	if (sibling && PROFILE_IS_HAT(profile)) {
1128 		root = aa_get_profile_rcu(&profile->parent);
1129 	} else if (!sibling && !PROFILE_IS_HAT(profile)) {
1130 		root = aa_get_profile(profile);
1131 	} else {
1132 		info = "conflicting target types";
1133 		error = -EPERM;
1134 		goto audit;
1135 	}
1136 
1137 	hat = aa_find_child(root, name);
1138 	if (!hat) {
1139 		error = -ENOENT;
1140 		if (COMPLAIN_MODE(profile)) {
1141 			hat = __aa_new_learning_profile(profile, true, name,
1142 							GFP_KERNEL);
1143 			if (!hat) {
1144 				info = "failed null profile create";
1145 				error = -ENOMEM;
1146 			}
1147 		}
1148 	}
1149 	aa_put_profile(root);
1150 
1151 audit:
1152 	aa_audit_file(subj_cred, profile, &nullperms, OP_CHANGE_HAT,
1153 		      AA_MAY_CHANGEHAT,
1154 		      name, hat ? hat->base.hname : NULL,
1155 		      hat ? &hat->label : NULL, GLOBAL_ROOT_UID, info,
1156 		      error);
1157 	if (!hat || (error && error != -ENOENT))
1158 		return ERR_PTR(error);
1159 	/* if hat && error - complain mode, already audited and we adjust for
1160 	 * complain mode allow by returning hat->label
1161 	 */
1162 	return &hat->label;
1163 }
1164 
1165 /* helper fn for changing into a hat
1166  *
1167  * Returns: label for hat transition or ERR_PTR. Does not return NULL
1168  */
change_hat(const struct cred * subj_cred,struct aa_label * label,const char * hats[],int count,int flags)1169 static struct aa_label *change_hat(const struct cred *subj_cred,
1170 				   struct aa_label *label, const char *hats[],
1171 				   int count, int flags)
1172 {
1173 	struct aa_profile *profile, *root, *hat = NULL;
1174 	struct aa_ns *ns, *new_ns;
1175 	struct aa_label *new;
1176 	struct label_it it;
1177 	bool sibling = false;
1178 	const char *name, *info = NULL;
1179 	int i, error;
1180 	bool needput = false;
1181 
1182 	AA_BUG(!label);
1183 	AA_BUG(!hats);
1184 	AA_BUG(count < 1);
1185 
1186 	/*
1187 	 * Acquire the newest label and then hold the lock until we choose a
1188 	 * hat, so that profile replacement doesn't atomically truncate the
1189 	 * list of potential hats. Because we are getting the namespaces from
1190 	 * the profiles and label, we can rely on the namespaces being live
1191 	 * and avoid incrementing their refcounts while grabbing the lock.
1192 	 */
1193 	ns = labels_ns(label);
1194 
1195 retry:
1196 	mutex_lock_nested(&ns->lock, ns->level);
1197 	if (label_is_stale(label)) {
1198 		new = aa_get_newest_label(label);
1199 		new_ns = labels_ns(new);
1200 
1201 		if (needput)
1202 			/* aa_put_label() is safe to call when under lock */
1203 			aa_put_label(label);
1204 		label = new;
1205 		needput = true;
1206 		/* check if replaced with label in parent ns, and lock there */
1207 		if (new_ns != ns) {
1208 			mutex_unlock(&ns->lock);
1209 			ns = new_ns;
1210 			/* retry will bottom out at the root of the tree */
1211 			goto retry;
1212 		}
1213 	}
1214 
1215 	if (PROFILE_IS_HAT(labels_profile(label)))
1216 		sibling = true;
1217 
1218 	/*find first matching hat */
1219 	for (i = 0; i < count && !hat; i++) {
1220 		name = hats[i];
1221 		label_for_each_in_scope(it, labels_ns(label), label, profile) {
1222 			if (sibling && PROFILE_IS_HAT(profile)) {
1223 				root = aa_get_profile(rcu_dereference_protected(profile->parent,
1224 						      mutex_is_locked(&ns->lock)));
1225 			} else if (!sibling && !PROFILE_IS_HAT(profile)) {
1226 				root = aa_get_profile(profile);
1227 			} else {	/* conflicting change type */
1228 				info = "conflicting targets types";
1229 				error = -EPERM;
1230 				goto fail;
1231 			}
1232 			hat = aa_find_child(root, name);
1233 			aa_put_profile(root);
1234 			if (!hat) {
1235 				if (!COMPLAIN_MODE(profile))
1236 					goto outer_continue;
1237 				/* complain mode succeed as if hat */
1238 			} else if (!PROFILE_IS_HAT(hat)) {
1239 				info = "target not hat";
1240 				error = -EPERM;
1241 				aa_put_profile(hat);
1242 				goto fail;
1243 			}
1244 			aa_put_profile(hat);
1245 		}
1246 		/* found a hat for all profiles in ns */
1247 		goto build;
1248 outer_continue:
1249 	;
1250 	}
1251 	/* no hats that match, find appropriate error
1252 	 *
1253 	 * In complain mode audit of the failure is based off of the first
1254 	 * hat supplied.  This is done due how userspace interacts with
1255 	 * change_hat.
1256 	 */
1257 	name = NULL;
1258 	label_for_each_in_scope(it, labels_ns(label), label, profile) {
1259 		if (!list_empty(&profile->base.profiles)) {
1260 			info = "hat not found";
1261 			error = -ENOENT;
1262 			goto fail;
1263 		}
1264 	}
1265 	info = "no hats defined";
1266 	error = -ECHILD;
1267 
1268 fail:
1269 	label_for_each_in_scope(it, labels_ns(label), label, profile) {
1270 		/*
1271 		 * no target as it has failed to be found or built
1272 		 *
1273 		 * change_hat uses probing and should not log failures
1274 		 * related to missing hats
1275 		 */
1276 		/* TODO: get rid of GLOBAL_ROOT_UID */
1277 		if (count > 1 || COMPLAIN_MODE(profile)) {
1278 			aa_audit_file(subj_cred, profile, &nullperms,
1279 				      OP_CHANGE_HAT,
1280 				      AA_MAY_CHANGEHAT, name, NULL, NULL,
1281 				      GLOBAL_ROOT_UID, info, error);
1282 		}
1283 	}
1284 	mutex_unlock(&ns->lock);
1285 	if (needput)
1286 		aa_put_label(label);
1287 	return ERR_PTR(error);
1288 
1289 build:
1290 	new = fn_label_build_in_scope(label, profile, GFP_KERNEL,
1291 				   build_change_hat(subj_cred, profile, name,
1292 						    sibling),
1293 				   aa_get_label(&profile->label));
1294 	mutex_unlock(&ns->lock);
1295 	AA_BUG(!new);
1296 	/* return new label or error ptr */
1297 	if (needput)
1298 		aa_put_label(label);
1299 	return new;
1300 }
1301 
1302 /**
1303  * aa_change_hat - change hat to/from subprofile
1304  * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
1305  * @count: number of hat names in @hats
1306  * @token: magic value to validate the hat change
1307  * @flags: flags affecting behavior of the change
1308  *
1309  * Returns %0 on success, error otherwise.
1310  *
1311  * Change to the first profile specified in @hats that exists, and store
1312  * the @hat_magic in the current task context.  If the count == 0 and the
1313  * @token matches that stored in the current task context, return to the
1314  * top level profile.
1315  *
1316  * change_hat only applies to profiles in the current ns, and each profile
1317  * in the ns must make the same transition otherwise change_hat will fail.
1318  */
aa_change_hat(const char * hats[],int count,u64 token,int flags)1319 int aa_change_hat(const char *hats[], int count, u64 token, int flags)
1320 {
1321 	const struct cred *subj_cred;
1322 	struct aa_task_ctx *ctx = task_ctx(current);
1323 	struct aa_label *label, *previous, *new = NULL, *target = NULL;
1324 	struct aa_profile *profile;
1325 	struct aa_perms perms = {};
1326 	const char *info = NULL;
1327 	int error = 0;
1328 
1329 	/* released below */
1330 	subj_cred = get_current_cred();
1331 	label = aa_get_newest_cred_label(subj_cred);
1332 	previous = aa_get_newest_label(ctx->previous);
1333 
1334 	/*
1335 	 * Detect no new privs being set, and store the label it
1336 	 * occurred under. Ideally this would happen when nnp
1337 	 * is set but there isn't a good way to do that yet.
1338 	 *
1339 	 * Testing for unconfined must be done before the subset test
1340 	 */
1341 	if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
1342 		ctx->nnp = aa_get_label(label);
1343 
1344 	/* return -EPERM when unconfined doesn't have children to avoid
1345 	 * changing the traditional error code for unconfined.
1346 	 */
1347 	if (unconfined(label)) {
1348 		struct label_it i;
1349 		bool empty = true;
1350 
1351 		rcu_read_lock();
1352 		label_for_each_in_scope(i, labels_ns(label), label, profile) {
1353 			empty &= list_empty(&profile->base.profiles);
1354 		}
1355 		rcu_read_unlock();
1356 
1357 		if (empty) {
1358 			info = "unconfined can not change_hat";
1359 			error = -EPERM;
1360 			goto fail;
1361 		}
1362 	}
1363 
1364 	if (count) {
1365 		new = change_hat(subj_cred, label, hats, count, flags);
1366 		AA_BUG(!new);
1367 		if (IS_ERR(new)) {
1368 			error = PTR_ERR(new);
1369 			new = NULL;
1370 			/* already audited */
1371 			goto out;
1372 		}
1373 
1374 		/* target cred is the same as current except new label */
1375 		error = may_change_ptraced_domain(subj_cred, new, &info);
1376 		if (error)
1377 			goto fail;
1378 
1379 		/*
1380 		 * no new privs prevents domain transitions that would
1381 		 * reduce restrictions.
1382 		 */
1383 		if (task_no_new_privs(current) && !unconfined(label) &&
1384 		    !aa_label_is_unconfined_subset(new, ctx->nnp)) {
1385 			/* not an apparmor denial per se, so don't log it */
1386 			AA_DEBUG(DEBUG_DOMAIN,
1387 				 "no_new_privs - change_hat denied");
1388 			error = -EPERM;
1389 			goto out;
1390 		}
1391 
1392 		if (flags & AA_CHANGE_TEST)
1393 			goto out;
1394 
1395 		target = new;
1396 		error = aa_set_current_hat(new, token);
1397 		if (error == -EACCES)
1398 			/* kill task in case of brute force attacks */
1399 			goto kill;
1400 	} else if (previous && !(flags & AA_CHANGE_TEST)) {
1401 		/*
1402 		 * no new privs prevents domain transitions that would
1403 		 * reduce restrictions.
1404 		 */
1405 		if (task_no_new_privs(current) && !unconfined(label) &&
1406 		    !aa_label_is_unconfined_subset(previous, ctx->nnp)) {
1407 			/* not an apparmor denial per se, so don't log it */
1408 			AA_DEBUG(DEBUG_DOMAIN,
1409 				 "no_new_privs - change_hat denied");
1410 			error = -EPERM;
1411 			goto out;
1412 		}
1413 
1414 		/* Return to saved label.  Kill task if restore fails
1415 		 * to avoid brute force attacks
1416 		 */
1417 		target = previous;
1418 		error = aa_restore_previous_label(token);
1419 		if (error) {
1420 			if (error == -EACCES)
1421 				goto kill;
1422 			goto fail;
1423 		}
1424 	} /* else ignore @flags && restores when there is no saved profile */
1425 
1426 out:
1427 	aa_put_label(new);
1428 	aa_put_label(previous);
1429 	aa_put_label(label);
1430 	put_cred(subj_cred);
1431 
1432 	return error;
1433 
1434 kill:
1435 	info = "failed token match";
1436 	perms.kill = AA_MAY_CHANGEHAT;
1437 
1438 fail:
1439 	fn_for_each_in_scope(label, profile,
1440 		aa_audit_file(subj_cred, profile, &perms, OP_CHANGE_HAT,
1441 			      AA_MAY_CHANGEHAT, NULL, NULL, target,
1442 			      GLOBAL_ROOT_UID, info, error));
1443 
1444 	goto out;
1445 }
1446 
1447 
change_profile_perms_wrapper(const char * op,const char * name,const struct cred * subj_cred,struct aa_profile * profile,struct aa_label * target,bool stack,u32 request,struct aa_perms * perms)1448 static int change_profile_perms_wrapper(const char *op, const char *name,
1449 					const struct cred *subj_cred,
1450 					struct aa_profile *profile,
1451 					struct aa_label *target, bool stack,
1452 					u32 request, struct aa_perms *perms)
1453 {
1454 	struct aa_ruleset *rules = profile->label.rules[0];
1455 	const char *info = NULL;
1456 	int error = 0;
1457 
1458 	if (!error)
1459 		error = change_profile_perms(profile, target, stack, request,
1460 					     rules->file->start[AA_CLASS_FILE],
1461 					     perms);
1462 	if (error)
1463 		error = aa_audit_file(subj_cred, profile, perms, op, request,
1464 				      name,
1465 				      NULL, target, GLOBAL_ROOT_UID, info,
1466 				      error);
1467 
1468 	return error;
1469 }
1470 
1471 /**
1472  * aa_change_profile - perform a one-way profile transition
1473  * @fqname: name of profile may include namespace (NOT NULL)
1474  * @flags: flags affecting change behavior
1475  *
1476  * Change to new profile @name.  Unlike with hats, there is no way
1477  * to change back.  If @name isn't specified the current profile name is
1478  * used.
1479  * If @onexec then the transition is delayed until
1480  * the next exec.
1481  *
1482  * Returns %0 on success, error otherwise.
1483  */
aa_change_profile(const char * fqname,int flags)1484 int aa_change_profile(const char *fqname, int flags)
1485 {
1486 	struct aa_label *label, *new = NULL, *target = NULL;
1487 	struct aa_profile *profile;
1488 	struct aa_perms perms = {};
1489 	const char *info = NULL;
1490 	const char *auditname = fqname;		/* retain leading & if stack */
1491 	bool stack = flags & AA_CHANGE_STACK;
1492 	struct aa_task_ctx *ctx = task_ctx(current);
1493 	const struct cred *subj_cred = get_current_cred();
1494 	int error = 0;
1495 	char *op;
1496 	u32 request;
1497 
1498 	label = aa_get_current_label();
1499 
1500 	/*
1501 	 * Detect no new privs being set, and store the label it
1502 	 * occurred under. Ideally this would happen when nnp
1503 	 * is set but there isn't a good way to do that yet.
1504 	 *
1505 	 * Testing for unconfined must be done before the subset test
1506 	 */
1507 	if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
1508 		ctx->nnp = aa_get_label(label);
1509 
1510 	if (!fqname || !*fqname) {
1511 		aa_put_label(label);
1512 		AA_DEBUG(DEBUG_DOMAIN, "no profile name");
1513 		return -EINVAL;
1514 	}
1515 
1516 	if (flags & AA_CHANGE_ONEXEC) {
1517 		request = AA_MAY_ONEXEC;
1518 		if (stack)
1519 			op = OP_STACK_ONEXEC;
1520 		else
1521 			op = OP_CHANGE_ONEXEC;
1522 	} else {
1523 		request = AA_MAY_CHANGE_PROFILE;
1524 		if (stack)
1525 			op = OP_STACK;
1526 		else
1527 			op = OP_CHANGE_PROFILE;
1528 	}
1529 
1530 	if (*fqname == '&') {
1531 		stack = true;
1532 		/* don't have label_parse() do stacking */
1533 		fqname++;
1534 	}
1535 	target = aa_label_parse(label, fqname, GFP_KERNEL, true, false);
1536 	if (IS_ERR(target)) {
1537 		struct aa_profile *tprofile;
1538 
1539 		info = "label not found";
1540 		error = PTR_ERR(target);
1541 		target = NULL;
1542 		/*
1543 		 * TODO: fixme using labels_profile is not right - do profile
1544 		 * per complain profile
1545 		 */
1546 		if ((flags & AA_CHANGE_TEST) ||
1547 		    !COMPLAIN_MODE(labels_profile(label)))
1548 			goto audit;
1549 		/* released below */
1550 		tprofile = aa_new_learning_profile(labels_profile(label), false,
1551 						   fqname, GFP_KERNEL);
1552 		if (!tprofile) {
1553 			info = "failed null profile create";
1554 			error = -ENOMEM;
1555 			goto audit;
1556 		}
1557 		target = &tprofile->label;
1558 		goto check;
1559 	}
1560 
1561 	/*
1562 	 * self directed transitions only apply to current policy ns
1563 	 * TODO: currently requiring perms for stacking and straight change
1564 	 *       stacking doesn't strictly need this. Determine how much
1565 	 *       we want to loosen this restriction for stacking
1566 	 *
1567 	 * if (!stack) {
1568 	 */
1569 	error = fn_for_each_in_scope(label, profile,
1570 			change_profile_perms_wrapper(op, auditname,
1571 						     subj_cred,
1572 						     profile, target, stack,
1573 						     request, &perms));
1574 	if (error)
1575 		/* auditing done in change_profile_perms_wrapper */
1576 		goto out;
1577 
1578 	/* } */
1579 
1580 check:
1581 	/* check if tracing task is allowed to trace target domain */
1582 	error = may_change_ptraced_domain(subj_cred, target, &info);
1583 	if (error && !fn_for_each_in_scope(label, profile,
1584 					COMPLAIN_MODE(profile)))
1585 		goto audit;
1586 
1587 	/* TODO: add permission check to allow this
1588 	 * if ((flags & AA_CHANGE_ONEXEC) && !current_is_single_threaded()) {
1589 	 *      info = "not a single threaded task";
1590 	 *      error = -EACCES;
1591 	 *      goto audit;
1592 	 * }
1593 	 */
1594 	if (flags & AA_CHANGE_TEST)
1595 		goto out;
1596 
1597 	/* stacking is always a subset, so only check the nonstack case */
1598 	if (!stack) {
1599 		new = fn_label_build_in_scope(label, profile, GFP_KERNEL,
1600 				priv_restricted_transition(subj_cred, profile,
1601 							   op, request,
1602 							   auditname, target,
1603 							   GFP_KERNEL),
1604 					   aa_get_label(&profile->label));
1605 		AA_BUG(!new);
1606 		if (IS_ERR(new))
1607 			goto build_fail;
1608 		/*
1609 		 * no new privs prevents domain transitions that would
1610 		 * reduce restrictions.
1611 		 */
1612 		if (task_no_new_privs(current) && !unconfined(label) &&
1613 		    !aa_label_is_unconfined_subset(new, ctx->nnp)) {
1614 			/* not an apparmor denial per se, so don't log it */
1615 			AA_DEBUG(DEBUG_DOMAIN,
1616 				 "no_new_privs - change_hat denied");
1617 			error = -EPERM;
1618 			goto out;
1619 		}
1620 	}
1621 
1622 	if (!(flags & AA_CHANGE_ONEXEC)) {
1623 		/* only transition profiles in the current ns */
1624 		if (stack)
1625 			new = aa_label_merge(label, target, GFP_KERNEL);
1626 		if (IS_ERR_OR_NULL(new))
1627 			goto build_fail;
1628 		error = aa_replace_current_label(new);
1629 	} else {
1630 		/* new will be recomputed so at exec time. So discard */
1631 		aa_put_label(new);
1632 		new = NULL;
1633 
1634 		/* full transition will be built in exec path */
1635 		aa_set_current_onexec(target, stack);
1636 	}
1637 
1638 	goto audit;
1639 
1640 build_fail:
1641 	info = "failed to build target label";
1642 	if (!new)
1643 		error = -ENOMEM;
1644 	else
1645 		error = PTR_ERR(new);
1646 	new = NULL;
1647 	perms.allow = 0;
1648 
1649 audit:
1650 	error = fn_for_each_in_scope(label, profile,
1651 			aa_audit_file(subj_cred,
1652 				      profile, &perms, op, request, auditname,
1653 				      NULL, new ? new : target,
1654 				      GLOBAL_ROOT_UID, info, error));
1655 
1656 out:
1657 	aa_put_label(new);
1658 	aa_put_label(target);
1659 	aa_put_label(label);
1660 	put_cred(subj_cred);
1661 
1662 	return error;
1663 }
1664