Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * AppArmor security module
4 : : *
5 : : * This file contains AppArmor policy manipulation functions
6 : : *
7 : : * Copyright (C) 1998-2008 Novell/SUSE
8 : : * Copyright 2009-2010 Canonical Ltd.
9 : : *
10 : : * AppArmor policy is based around profiles, which contain the rules a
11 : : * task is confined by. Every task in the system has a profile attached
12 : : * to it determined either by matching "unconfined" tasks against the
13 : : * visible set of profiles or by following a profiles attachment rules.
14 : : *
15 : : * Each profile exists in a profile namespace which is a container of
16 : : * visible profiles. Each namespace contains a special "unconfined" profile,
17 : : * which doesn't enforce any confinement on a task beyond DAC.
18 : : *
19 : : * Namespace and profile names can be written together in either
20 : : * of two syntaxes.
21 : : * :namespace:profile - used by kernel interfaces for easy detection
22 : : * namespace://profile - used by policy
23 : : *
24 : : * Profile names can not start with : or @ or ^ and may not contain \0
25 : : *
26 : : * Reserved profile names
27 : : * unconfined - special automatically generated unconfined profile
28 : : * inherit - special name to indicate profile inheritance
29 : : * null-XXXX-YYYY - special automatically generated learning profiles
30 : : *
31 : : * Namespace names may not start with / or @ and may not contain \0 or :
32 : : * Reserved namespace names
33 : : * user-XXXX - user defined profiles
34 : : *
35 : : * a // in a profile or namespace name indicates a hierarchical name with the
36 : : * name before the // being the parent and the name after the child.
37 : : *
38 : : * Profile and namespace hierarchies serve two different but similar purposes.
39 : : * The namespace contains the set of visible profiles that are considered
40 : : * for attachment. The hierarchy of namespaces allows for virtualizing
41 : : * the namespace so that for example a chroot can have its own set of profiles
42 : : * which may define some local user namespaces.
43 : : * The profile hierarchy severs two distinct purposes,
44 : : * - it allows for sub profiles or hats, which allows an application to run
45 : : * subprograms under its own profile with different restriction than it
46 : : * self, and not have it use the system profile.
47 : : * eg. if a mail program starts an editor, the policy might make the
48 : : * restrictions tighter on the editor tighter than the mail program,
49 : : * and definitely different than general editor restrictions
50 : : * - it allows for binary hierarchy of profiles, so that execution history
51 : : * is preserved. This feature isn't exploited by AppArmor reference policy
52 : : * but is allowed. NOTE: this is currently suboptimal because profile
53 : : * aliasing is not currently implemented so that a profile for each
54 : : * level must be defined.
55 : : * eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
56 : : * from /bin/bash
57 : : *
58 : : * A profile or namespace name that can contain one or more // separators
59 : : * is referred to as an hname (hierarchical).
60 : : * eg. /bin/bash//bin/ls
61 : : *
62 : : * An fqname is a name that may contain both namespace and profile hnames.
63 : : * eg. :ns:/bin/bash//bin/ls
64 : : *
65 : : * NOTES:
66 : : * - locking of profile lists is currently fairly coarse. All profile
67 : : * lists within a namespace use the namespace lock.
68 : : * FIXME: move profile lists to using rcu_lists
69 : : */
70 : :
71 : : #include <linux/slab.h>
72 : : #include <linux/spinlock.h>
73 : : #include <linux/string.h>
74 : : #include <linux/cred.h>
75 : : #include <linux/rculist.h>
76 : : #include <linux/user_namespace.h>
77 : :
78 : : #include "include/apparmor.h"
79 : : #include "include/capability.h"
80 : : #include "include/cred.h"
81 : : #include "include/file.h"
82 : : #include "include/ipc.h"
83 : : #include "include/match.h"
84 : : #include "include/path.h"
85 : : #include "include/policy.h"
86 : : #include "include/policy_ns.h"
87 : : #include "include/policy_unpack.h"
88 : : #include "include/resource.h"
89 : :
90 : : int unprivileged_userns_apparmor_policy = 1;
91 : :
92 : : const char *const aa_profile_mode_names[] = {
93 : : "enforce",
94 : : "complain",
95 : : "kill",
96 : : "unconfined",
97 : : };
98 : :
99 : :
100 : : /**
101 : : * __add_profile - add a profiles to list and label tree
102 : : * @list: list to add it to (NOT NULL)
103 : : * @profile: the profile to add (NOT NULL)
104 : : *
105 : : * refcount @profile, should be put by __list_remove_profile
106 : : *
107 : : * Requires: namespace lock be held, or list not be shared
108 : : */
109 : 0 : static void __add_profile(struct list_head *list, struct aa_profile *profile)
110 : : {
111 : : struct aa_label *l;
112 : :
113 : : AA_BUG(!list);
114 : : AA_BUG(!profile);
115 : : AA_BUG(!profile->ns);
116 : : AA_BUG(!mutex_is_locked(&profile->ns->lock));
117 : :
118 : 0 : list_add_rcu(&profile->base.list, list);
119 : : /* get list reference */
120 : : aa_get_profile(profile);
121 : 0 : l = aa_label_insert(&profile->ns->labels, &profile->label);
122 : : AA_BUG(l != &profile->label);
123 : : aa_put_label(l);
124 : 0 : }
125 : :
126 : : /**
127 : : * __list_remove_profile - remove a profile from the list it is on
128 : : * @profile: the profile to remove (NOT NULL)
129 : : *
130 : : * remove a profile from the list, warning generally removal should
131 : : * be done with __replace_profile as most profile removals are
132 : : * replacements to the unconfined profile.
133 : : *
134 : : * put @profile list refcount
135 : : *
136 : : * Requires: namespace lock be held, or list not have been live
137 : : */
138 : 0 : static void __list_remove_profile(struct aa_profile *profile)
139 : : {
140 : : AA_BUG(!profile);
141 : : AA_BUG(!profile->ns);
142 : : AA_BUG(!mutex_is_locked(&profile->ns->lock));
143 : :
144 : : list_del_rcu(&profile->base.list);
145 : : aa_put_profile(profile);
146 : 0 : }
147 : :
148 : : /**
149 : : * __remove_profile - remove old profile, and children
150 : : * @profile: profile to be replaced (NOT NULL)
151 : : *
152 : : * Requires: namespace list lock be held, or list not be shared
153 : : */
154 : 0 : static void __remove_profile(struct aa_profile *profile)
155 : : {
156 : : AA_BUG(!profile);
157 : : AA_BUG(!profile->ns);
158 : : AA_BUG(!mutex_is_locked(&profile->ns->lock));
159 : :
160 : : /* release any children lists first */
161 : 0 : __aa_profile_list_release(&profile->base.profiles);
162 : : /* released by free_profile */
163 : 0 : aa_label_remove(&profile->label);
164 : 0 : __aafs_profile_rmdir(profile);
165 : 0 : __list_remove_profile(profile);
166 : 0 : }
167 : :
168 : : /**
169 : : * __aa_profile_list_release - remove all profiles on the list and put refs
170 : : * @head: list of profiles (NOT NULL)
171 : : *
172 : : * Requires: namespace lock be held
173 : : */
174 : 0 : void __aa_profile_list_release(struct list_head *head)
175 : : {
176 : : struct aa_profile *profile, *tmp;
177 [ # # ]: 0 : list_for_each_entry_safe(profile, tmp, head, base.list)
178 : 0 : __remove_profile(profile);
179 : 0 : }
180 : :
181 : : /**
182 : : * aa_free_data - free a data blob
183 : : * @ptr: data to free
184 : : * @arg: unused
185 : : */
186 : 0 : static void aa_free_data(void *ptr, void *arg)
187 : : {
188 : : struct aa_data *data = ptr;
189 : :
190 : 0 : kzfree(data->data);
191 : 0 : kzfree(data->key);
192 : 0 : kzfree(data);
193 : 0 : }
194 : :
195 : : /**
196 : : * aa_free_profile - free a profile
197 : : * @profile: the profile to free (MAYBE NULL)
198 : : *
199 : : * Free a profile, its hats and null_profile. All references to the profile,
200 : : * its hats and null_profile must have been put.
201 : : *
202 : : * If the profile was referenced from a task context, free_profile() will
203 : : * be called from an rcu callback routine, so we must not sleep here.
204 : : */
205 : 0 : void aa_free_profile(struct aa_profile *profile)
206 : : {
207 : : struct rhashtable *rht;
208 : : int i;
209 : :
210 : : AA_DEBUG("%s(%p)\n", __func__, profile);
211 : :
212 [ # # ]: 0 : if (!profile)
213 : 0 : return;
214 : :
215 : : /* free children profiles */
216 : 0 : aa_policy_destroy(&profile->base);
217 : 0 : aa_put_profile(rcu_access_pointer(profile->parent));
218 : :
219 : 0 : aa_put_ns(profile->ns);
220 : 0 : kzfree(profile->rename);
221 : :
222 : 0 : aa_free_file_rules(&profile->file);
223 : : aa_free_cap_rules(&profile->caps);
224 : : aa_free_rlimit_rules(&profile->rlimits);
225 : :
226 [ # # ]: 0 : for (i = 0; i < profile->xattr_count; i++)
227 : 0 : kzfree(profile->xattrs[i]);
228 : 0 : kzfree(profile->xattrs);
229 [ # # ]: 0 : for (i = 0; i < profile->secmark_count; i++)
230 : 0 : kzfree(profile->secmark[i].label);
231 : 0 : kzfree(profile->secmark);
232 : 0 : kzfree(profile->dirname);
233 : 0 : aa_put_dfa(profile->xmatch);
234 : 0 : aa_put_dfa(profile->policy.dfa);
235 : :
236 [ # # ]: 0 : if (profile->data) {
237 : : rht = profile->data;
238 : 0 : profile->data = NULL;
239 : 0 : rhashtable_free_and_destroy(rht, aa_free_data, NULL);
240 : 0 : kzfree(rht);
241 : : }
242 : :
243 : 0 : kzfree(profile->hash);
244 : 0 : aa_put_loaddata(profile->rawdata);
245 : :
246 : 0 : kzfree(profile);
247 : : }
248 : :
249 : : /**
250 : : * aa_alloc_profile - allocate, initialize and return a new profile
251 : : * @hname: name of the profile (NOT NULL)
252 : : * @gfp: allocation type
253 : : *
254 : : * Returns: refcount profile or NULL on failure
255 : : */
256 : 0 : struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy,
257 : : gfp_t gfp)
258 : : {
259 : : struct aa_profile *profile;
260 : :
261 : : /* freed by free_profile - usually through aa_put_profile */
262 : 0 : profile = kzalloc(sizeof(*profile) + sizeof(struct aa_profile *) * 2,
263 : : gfp);
264 [ # # ]: 0 : if (!profile)
265 : : return NULL;
266 : :
267 [ # # ]: 0 : if (!aa_policy_init(&profile->base, NULL, hname, gfp))
268 : : goto fail;
269 [ # # ]: 0 : if (!aa_label_init(&profile->label, 1, gfp))
270 : : goto fail;
271 : :
272 : : /* update being set needed by fs interface */
273 [ # # ]: 0 : if (!proxy) {
274 : 0 : proxy = aa_alloc_proxy(&profile->label, gfp);
275 [ # # ]: 0 : if (!proxy)
276 : : goto fail;
277 : : } else
278 : : aa_get_proxy(proxy);
279 : 0 : profile->label.proxy = proxy;
280 : :
281 : 0 : profile->label.hname = profile->base.hname;
282 : 0 : profile->label.flags |= FLAG_PROFILE;
283 : 0 : profile->label.vec[0] = profile;
284 : :
285 : : /* refcount released by caller */
286 : 0 : return profile;
287 : :
288 : : fail:
289 : 0 : aa_free_profile(profile);
290 : :
291 : 0 : return NULL;
292 : : }
293 : :
294 : : /* TODO: profile accounting - setup in remove */
295 : :
296 : : /**
297 : : * __strn_find_child - find a profile on @head list using substring of @name
298 : : * @head: list to search (NOT NULL)
299 : : * @name: name of profile (NOT NULL)
300 : : * @len: length of @name substring to match
301 : : *
302 : : * Requires: rcu_read_lock be held
303 : : *
304 : : * Returns: unrefcounted profile ptr, or NULL if not found
305 : : */
306 : : static struct aa_profile *__strn_find_child(struct list_head *head,
307 : : const char *name, int len)
308 : : {
309 : 0 : return (struct aa_profile *)__policy_strn_find(head, name, len);
310 : : }
311 : :
312 : : /**
313 : : * __find_child - find a profile on @head list with a name matching @name
314 : : * @head: list to search (NOT NULL)
315 : : * @name: name of profile (NOT NULL)
316 : : *
317 : : * Requires: rcu_read_lock be held
318 : : *
319 : : * Returns: unrefcounted profile ptr, or NULL if not found
320 : : */
321 : 0 : static struct aa_profile *__find_child(struct list_head *head, const char *name)
322 : : {
323 : 0 : return __strn_find_child(head, name, strlen(name));
324 : : }
325 : :
326 : : /**
327 : : * aa_find_child - find a profile by @name in @parent
328 : : * @parent: profile to search (NOT NULL)
329 : : * @name: profile name to search for (NOT NULL)
330 : : *
331 : : * Returns: a refcounted profile or NULL if not found
332 : : */
333 : 0 : struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
334 : : {
335 : : struct aa_profile *profile;
336 : :
337 : : rcu_read_lock();
338 : : do {
339 : 0 : profile = __find_child(&parent->base.profiles, name);
340 [ # # # # ]: 0 : } while (profile && !aa_get_profile_not0(profile));
341 : : rcu_read_unlock();
342 : :
343 : : /* refcount released by caller */
344 : 0 : return profile;
345 : : }
346 : :
347 : : /**
348 : : * __lookup_parent - lookup the parent of a profile of name @hname
349 : : * @ns: namespace to lookup profile in (NOT NULL)
350 : : * @hname: hierarchical profile name to find parent of (NOT NULL)
351 : : *
352 : : * Lookups up the parent of a fully qualified profile name, the profile
353 : : * that matches hname does not need to exist, in general this
354 : : * is used to load a new profile.
355 : : *
356 : : * Requires: rcu_read_lock be held
357 : : *
358 : : * Returns: unrefcounted policy or NULL if not found
359 : : */
360 : 0 : static struct aa_policy *__lookup_parent(struct aa_ns *ns,
361 : : const char *hname)
362 : : {
363 : : struct aa_policy *policy;
364 : : struct aa_profile *profile = NULL;
365 : : char *split;
366 : :
367 : 0 : policy = &ns->base;
368 : :
369 [ # # ]: 0 : for (split = strstr(hname, "//"); split;) {
370 : 0 : profile = __strn_find_child(&policy->profiles, hname,
371 : : split - hname);
372 [ # # ]: 0 : if (!profile)
373 : : return NULL;
374 : 0 : policy = &profile->base;
375 : 0 : hname = split + 2;
376 : 0 : split = strstr(hname, "//");
377 : : }
378 [ # # ]: 0 : if (!profile)
379 : : return &ns->base;
380 : 0 : return &profile->base;
381 : : }
382 : :
383 : : /**
384 : : * __lookupn_profile - lookup the profile matching @hname
385 : : * @base: base list to start looking up profile name from (NOT NULL)
386 : : * @hname: hierarchical profile name (NOT NULL)
387 : : * @n: length of @hname
388 : : *
389 : : * Requires: rcu_read_lock be held
390 : : *
391 : : * Returns: unrefcounted profile pointer or NULL if not found
392 : : *
393 : : * Do a relative name lookup, recursing through profile tree.
394 : : */
395 : 0 : static struct aa_profile *__lookupn_profile(struct aa_policy *base,
396 : : const char *hname, size_t n)
397 : : {
398 : : struct aa_profile *profile = NULL;
399 : : const char *split;
400 : :
401 [ # # ]: 0 : for (split = strnstr(hname, "//", n); split;
402 : 0 : split = strnstr(hname, "//", n)) {
403 : 0 : profile = __strn_find_child(&base->profiles, hname,
404 : : split - hname);
405 [ # # ]: 0 : if (!profile)
406 : : return NULL;
407 : :
408 : 0 : base = &profile->base;
409 : 0 : n -= split + 2 - hname;
410 : : hname = split + 2;
411 : : }
412 : :
413 [ # # ]: 0 : if (n)
414 : 0 : return __strn_find_child(&base->profiles, hname, n);
415 : : return NULL;
416 : : }
417 : :
418 : 0 : static struct aa_profile *__lookup_profile(struct aa_policy *base,
419 : : const char *hname)
420 : : {
421 : 0 : return __lookupn_profile(base, hname, strlen(hname));
422 : : }
423 : :
424 : : /**
425 : : * aa_lookup_profile - find a profile by its full or partial name
426 : : * @ns: the namespace to start from (NOT NULL)
427 : : * @hname: name to do lookup on. Does not contain namespace prefix (NOT NULL)
428 : : * @n: size of @hname
429 : : *
430 : : * Returns: refcounted profile or NULL if not found
431 : : */
432 : 0 : struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname,
433 : : size_t n)
434 : : {
435 : : struct aa_profile *profile;
436 : :
437 : : rcu_read_lock();
438 : : do {
439 : 0 : profile = __lookupn_profile(&ns->base, hname, n);
440 [ # # # # ]: 0 : } while (profile && !aa_get_profile_not0(profile));
441 : : rcu_read_unlock();
442 : :
443 : : /* the unconfined profile is not in the regular profile list */
444 [ # # # # ]: 0 : if (!profile && strncmp(hname, "unconfined", n) == 0)
445 : 0 : profile = aa_get_newest_profile(ns->unconfined);
446 : :
447 : : /* refcount released by caller */
448 : 0 : return profile;
449 : : }
450 : :
451 : 0 : struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *hname)
452 : : {
453 : 0 : return aa_lookupn_profile(ns, hname, strlen(hname));
454 : : }
455 : :
456 : 0 : struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
457 : : const char *fqname, size_t n)
458 : : {
459 : : struct aa_profile *profile;
460 : : struct aa_ns *ns;
461 : : const char *name, *ns_name;
462 : : size_t ns_len;
463 : :
464 : 0 : name = aa_splitn_fqname(fqname, n, &ns_name, &ns_len);
465 [ # # ]: 0 : if (ns_name) {
466 : 0 : ns = aa_lookupn_ns(labels_ns(base), ns_name, ns_len);
467 [ # # ]: 0 : if (!ns)
468 : : return NULL;
469 : : } else
470 : 0 : ns = aa_get_ns(labels_ns(base));
471 : :
472 [ # # ]: 0 : if (name)
473 : 0 : profile = aa_lookupn_profile(ns, name, n - (name - fqname));
474 [ # # ]: 0 : else if (ns)
475 : : /* default profile for ns, currently unconfined */
476 : 0 : profile = aa_get_newest_profile(ns->unconfined);
477 : : else
478 : : profile = NULL;
479 : 0 : aa_put_ns(ns);
480 : :
481 : 0 : return profile;
482 : : }
483 : :
484 : : /**
485 : : * aa_new_null_profile - create or find a null-X learning profile
486 : : * @parent: profile that caused this profile to be created (NOT NULL)
487 : : * @hat: true if the null- learning profile is a hat
488 : : * @base: name to base the null profile off of
489 : : * @gfp: type of allocation
490 : : *
491 : : * Find/Create a null- complain mode profile used in learning mode. The
492 : : * name of the profile is unique and follows the format of parent//null-XXX.
493 : : * where XXX is based on the @name or if that fails or is not supplied
494 : : * a unique number
495 : : *
496 : : * null profiles are added to the profile list but the list does not
497 : : * hold a count on them so that they are automatically released when
498 : : * not in use.
499 : : *
500 : : * Returns: new refcounted profile else NULL on failure
501 : : */
502 : 0 : struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
503 : : const char *base, gfp_t gfp)
504 : : {
505 : : struct aa_profile *p, *profile;
506 : : const char *bname;
507 : : char *name = NULL;
508 : :
509 : : AA_BUG(!parent);
510 : :
511 [ # # ]: 0 : if (base) {
512 : 0 : name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base),
513 : : gfp);
514 [ # # ]: 0 : if (name) {
515 : 0 : sprintf(name, "%s//null-%s", parent->base.hname, base);
516 : 0 : goto name;
517 : : }
518 : : /* fall through to try shorter uniq */
519 : : }
520 : :
521 : 0 : name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp);
522 [ # # ]: 0 : if (!name)
523 : : return NULL;
524 : 0 : sprintf(name, "%s//null-%x", parent->base.hname,
525 : 0 : atomic_inc_return(&parent->ns->uniq_null));
526 : :
527 : : name:
528 : : /* lookup to see if this is a dup creation */
529 : 0 : bname = basename(name);
530 : 0 : profile = aa_find_child(parent, bname);
531 [ # # ]: 0 : if (profile)
532 : : goto out;
533 : :
534 : 0 : profile = aa_alloc_profile(name, NULL, gfp);
535 [ # # ]: 0 : if (!profile)
536 : : goto fail;
537 : :
538 : 0 : profile->mode = APPARMOR_COMPLAIN;
539 : 0 : profile->label.flags |= FLAG_NULL;
540 [ # # ]: 0 : if (hat)
541 : 0 : profile->label.flags |= FLAG_HAT;
542 : 0 : profile->path_flags = parent->path_flags;
543 : :
544 : : /* released on free_profile */
545 : 0 : rcu_assign_pointer(profile->parent, aa_get_profile(parent));
546 : 0 : profile->ns = aa_get_ns(parent->ns);
547 : 0 : profile->file.dfa = aa_get_dfa(nulldfa);
548 : 0 : profile->policy.dfa = aa_get_dfa(nulldfa);
549 : :
550 : 0 : mutex_lock_nested(&profile->ns->lock, profile->ns->level);
551 : 0 : p = __find_child(&parent->base.profiles, bname);
552 [ # # ]: 0 : if (p) {
553 : 0 : aa_free_profile(profile);
554 : : profile = aa_get_profile(p);
555 : : } else {
556 : 0 : __add_profile(&parent->base.profiles, profile);
557 : : }
558 : 0 : mutex_unlock(&profile->ns->lock);
559 : :
560 : : /* refcount released by caller */
561 : : out:
562 : 0 : kfree(name);
563 : :
564 : 0 : return profile;
565 : :
566 : : fail:
567 : 0 : kfree(name);
568 : 0 : aa_free_profile(profile);
569 : 0 : return NULL;
570 : : }
571 : :
572 : : /**
573 : : * replacement_allowed - test to see if replacement is allowed
574 : : * @profile: profile to test if it can be replaced (MAYBE NULL)
575 : : * @noreplace: true if replacement shouldn't be allowed but addition is okay
576 : : * @info: Returns - info about why replacement failed (NOT NULL)
577 : : *
578 : : * Returns: %0 if replacement allowed else error code
579 : : */
580 : : static int replacement_allowed(struct aa_profile *profile, int noreplace,
581 : : const char **info)
582 : : {
583 [ # # ]: 0 : if (profile) {
584 [ # # ]: 0 : if (profile->label.flags & FLAG_IMMUTIBLE) {
585 : 0 : *info = "cannot replace immutible profile";
586 : : return -EPERM;
587 [ # # ]: 0 : } else if (noreplace) {
588 : 0 : *info = "profile already exists";
589 : : return -EEXIST;
590 : : }
591 : : }
592 : : return 0;
593 : : }
594 : :
595 : : /* audit callback for net specific fields */
596 : 0 : static void audit_cb(struct audit_buffer *ab, void *va)
597 : : {
598 : : struct common_audit_data *sa = va;
599 : :
600 [ # # ]: 0 : if (aad(sa)->iface.ns) {
601 : 0 : audit_log_format(ab, " ns=");
602 : 0 : audit_log_untrustedstring(ab, aad(sa)->iface.ns);
603 : : }
604 : 0 : }
605 : :
606 : : /**
607 : : * audit_policy - Do auditing of policy changes
608 : : * @label: label to check if it can manage policy
609 : : * @op: policy operation being performed
610 : : * @ns_name: name of namespace being manipulated
611 : : * @name: name of profile being manipulated (NOT NULL)
612 : : * @info: any extra information to be audited (MAYBE NULL)
613 : : * @error: error code
614 : : *
615 : : * Returns: the error to be returned after audit is done
616 : : */
617 : 0 : static int audit_policy(struct aa_label *label, const char *op,
618 : : const char *ns_name, const char *name,
619 : : const char *info, int error)
620 : : {
621 : 0 : DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
622 : :
623 : 0 : aad(&sa)->iface.ns = ns_name;
624 : 0 : aad(&sa)->name = name;
625 : 0 : aad(&sa)->info = info;
626 : 0 : aad(&sa)->error = error;
627 : 0 : aad(&sa)->label = label;
628 : :
629 : 0 : aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, audit_cb);
630 : :
631 : 0 : return error;
632 : : }
633 : :
634 : : /**
635 : : * policy_view_capable - check if viewing policy in at @ns is allowed
636 : : * ns: namespace being viewed by current task (may be NULL)
637 : : * Returns: true if viewing policy is allowed
638 : : *
639 : : * If @ns is NULL then the namespace being viewed is assumed to be the
640 : : * tasks current namespace.
641 : : */
642 : 0 : bool policy_view_capable(struct aa_ns *ns)
643 : : {
644 : 0 : struct user_namespace *user_ns = current_user_ns();
645 : 0 : struct aa_ns *view_ns = aa_get_current_ns();
646 [ # # # # ]: 0 : bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) ||
647 : 0 : in_egroup_p(make_kgid(user_ns, 0));
648 : : bool response = false;
649 [ # # ]: 0 : if (!ns)
650 : : ns = view_ns;
651 : :
652 [ # # # # : 0 : if (root_in_user_ns && aa_ns_visible(view_ns, ns, true) &&
# # ]
653 [ # # ]: 0 : (user_ns == &init_user_ns ||
654 [ # # ]: 0 : (unprivileged_userns_apparmor_policy != 0 &&
655 : 0 : user_ns->level == view_ns->level)))
656 : : response = true;
657 : 0 : aa_put_ns(view_ns);
658 : :
659 : 0 : return response;
660 : : }
661 : :
662 : 0 : bool policy_admin_capable(struct aa_ns *ns)
663 : : {
664 : 0 : struct user_namespace *user_ns = current_user_ns();
665 : 0 : bool capable = ns_capable(user_ns, CAP_MAC_ADMIN);
666 : :
667 : : AA_DEBUG("cap_mac_admin? %d\n", capable);
668 : : AA_DEBUG("policy locked? %d\n", aa_g_lock_policy);
669 : :
670 [ # # # # : 0 : return policy_view_capable(ns) && capable && !aa_g_lock_policy;
# # ]
671 : : }
672 : :
673 : : /**
674 : : * aa_may_manage_policy - can the current task manage policy
675 : : * @label: label to check if it can manage policy
676 : : * @op: the policy manipulation operation being done
677 : : *
678 : : * Returns: 0 if the task is allowed to manipulate policy else error
679 : : */
680 : 0 : int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask)
681 : : {
682 : : const char *op;
683 : :
684 [ # # ]: 0 : if (mask & AA_MAY_REMOVE_POLICY)
685 : : op = OP_PROF_RM;
686 [ # # ]: 0 : else if (mask & AA_MAY_REPLACE_POLICY)
687 : : op = OP_PROF_REPL;
688 : : else
689 : : op = OP_PROF_LOAD;
690 : :
691 : : /* check if loading policy is locked out */
692 [ # # ]: 0 : if (aa_g_lock_policy)
693 : 0 : return audit_policy(label, op, NULL, NULL, "policy_locked",
694 : : -EACCES);
695 : :
696 [ # # ]: 0 : if (!policy_admin_capable(ns))
697 : 0 : return audit_policy(label, op, NULL, NULL, "not policy admin",
698 : : -EACCES);
699 : :
700 : : /* TODO: add fine grained mediation of policy loads */
701 : : return 0;
702 : : }
703 : :
704 : 0 : static struct aa_profile *__list_lookup_parent(struct list_head *lh,
705 : : struct aa_profile *profile)
706 : : {
707 : 0 : const char *base = basename(profile->base.hname);
708 : 0 : long len = base - profile->base.hname;
709 : : struct aa_load_ent *ent;
710 : :
711 : : /* parent won't have trailing // so remove from len */
712 [ # # ]: 0 : if (len <= 2)
713 : : return NULL;
714 : 0 : len -= 2;
715 : :
716 [ # # ]: 0 : list_for_each_entry(ent, lh, list) {
717 [ # # ]: 0 : if (ent->new == profile)
718 : 0 : continue;
719 [ # # ]: 0 : if (strncmp(ent->new->base.hname, profile->base.hname, len) ==
720 [ # # ]: 0 : 0 && ent->new->base.hname[len] == 0)
721 : 0 : return ent->new;
722 : : }
723 : :
724 : : return NULL;
725 : : }
726 : :
727 : : /**
728 : : * __replace_profile - replace @old with @new on a list
729 : : * @old: profile to be replaced (NOT NULL)
730 : : * @new: profile to replace @old with (NOT NULL)
731 : : * @share_proxy: transfer @old->proxy to @new
732 : : *
733 : : * Will duplicate and refcount elements that @new inherits from @old
734 : : * and will inherit @old children.
735 : : *
736 : : * refcount @new for list, put @old list refcount
737 : : *
738 : : * Requires: namespace list lock be held, or list not be shared
739 : : */
740 : 0 : static void __replace_profile(struct aa_profile *old, struct aa_profile *new)
741 : : {
742 : : struct aa_profile *child, *tmp;
743 : :
744 [ # # ]: 0 : if (!list_empty(&old->base.profiles)) {
745 : 0 : LIST_HEAD(lh);
746 : : list_splice_init_rcu(&old->base.profiles, &lh, synchronize_rcu);
747 : :
748 [ # # ]: 0 : list_for_each_entry_safe(child, tmp, &lh, base.list) {
749 : : struct aa_profile *p;
750 : :
751 : : list_del_init(&child->base.list);
752 : 0 : p = __find_child(&new->base.profiles, child->base.name);
753 [ # # ]: 0 : if (p) {
754 : : /* @p replaces @child */
755 : 0 : __replace_profile(child, p);
756 : 0 : continue;
757 : : }
758 : :
759 : : /* inherit @child and its children */
760 : : /* TODO: update hname of inherited children */
761 : : /* list refcount transferred to @new */
762 : : p = aa_deref_parent(child);
763 : 0 : rcu_assign_pointer(child->parent, aa_get_profile(new));
764 : : list_add_rcu(&child->base.list, &new->base.profiles);
765 : : aa_put_profile(p);
766 : : }
767 : : }
768 : :
769 [ # # ]: 0 : if (!rcu_access_pointer(new->parent)) {
770 : : struct aa_profile *parent = aa_deref_parent(old);
771 : 0 : rcu_assign_pointer(new->parent, aa_get_profile(parent));
772 : : }
773 : 0 : aa_label_replace(&old->label, &new->label);
774 : : /* migrate dents must come after label replacement b/c update */
775 : 0 : __aafs_profile_migrate_dents(old, new);
776 : :
777 [ # # ]: 0 : if (list_empty(&new->base.list)) {
778 : : /* new is not on a list already */
779 : : list_replace_rcu(&old->base.list, &new->base.list);
780 : : aa_get_profile(new);
781 : : aa_put_profile(old);
782 : : } else
783 : 0 : __list_remove_profile(old);
784 : 0 : }
785 : :
786 : : /**
787 : : * __lookup_replace - lookup replacement information for a profile
788 : : * @ns - namespace the lookup occurs in
789 : : * @hname - name of profile to lookup
790 : : * @noreplace - true if not replacing an existing profile
791 : : * @p - Returns: profile to be replaced
792 : : * @info - Returns: info string on why lookup failed
793 : : *
794 : : * Returns: profile to replace (no ref) on success else ptr error
795 : : */
796 : 0 : static int __lookup_replace(struct aa_ns *ns, const char *hname,
797 : : bool noreplace, struct aa_profile **p,
798 : : const char **info)
799 : : {
800 : 0 : *p = aa_get_profile(__lookup_profile(&ns->base, hname));
801 [ # # ]: 0 : if (*p) {
802 : : int error = replacement_allowed(*p, noreplace, info);
803 [ # # ]: 0 : if (error) {
804 : 0 : *info = "profile can not be replaced";
805 : 0 : return error;
806 : : }
807 : : }
808 : :
809 : : return 0;
810 : : }
811 : :
812 : 0 : static void share_name(struct aa_profile *old, struct aa_profile *new)
813 : : {
814 : 0 : aa_put_str(new->base.hname);
815 : 0 : aa_get_str(old->base.hname);
816 : 0 : new->base.hname = old->base.hname;
817 : 0 : new->base.name = old->base.name;
818 : 0 : new->label.hname = old->label.hname;
819 : 0 : }
820 : :
821 : : /* Update to newest version of parent after previous replacements
822 : : * Returns: unrefcount newest version of parent
823 : : */
824 : 0 : static struct aa_profile *update_to_newest_parent(struct aa_profile *new)
825 : : {
826 : : struct aa_profile *parent, *newest;
827 : :
828 : 0 : parent = rcu_dereference_protected(new->parent,
829 : : mutex_is_locked(&new->ns->lock));
830 : 0 : newest = aa_get_newest_profile(parent);
831 : :
832 : : /* parent replaced in this atomic set? */
833 [ # # ]: 0 : if (newest != parent) {
834 : : aa_put_profile(parent);
835 : 0 : rcu_assign_pointer(new->parent, newest);
836 : : } else
837 : : aa_put_profile(newest);
838 : :
839 : 0 : return newest;
840 : : }
841 : :
842 : : /**
843 : : * aa_replace_profiles - replace profile(s) on the profile list
844 : : * @policy_ns: namespace load is occurring on
845 : : * @label: label that is attempting to load/replace policy
846 : : * @mask: permission mask
847 : : * @udata: serialized data stream (NOT NULL)
848 : : *
849 : : * unpack and replace a profile on the profile list and uses of that profile
850 : : * by any task creds via invalidating the old version of the profile, which
851 : : * tasks will notice to update their own cred. If the profile does not exist
852 : : * on the profile list it is added.
853 : : *
854 : : * Returns: size of data consumed else error code on failure.
855 : : */
856 : 0 : ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label,
857 : : u32 mask, struct aa_loaddata *udata)
858 : : {
859 : 0 : const char *ns_name, *info = NULL;
860 : : struct aa_ns *ns = NULL;
861 : : struct aa_load_ent *ent, *tmp;
862 : : struct aa_loaddata *rawdata_ent;
863 : : const char *op;
864 : : ssize_t count, error;
865 : 0 : LIST_HEAD(lh);
866 : :
867 [ # # ]: 0 : op = mask & AA_MAY_REPLACE_POLICY ? OP_PROF_REPL : OP_PROF_LOAD;
868 : : aa_get_loaddata(udata);
869 : : /* released below */
870 : 0 : error = aa_unpack(udata, &lh, &ns_name);
871 [ # # ]: 0 : if (error)
872 : : goto out;
873 : :
874 : : /* ensure that profiles are all for the same ns
875 : : * TODO: update locking to remove this constaint. All profiles in
876 : : * the load set must succeed as a set or the load will
877 : : * fail. Sort ent list and take ns locks in hierarchy order
878 : : */
879 : : count = 0;
880 [ # # ]: 0 : list_for_each_entry(ent, &lh, list) {
881 [ # # ]: 0 : if (ns_name) {
882 [ # # # # ]: 0 : if (ent->ns_name &&
883 : 0 : strcmp(ent->ns_name, ns_name) != 0) {
884 : 0 : info = "policy load has mixed namespaces";
885 : : error = -EACCES;
886 : 0 : goto fail;
887 : : }
888 [ # # ]: 0 : } else if (ent->ns_name) {
889 [ # # ]: 0 : if (count) {
890 : 0 : info = "policy load has mixed namespaces";
891 : : error = -EACCES;
892 : 0 : goto fail;
893 : : }
894 : 0 : ns_name = ent->ns_name;
895 : : } else
896 : 0 : count++;
897 : : }
898 [ # # ]: 0 : if (ns_name) {
899 [ # # ]: 0 : ns = aa_prepare_ns(policy_ns ? policy_ns : labels_ns(label),
900 : : ns_name);
901 [ # # ]: 0 : if (IS_ERR(ns)) {
902 : : op = OP_PROF_LOAD;
903 : 0 : info = "failed to prepare namespace";
904 : : error = PTR_ERR(ns);
905 : : ns = NULL;
906 : : ent = NULL;
907 : 0 : goto fail;
908 : : }
909 : : } else
910 [ # # ]: 0 : ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(label));
911 : :
912 : 0 : mutex_lock_nested(&ns->lock, ns->level);
913 : : /* check for duplicate rawdata blobs: space and file dedup */
914 [ # # ]: 0 : list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) {
915 [ # # ]: 0 : if (aa_rawdata_eq(rawdata_ent, udata)) {
916 : : struct aa_loaddata *tmp;
917 : :
918 : : tmp = __aa_get_loaddata(rawdata_ent);
919 : : /* check we didn't fail the race */
920 [ # # ]: 0 : if (tmp) {
921 : : aa_put_loaddata(udata);
922 : 0 : udata = tmp;
923 : 0 : break;
924 : : }
925 : : }
926 : : }
927 : : /* setup parent and ns info */
928 [ # # ]: 0 : list_for_each_entry(ent, &lh, list) {
929 : : struct aa_policy *policy;
930 : :
931 : 0 : ent->new->rawdata = aa_get_loaddata(udata);
932 : 0 : error = __lookup_replace(ns, ent->new->base.hname,
933 : : !(mask & AA_MAY_REPLACE_POLICY),
934 : : &ent->old, &info);
935 [ # # ]: 0 : if (error)
936 : : goto fail_lock;
937 : :
938 [ # # ]: 0 : if (ent->new->rename) {
939 : 0 : error = __lookup_replace(ns, ent->new->rename,
940 : : !(mask & AA_MAY_REPLACE_POLICY),
941 : : &ent->rename, &info);
942 [ # # ]: 0 : if (error)
943 : : goto fail_lock;
944 : : }
945 : :
946 : : /* released when @new is freed */
947 : 0 : ent->new->ns = aa_get_ns(ns);
948 : :
949 [ # # # # ]: 0 : if (ent->old || ent->rename)
950 : 0 : continue;
951 : :
952 : : /* no ref on policy only use inside lock */
953 : 0 : policy = __lookup_parent(ns, ent->new->base.hname);
954 [ # # ]: 0 : if (!policy) {
955 : : struct aa_profile *p;
956 : 0 : p = __list_lookup_parent(&lh, ent->new);
957 [ # # ]: 0 : if (!p) {
958 : : error = -ENOENT;
959 : 0 : info = "parent does not exist";
960 : 0 : goto fail_lock;
961 : : }
962 : 0 : rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
963 [ # # ]: 0 : } else if (policy != &ns->base) {
964 : : /* released on profile replacement or free_profile */
965 : : struct aa_profile *p = (struct aa_profile *) policy;
966 : 0 : rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
967 : : }
968 : : }
969 : :
970 : : /* create new fs entries for introspection if needed */
971 [ # # ]: 0 : if (!udata->dents[AAFS_LOADDATA_DIR]) {
972 : 0 : error = __aa_fs_create_rawdata(ns, udata);
973 [ # # ]: 0 : if (error) {
974 : 0 : info = "failed to create raw_data dir and files";
975 : : ent = NULL;
976 : 0 : goto fail_lock;
977 : : }
978 : : }
979 [ # # ]: 0 : list_for_each_entry(ent, &lh, list) {
980 [ # # ]: 0 : if (!ent->old) {
981 : : struct dentry *parent;
982 [ # # ]: 0 : if (rcu_access_pointer(ent->new->parent)) {
983 : : struct aa_profile *p;
984 : : p = aa_deref_parent(ent->new);
985 : 0 : parent = prof_child_dir(p);
986 : : } else
987 : 0 : parent = ns_subprofs_dir(ent->new->ns);
988 : 0 : error = __aafs_profile_mkdir(ent->new, parent);
989 : : }
990 : :
991 [ # # ]: 0 : if (error) {
992 : 0 : info = "failed to create";
993 : 0 : goto fail_lock;
994 : : }
995 : : }
996 : :
997 : : /* Done with checks that may fail - do actual replacement */
998 : 0 : __aa_bump_ns_revision(ns);
999 : 0 : __aa_loaddata_update(udata, ns->revision);
1000 [ # # ]: 0 : list_for_each_entry_safe(ent, tmp, &lh, list) {
1001 : : list_del_init(&ent->list);
1002 [ # # # # ]: 0 : op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL;
1003 : :
1004 [ # # # # ]: 0 : if (ent->old && ent->old->rawdata == ent->new->rawdata) {
1005 : : /* dedup actual profile replacement */
1006 : 0 : audit_policy(label, op, ns_name, ent->new->base.hname,
1007 : : "same as current profile, skipping",
1008 : : error);
1009 : : /* break refcount cycle with proxy. */
1010 : 0 : aa_put_proxy(ent->new->label.proxy);
1011 : 0 : ent->new->label.proxy = NULL;
1012 : 0 : goto skip;
1013 : : }
1014 : :
1015 : : /*
1016 : : * TODO: finer dedup based on profile range in data. Load set
1017 : : * can differ but profile may remain unchanged
1018 : : */
1019 : 0 : audit_policy(label, op, ns_name, ent->new->base.hname, NULL,
1020 : : error);
1021 : :
1022 [ # # ]: 0 : if (ent->old) {
1023 : 0 : share_name(ent->old, ent->new);
1024 : 0 : __replace_profile(ent->old, ent->new);
1025 : : } else {
1026 : : struct list_head *lh;
1027 : :
1028 [ # # ]: 0 : if (rcu_access_pointer(ent->new->parent)) {
1029 : : struct aa_profile *parent;
1030 : :
1031 : 0 : parent = update_to_newest_parent(ent->new);
1032 : 0 : lh = &parent->base.profiles;
1033 : : } else
1034 : 0 : lh = &ns->base.profiles;
1035 : 0 : __add_profile(lh, ent->new);
1036 : : }
1037 : : skip:
1038 : 0 : aa_load_ent_free(ent);
1039 : : }
1040 : 0 : __aa_labelset_update_subtree(ns);
1041 : 0 : mutex_unlock(&ns->lock);
1042 : :
1043 : : out:
1044 : 0 : aa_put_ns(ns);
1045 : : aa_put_loaddata(udata);
1046 : :
1047 [ # # ]: 0 : if (error)
1048 : : return error;
1049 : 0 : return udata->size;
1050 : :
1051 : : fail_lock:
1052 : 0 : mutex_unlock(&ns->lock);
1053 : :
1054 : : /* audit cause of failure */
1055 [ # # # # ]: 0 : op = (ent && !ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
1056 : : fail:
1057 [ # # ]: 0 : audit_policy(label, op, ns_name, ent ? ent->new->base.hname : NULL,
1058 : : info, error);
1059 : : /* audit status that rest of profiles in the atomic set failed too */
1060 : 0 : info = "valid profile in failed atomic policy load";
1061 [ # # ]: 0 : list_for_each_entry(tmp, &lh, list) {
1062 [ # # ]: 0 : if (tmp == ent) {
1063 : 0 : info = "unchecked profile in failed atomic policy load";
1064 : : /* skip entry that caused failure */
1065 : 0 : continue;
1066 : : }
1067 [ # # ]: 0 : op = (!tmp->old) ? OP_PROF_LOAD : OP_PROF_REPL;
1068 : 0 : audit_policy(label, op, ns_name, tmp->new->base.hname, info,
1069 : : error);
1070 : : }
1071 [ # # ]: 0 : list_for_each_entry_safe(ent, tmp, &lh, list) {
1072 : : list_del_init(&ent->list);
1073 : 0 : aa_load_ent_free(ent);
1074 : : }
1075 : :
1076 : : goto out;
1077 : : }
1078 : :
1079 : : /**
1080 : : * aa_remove_profiles - remove profile(s) from the system
1081 : : * @policy_ns: namespace the remove is being done from
1082 : : * @subj: label attempting to remove policy
1083 : : * @fqname: name of the profile or namespace to remove (NOT NULL)
1084 : : * @size: size of the name
1085 : : *
1086 : : * Remove a profile or sub namespace from the current namespace, so that
1087 : : * they can not be found anymore and mark them as replaced by unconfined
1088 : : *
1089 : : * NOTE: removing confinement does not restore rlimits to preconfinement values
1090 : : *
1091 : : * Returns: size of data consume else error code if fails
1092 : : */
1093 : 0 : ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj,
1094 : : char *fqname, size_t size)
1095 : : {
1096 : : struct aa_ns *ns = NULL;
1097 : : struct aa_profile *profile = NULL;
1098 : : const char *name = fqname, *info = NULL;
1099 : 0 : const char *ns_name = NULL;
1100 : : ssize_t error = 0;
1101 : :
1102 [ # # ]: 0 : if (*fqname == 0) {
1103 : : info = "no profile specified";
1104 : : error = -ENOENT;
1105 : : goto fail;
1106 : : }
1107 : :
1108 [ # # ]: 0 : if (fqname[0] == ':') {
1109 : : size_t ns_len;
1110 : :
1111 : 0 : name = aa_splitn_fqname(fqname, size, &ns_name, &ns_len);
1112 : : /* released below */
1113 [ # # ]: 0 : ns = aa_lookupn_ns(policy_ns ? policy_ns : labels_ns(subj),
1114 : : ns_name, ns_len);
1115 [ # # ]: 0 : if (!ns) {
1116 : : info = "namespace does not exist";
1117 : : error = -ENOENT;
1118 : 0 : goto fail;
1119 : : }
1120 : : } else
1121 : : /* released below */
1122 [ # # ]: 0 : ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(subj));
1123 : :
1124 [ # # ]: 0 : if (!name) {
1125 : : /* remove namespace - can only happen if fqname[0] == ':' */
1126 : 0 : mutex_lock_nested(&ns->parent->lock, ns->level);
1127 : 0 : __aa_bump_ns_revision(ns);
1128 : 0 : __aa_remove_ns(ns);
1129 : 0 : mutex_unlock(&ns->parent->lock);
1130 : : } else {
1131 : : /* remove profile */
1132 : 0 : mutex_lock_nested(&ns->lock, ns->level);
1133 : 0 : profile = aa_get_profile(__lookup_profile(&ns->base, name));
1134 [ # # ]: 0 : if (!profile) {
1135 : : error = -ENOENT;
1136 : : info = "profile does not exist";
1137 : : goto fail_ns_lock;
1138 : : }
1139 : 0 : name = profile->base.hname;
1140 : 0 : __aa_bump_ns_revision(ns);
1141 : 0 : __remove_profile(profile);
1142 : 0 : __aa_labelset_update_subtree(ns);
1143 : 0 : mutex_unlock(&ns->lock);
1144 : : }
1145 : :
1146 : : /* don't fail removal if audit fails */
1147 : 0 : (void) audit_policy(subj, OP_PROF_RM, ns_name, name, info,
1148 : : error);
1149 : 0 : aa_put_ns(ns);
1150 : : aa_put_profile(profile);
1151 : 0 : return size;
1152 : :
1153 : : fail_ns_lock:
1154 : 0 : mutex_unlock(&ns->lock);
1155 : 0 : aa_put_ns(ns);
1156 : :
1157 : : fail:
1158 : 0 : (void) audit_policy(subj, OP_PROF_RM, ns_name, name, info,
1159 : : error);
1160 : 0 : return error;
1161 : : }
|