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 label definitions
6 : : *
7 : : * Copyright 2017 Canonical Ltd.
8 : : */
9 : :
10 : : #include <linux/audit.h>
11 : : #include <linux/seq_file.h>
12 : : #include <linux/sort.h>
13 : :
14 : : #include "include/apparmor.h"
15 : : #include "include/cred.h"
16 : : #include "include/label.h"
17 : : #include "include/policy.h"
18 : : #include "include/secid.h"
19 : :
20 : :
21 : : /*
22 : : * the aa_label represents the set of profiles confining an object
23 : : *
24 : : * Labels maintain a reference count to the set of pointers they reference
25 : : * Labels are ref counted by
26 : : * tasks and object via the security field/security context off the field
27 : : * code - will take a ref count on a label if it needs the label
28 : : * beyond what is possible with an rcu_read_lock.
29 : : * profiles - each profile is a label
30 : : * secids - a pinned secid will keep a refcount of the label it is
31 : : * referencing
32 : : * objects - inode, files, sockets, ...
33 : : *
34 : : * Labels are not ref counted by the label set, so they maybe removed and
35 : : * freed when no longer in use.
36 : : *
37 : : */
38 : :
39 : : #define PROXY_POISON 97
40 : : #define LABEL_POISON 100
41 : :
42 : 0 : static void free_proxy(struct aa_proxy *proxy)
43 : : {
44 : 0 : if (proxy) {
45 : : /* p->label will not updated any more as p is dead */
46 : 0 : aa_put_label(rcu_dereference_protected(proxy->label, true));
47 : 0 : memset(proxy, 0, sizeof(*proxy));
48 : : RCU_INIT_POINTER(proxy->label, (struct aa_label *)PROXY_POISON);
49 : 0 : kfree(proxy);
50 : : }
51 : 0 : }
52 : :
53 : 0 : void aa_proxy_kref(struct kref *kref)
54 : : {
55 : : struct aa_proxy *proxy = container_of(kref, struct aa_proxy, count);
56 : :
57 : 0 : free_proxy(proxy);
58 : 0 : }
59 : :
60 : 0 : struct aa_proxy *aa_alloc_proxy(struct aa_label *label, gfp_t gfp)
61 : : {
62 : : struct aa_proxy *new;
63 : :
64 : 0 : new = kzalloc(sizeof(struct aa_proxy), gfp);
65 : 0 : if (new) {
66 : : kref_init(&new->count);
67 : 0 : rcu_assign_pointer(new->label, aa_get_label(label));
68 : : }
69 : 0 : return new;
70 : : }
71 : :
72 : : /* requires profile list write lock held */
73 : 0 : void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new)
74 : : {
75 : : struct aa_label *tmp;
76 : :
77 : : AA_BUG(!orig);
78 : : AA_BUG(!new);
79 : : lockdep_assert_held_write(&labels_set(orig)->lock);
80 : :
81 : 0 : tmp = rcu_dereference_protected(orig->proxy->label,
82 : : &labels_ns(orig)->lock);
83 : 0 : rcu_assign_pointer(orig->proxy->label, aa_get_label(new));
84 : 0 : orig->flags |= FLAG_STALE;
85 : : aa_put_label(tmp);
86 : 0 : }
87 : :
88 : 0 : static void __proxy_share(struct aa_label *old, struct aa_label *new)
89 : : {
90 : 0 : struct aa_proxy *proxy = new->proxy;
91 : :
92 : 0 : new->proxy = aa_get_proxy(old->proxy);
93 : 0 : __aa_proxy_redirect(old, new);
94 : : aa_put_proxy(proxy);
95 : 0 : }
96 : :
97 : :
98 : : /**
99 : : * ns_cmp - compare ns for label set ordering
100 : : * @a: ns to compare (NOT NULL)
101 : : * @b: ns to compare (NOT NULL)
102 : : *
103 : : * Returns: <0 if a < b
104 : : * ==0 if a == b
105 : : * >0 if a > b
106 : : */
107 : 0 : static int ns_cmp(struct aa_ns *a, struct aa_ns *b)
108 : : {
109 : : int res;
110 : :
111 : : AA_BUG(!a);
112 : : AA_BUG(!b);
113 : : AA_BUG(!a->base.hname);
114 : : AA_BUG(!b->base.hname);
115 : :
116 : 0 : if (a == b)
117 : : return 0;
118 : :
119 : 0 : res = a->level - b->level;
120 : 0 : if (res)
121 : : return res;
122 : :
123 : 0 : return strcmp(a->base.hname, b->base.hname);
124 : : }
125 : :
126 : : /**
127 : : * profile_cmp - profile comparison for set ordering
128 : : * @a: profile to compare (NOT NULL)
129 : : * @b: profile to compare (NOT NULL)
130 : : *
131 : : * Returns: <0 if a < b
132 : : * ==0 if a == b
133 : : * >0 if a > b
134 : : */
135 : 0 : static int profile_cmp(struct aa_profile *a, struct aa_profile *b)
136 : : {
137 : : int res;
138 : :
139 : : AA_BUG(!a);
140 : : AA_BUG(!b);
141 : : AA_BUG(!a->ns);
142 : : AA_BUG(!b->ns);
143 : : AA_BUG(!a->base.hname);
144 : : AA_BUG(!b->base.hname);
145 : :
146 : 0 : if (a == b || a->base.hname == b->base.hname)
147 : : return 0;
148 : 0 : res = ns_cmp(a->ns, b->ns);
149 : 0 : if (res)
150 : : return res;
151 : :
152 : 0 : return strcmp(a->base.hname, b->base.hname);
153 : : }
154 : :
155 : : /**
156 : : * vec_cmp - label comparison for set ordering
157 : : * @a: label to compare (NOT NULL)
158 : : * @vec: vector of profiles to compare (NOT NULL)
159 : : * @n: length of @vec
160 : : *
161 : : * Returns: <0 if a < vec
162 : : * ==0 if a == vec
163 : : * >0 if a > vec
164 : : */
165 : 0 : static int vec_cmp(struct aa_profile **a, int an, struct aa_profile **b, int bn)
166 : : {
167 : : int i;
168 : :
169 : : AA_BUG(!a);
170 : : AA_BUG(!*a);
171 : : AA_BUG(!b);
172 : : AA_BUG(!*b);
173 : : AA_BUG(an <= 0);
174 : : AA_BUG(bn <= 0);
175 : :
176 : 0 : for (i = 0; i < an && i < bn; i++) {
177 : 0 : int res = profile_cmp(a[i], b[i]);
178 : :
179 : 0 : if (res != 0)
180 : 0 : return res;
181 : : }
182 : :
183 : 0 : return an - bn;
184 : : }
185 : :
186 : : static bool vec_is_stale(struct aa_profile **vec, int n)
187 : : {
188 : : int i;
189 : :
190 : : AA_BUG(!vec);
191 : :
192 : 0 : for (i = 0; i < n; i++) {
193 : 0 : if (profile_is_stale(vec[i]))
194 : : return true;
195 : : }
196 : :
197 : : return false;
198 : : }
199 : :
200 : : static bool vec_unconfined(struct aa_profile **vec, int n)
201 : : {
202 : : int i;
203 : :
204 : : AA_BUG(!vec);
205 : :
206 : 0 : for (i = 0; i < n; i++) {
207 : 0 : if (!profile_unconfined(vec[i]))
208 : : return false;
209 : : }
210 : :
211 : : return true;
212 : : }
213 : :
214 : 0 : static int sort_cmp(const void *a, const void *b)
215 : : {
216 : 0 : return profile_cmp(*(struct aa_profile **)a, *(struct aa_profile **)b);
217 : : }
218 : :
219 : : /*
220 : : * assumes vec is sorted
221 : : * Assumes @vec has null terminator at vec[n], and will null terminate
222 : : * vec[n - dups]
223 : : */
224 : 0 : static inline int unique(struct aa_profile **vec, int n)
225 : : {
226 : : int i, pos, dups = 0;
227 : :
228 : : AA_BUG(n < 1);
229 : : AA_BUG(!vec);
230 : :
231 : : pos = 0;
232 : 0 : for (i = 1; i < n; i++) {
233 : 0 : int res = profile_cmp(vec[pos], vec[i]);
234 : :
235 : : AA_BUG(res > 0, "vec not sorted");
236 : 0 : if (res == 0) {
237 : : /* drop duplicate */
238 : : aa_put_profile(vec[i]);
239 : 0 : dups++;
240 : 0 : continue;
241 : : }
242 : 0 : pos++;
243 : 0 : if (dups)
244 : 0 : vec[pos] = vec[i];
245 : : }
246 : :
247 : : AA_BUG(dups < 0);
248 : :
249 : 0 : return dups;
250 : : }
251 : :
252 : : /**
253 : : * aa_vec_unique - canonical sort and unique a list of profiles
254 : : * @n: number of refcounted profiles in the list (@n > 0)
255 : : * @vec: list of profiles to sort and merge
256 : : *
257 : : * Returns: the number of duplicates eliminated == references put
258 : : *
259 : : * If @flags & VEC_FLAG_TERMINATE @vec has null terminator at vec[n], and will
260 : : * null terminate vec[n - dups]
261 : : */
262 : 0 : int aa_vec_unique(struct aa_profile **vec, int n, int flags)
263 : : {
264 : : int i, dups = 0;
265 : :
266 : : AA_BUG(n < 1);
267 : : AA_BUG(!vec);
268 : :
269 : : /* vecs are usually small and inorder, have a fallback for larger */
270 : 0 : if (n > 8) {
271 : 0 : sort(vec, n, sizeof(struct aa_profile *), sort_cmp, NULL);
272 : 0 : dups = unique(vec, n);
273 : 0 : goto out;
274 : : }
275 : :
276 : : /* insertion sort + unique in one */
277 : 0 : for (i = 1; i < n; i++) {
278 : 0 : struct aa_profile *tmp = vec[i];
279 : : int pos, j;
280 : :
281 : 0 : for (pos = i - 1 - dups; pos >= 0; pos--) {
282 : 0 : int res = profile_cmp(vec[pos], tmp);
283 : :
284 : 0 : if (res == 0) {
285 : : /* drop duplicate entry */
286 : : aa_put_profile(tmp);
287 : 0 : dups++;
288 : 0 : goto continue_outer;
289 : 0 : } else if (res < 0)
290 : : break;
291 : : }
292 : : /* pos is at entry < tmp, or index -1. Set to insert pos */
293 : 0 : pos++;
294 : :
295 : 0 : for (j = i - dups; j > pos; j--)
296 : 0 : vec[j] = vec[j - 1];
297 : 0 : vec[pos] = tmp;
298 : : continue_outer:
299 : : ;
300 : : }
301 : :
302 : : AA_BUG(dups < 0);
303 : :
304 : : out:
305 : 0 : if (flags & VEC_FLAG_TERMINATE)
306 : 0 : vec[n - dups] = NULL;
307 : :
308 : 0 : return dups;
309 : : }
310 : :
311 : :
312 : 0 : static void label_destroy(struct aa_label *label)
313 : : {
314 : : struct aa_label *tmp;
315 : :
316 : : AA_BUG(!label);
317 : :
318 : 0 : if (!label_isprofile(label)) {
319 : : struct aa_profile *profile;
320 : : struct label_it i;
321 : :
322 : 0 : aa_put_str(label->hname);
323 : :
324 : 0 : label_for_each(i, label, profile) {
325 : : aa_put_profile(profile);
326 : 0 : label->vec[i.i] = (struct aa_profile *)
327 : 0 : (LABEL_POISON + (long) i.i);
328 : : }
329 : : }
330 : :
331 : 0 : if (rcu_dereference_protected(label->proxy->label, true) == label)
332 : : rcu_assign_pointer(label->proxy->label, NULL);
333 : :
334 : 0 : aa_free_secid(label->secid);
335 : :
336 : 0 : tmp = rcu_dereference_protected(label->proxy->label, true);
337 : 0 : if (tmp == label)
338 : : rcu_assign_pointer(label->proxy->label, NULL);
339 : :
340 : 0 : aa_put_proxy(label->proxy);
341 : 0 : label->proxy = (struct aa_proxy *) PROXY_POISON + 1;
342 : 0 : }
343 : :
344 : 0 : void aa_label_free(struct aa_label *label)
345 : : {
346 : 0 : if (!label)
347 : 0 : return;
348 : :
349 : 0 : label_destroy(label);
350 : 0 : kfree(label);
351 : : }
352 : :
353 : 0 : static void label_free_switch(struct aa_label *label)
354 : : {
355 : 0 : if (label->flags & FLAG_NS_COUNT)
356 : 0 : aa_free_ns(labels_ns(label));
357 : 0 : else if (label_isprofile(label))
358 : 0 : aa_free_profile(labels_profile(label));
359 : : else
360 : 0 : aa_label_free(label);
361 : 0 : }
362 : :
363 : 0 : static void label_free_rcu(struct rcu_head *head)
364 : : {
365 : 0 : struct aa_label *label = container_of(head, struct aa_label, rcu);
366 : :
367 : 0 : if (label->flags & FLAG_IN_TREE)
368 : 0 : (void) aa_label_remove(label);
369 : 0 : label_free_switch(label);
370 : 0 : }
371 : :
372 : 0 : void aa_label_kref(struct kref *kref)
373 : : {
374 : : struct aa_label *label = container_of(kref, struct aa_label, count);
375 : 0 : struct aa_ns *ns = labels_ns(label);
376 : :
377 : 0 : if (!ns) {
378 : : /* never live, no rcu callback needed, just using the fn */
379 : 0 : label_free_switch(label);
380 : 0 : return;
381 : : }
382 : : /* TODO: update labels_profile macro so it works here */
383 : : AA_BUG(label_isprofile(label) &&
384 : : on_list_rcu(&label->vec[0]->base.profiles));
385 : : AA_BUG(label_isprofile(label) &&
386 : : on_list_rcu(&label->vec[0]->base.list));
387 : :
388 : : /* TODO: if compound label and not stale add to reclaim cache */
389 : 0 : call_rcu(&label->rcu, label_free_rcu);
390 : : }
391 : :
392 : 0 : static void label_free_or_put_new(struct aa_label *label, struct aa_label *new)
393 : : {
394 : 0 : if (label != new)
395 : : /* need to free directly to break circular ref with proxy */
396 : 0 : aa_label_free(new);
397 : : else
398 : : aa_put_label(new);
399 : 0 : }
400 : :
401 : 0 : bool aa_label_init(struct aa_label *label, int size, gfp_t gfp)
402 : : {
403 : : AA_BUG(!label);
404 : : AA_BUG(size < 1);
405 : :
406 : 0 : if (aa_alloc_secid(label, gfp) < 0)
407 : : return false;
408 : :
409 : 0 : label->size = size; /* doesn't include null */
410 : 0 : label->vec[size] = NULL; /* null terminate */
411 : : kref_init(&label->count);
412 : 0 : RB_CLEAR_NODE(&label->node);
413 : :
414 : 0 : return true;
415 : : }
416 : :
417 : : /**
418 : : * aa_label_alloc - allocate a label with a profile vector of @size length
419 : : * @size: size of profile vector in the label
420 : : * @proxy: proxy to use OR null if to allocate a new one
421 : : * @gfp: memory allocation type
422 : : *
423 : : * Returns: new label
424 : : * else NULL if failed
425 : : */
426 : 0 : struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp)
427 : : {
428 : : struct aa_label *new;
429 : :
430 : : AA_BUG(size < 1);
431 : :
432 : : /* + 1 for null terminator entry on vec */
433 : 0 : new = kzalloc(sizeof(*new) + sizeof(struct aa_profile *) * (size + 1),
434 : : gfp);
435 : : AA_DEBUG("%s (%p)\n", __func__, new);
436 : 0 : if (!new)
437 : : goto fail;
438 : :
439 : 0 : if (!aa_label_init(new, size, gfp))
440 : : goto fail;
441 : :
442 : 0 : if (!proxy) {
443 : 0 : proxy = aa_alloc_proxy(new, gfp);
444 : 0 : if (!proxy)
445 : : goto fail;
446 : : } else
447 : : aa_get_proxy(proxy);
448 : : /* just set new's proxy, don't redirect proxy here if it was passed in*/
449 : 0 : new->proxy = proxy;
450 : :
451 : 0 : return new;
452 : :
453 : : fail:
454 : 0 : kfree(new);
455 : :
456 : 0 : return NULL;
457 : : }
458 : :
459 : :
460 : : /**
461 : : * label_cmp - label comparison for set ordering
462 : : * @a: label to compare (NOT NULL)
463 : : * @b: label to compare (NOT NULL)
464 : : *
465 : : * Returns: <0 if a < b
466 : : * ==0 if a == b
467 : : * >0 if a > b
468 : : */
469 : : static int label_cmp(struct aa_label *a, struct aa_label *b)
470 : : {
471 : : AA_BUG(!b);
472 : :
473 : 0 : if (a == b)
474 : : return 0;
475 : :
476 : 0 : return vec_cmp(a->vec, a->size, b->vec, b->size);
477 : : }
478 : :
479 : : /* helper fn for label_for_each_confined */
480 : 0 : int aa_label_next_confined(struct aa_label *label, int i)
481 : : {
482 : : AA_BUG(!label);
483 : : AA_BUG(i < 0);
484 : :
485 : 0 : for (; i < label->size; i++) {
486 : 0 : if (!profile_unconfined(label->vec[i]))
487 : : return i;
488 : : }
489 : :
490 : : return i;
491 : : }
492 : :
493 : : /**
494 : : * aa_label_next_not_in_set - return the next profile of @sub not in @set
495 : : * @I: label iterator
496 : : * @set: label to test against
497 : : * @sub: label to if is subset of @set
498 : : *
499 : : * Returns: profile in @sub that is not in @set, with iterator set pos after
500 : : * else NULL if @sub is a subset of @set
501 : : */
502 : 0 : struct aa_profile *__aa_label_next_not_in_set(struct label_it *I,
503 : : struct aa_label *set,
504 : : struct aa_label *sub)
505 : : {
506 : : AA_BUG(!set);
507 : : AA_BUG(!I);
508 : : AA_BUG(I->i < 0);
509 : : AA_BUG(I->i > set->size);
510 : : AA_BUG(!sub);
511 : : AA_BUG(I->j < 0);
512 : : AA_BUG(I->j > sub->size);
513 : :
514 : 0 : while (I->j < sub->size && I->i < set->size) {
515 : 0 : int res = profile_cmp(sub->vec[I->j], set->vec[I->i]);
516 : :
517 : 0 : if (res == 0) {
518 : 0 : (I->j)++;
519 : 0 : (I->i)++;
520 : 0 : } else if (res > 0)
521 : 0 : (I->i)++;
522 : : else
523 : 0 : return sub->vec[(I->j)++];
524 : : }
525 : :
526 : 0 : if (I->j < sub->size)
527 : 0 : return sub->vec[(I->j)++];
528 : :
529 : : return NULL;
530 : : }
531 : :
532 : : /**
533 : : * aa_label_is_subset - test if @sub is a subset of @set
534 : : * @set: label to test against
535 : : * @sub: label to test if is subset of @set
536 : : *
537 : : * Returns: true if @sub is subset of @set
538 : : * else false
539 : : */
540 : 0 : bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub)
541 : : {
542 : 0 : struct label_it i = { };
543 : :
544 : : AA_BUG(!set);
545 : : AA_BUG(!sub);
546 : :
547 : 0 : if (sub == set)
548 : : return true;
549 : :
550 : 0 : return __aa_label_next_not_in_set(&i, set, sub) == NULL;
551 : : }
552 : :
553 : : /**
554 : : * aa_label_is_unconfined_subset - test if @sub is a subset of @set
555 : : * @set: label to test against
556 : : * @sub: label to test if is subset of @set
557 : : *
558 : : * This checks for subset but taking into account unconfined. IF
559 : : * @sub contains an unconfined profile that does not have a matching
560 : : * unconfined in @set then this will not cause the test to fail.
561 : : * Conversely we don't care about an unconfined in @set that is not in
562 : : * @sub
563 : : *
564 : : * Returns: true if @sub is special_subset of @set
565 : : * else false
566 : : */
567 : 0 : bool aa_label_is_unconfined_subset(struct aa_label *set, struct aa_label *sub)
568 : : {
569 : 0 : struct label_it i = { };
570 : : struct aa_profile *p;
571 : :
572 : : AA_BUG(!set);
573 : : AA_BUG(!sub);
574 : :
575 : 0 : if (sub == set)
576 : : return true;
577 : :
578 : : do {
579 : 0 : p = __aa_label_next_not_in_set(&i, set, sub);
580 : 0 : if (p && !profile_unconfined(p))
581 : : break;
582 : 0 : } while (p);
583 : :
584 : 0 : return p == NULL;
585 : : }
586 : :
587 : :
588 : : /**
589 : : * __label_remove - remove @label from the label set
590 : : * @l: label to remove
591 : : * @new: label to redirect to
592 : : *
593 : : * Requires: labels_set(@label)->lock write_lock
594 : : * Returns: true if the label was in the tree and removed
595 : : */
596 : 0 : static bool __label_remove(struct aa_label *label, struct aa_label *new)
597 : : {
598 : 0 : struct aa_labelset *ls = labels_set(label);
599 : :
600 : : AA_BUG(!ls);
601 : : AA_BUG(!label);
602 : : lockdep_assert_held_write(&ls->lock);
603 : :
604 : 0 : if (new)
605 : 0 : __aa_proxy_redirect(label, new);
606 : :
607 : 0 : if (!label_is_stale(label))
608 : 0 : __label_make_stale(label);
609 : :
610 : 0 : if (label->flags & FLAG_IN_TREE) {
611 : 0 : rb_erase(&label->node, &ls->root);
612 : 0 : label->flags &= ~FLAG_IN_TREE;
613 : 0 : return true;
614 : : }
615 : :
616 : : return false;
617 : : }
618 : :
619 : : /**
620 : : * __label_replace - replace @old with @new in label set
621 : : * @old: label to remove from label set
622 : : * @new: label to replace @old with
623 : : *
624 : : * Requires: labels_set(@old)->lock write_lock
625 : : * valid ref count be held on @new
626 : : * Returns: true if @old was in set and replaced by @new
627 : : *
628 : : * Note: current implementation requires label set be order in such a way
629 : : * that @new directly replaces @old position in the set (ie.
630 : : * using pointer comparison of the label address would not work)
631 : : */
632 : 0 : static bool __label_replace(struct aa_label *old, struct aa_label *new)
633 : : {
634 : 0 : struct aa_labelset *ls = labels_set(old);
635 : :
636 : : AA_BUG(!ls);
637 : : AA_BUG(!old);
638 : : AA_BUG(!new);
639 : : lockdep_assert_held_write(&ls->lock);
640 : : AA_BUG(new->flags & FLAG_IN_TREE);
641 : :
642 : 0 : if (!label_is_stale(old))
643 : 0 : __label_make_stale(old);
644 : :
645 : 0 : if (old->flags & FLAG_IN_TREE) {
646 : 0 : rb_replace_node(&old->node, &new->node, &ls->root);
647 : 0 : old->flags &= ~FLAG_IN_TREE;
648 : 0 : new->flags |= FLAG_IN_TREE;
649 : 0 : return true;
650 : : }
651 : :
652 : : return false;
653 : : }
654 : :
655 : : /**
656 : : * __label_insert - attempt to insert @l into a label set
657 : : * @ls: set of labels to insert @l into (NOT NULL)
658 : : * @label: new label to insert (NOT NULL)
659 : : * @replace: whether insertion should replace existing entry that is not stale
660 : : *
661 : : * Requires: @ls->lock
662 : : * caller to hold a valid ref on l
663 : : * if @replace is true l has a preallocated proxy associated
664 : : * Returns: @l if successful in inserting @l - with additional refcount
665 : : * else ref counted equivalent label that is already in the set,
666 : : * the else condition only happens if @replace is false
667 : : */
668 : 0 : static struct aa_label *__label_insert(struct aa_labelset *ls,
669 : : struct aa_label *label, bool replace)
670 : : {
671 : : struct rb_node **new, *parent = NULL;
672 : :
673 : : AA_BUG(!ls);
674 : : AA_BUG(!label);
675 : : AA_BUG(labels_set(label) != ls);
676 : : lockdep_assert_held_write(&ls->lock);
677 : : AA_BUG(label->flags & FLAG_IN_TREE);
678 : :
679 : : /* Figure out where to put new node */
680 : 0 : new = &ls->root.rb_node;
681 : 0 : while (*new) {
682 : 0 : struct aa_label *this = rb_entry(*new, struct aa_label, node);
683 : : int result = label_cmp(label, this);
684 : :
685 : : parent = *new;
686 : 0 : if (result == 0) {
687 : : /* !__aa_get_label means queued for destruction,
688 : : * so replace in place, however the label has
689 : : * died before the replacement so do not share
690 : : * the proxy
691 : : */
692 : 0 : if (!replace && !label_is_stale(this)) {
693 : 0 : if (__aa_get_label(this))
694 : 0 : return this;
695 : : } else
696 : 0 : __proxy_share(this, label);
697 : : AA_BUG(!__label_replace(this, label));
698 : 0 : return aa_get_label(label);
699 : 0 : } else if (result < 0)
700 : 0 : new = &((*new)->rb_left);
701 : : else /* (result > 0) */
702 : 0 : new = &((*new)->rb_right);
703 : : }
704 : :
705 : : /* Add new node and rebalance tree. */
706 : 0 : rb_link_node(&label->node, parent, new);
707 : 0 : rb_insert_color(&label->node, &ls->root);
708 : 0 : label->flags |= FLAG_IN_TREE;
709 : :
710 : 0 : return aa_get_label(label);
711 : : }
712 : :
713 : : /**
714 : : * __vec_find - find label that matches @vec in label set
715 : : * @vec: vec of profiles to find matching label for (NOT NULL)
716 : : * @n: length of @vec
717 : : *
718 : : * Requires: @vec_labelset(vec) lock held
719 : : * caller to hold a valid ref on l
720 : : *
721 : : * Returns: ref counted @label if matching label is in tree
722 : : * ref counted label that is equiv to @l in tree
723 : : * else NULL if @vec equiv is not in tree
724 : : */
725 : 0 : static struct aa_label *__vec_find(struct aa_profile **vec, int n)
726 : : {
727 : : struct rb_node *node;
728 : :
729 : : AA_BUG(!vec);
730 : : AA_BUG(!*vec);
731 : : AA_BUG(n <= 0);
732 : :
733 : 0 : node = vec_labelset(vec, n)->root.rb_node;
734 : 0 : while (node) {
735 : 0 : struct aa_label *this = rb_entry(node, struct aa_label, node);
736 : 0 : int result = vec_cmp(this->vec, this->size, vec, n);
737 : :
738 : 0 : if (result > 0)
739 : 0 : node = node->rb_left;
740 : 0 : else if (result < 0)
741 : 0 : node = node->rb_right;
742 : : else
743 : 0 : return __aa_get_label(this);
744 : : }
745 : :
746 : : return NULL;
747 : : }
748 : :
749 : : /**
750 : : * __label_find - find label @label in label set
751 : : * @label: label to find (NOT NULL)
752 : : *
753 : : * Requires: labels_set(@label)->lock held
754 : : * caller to hold a valid ref on l
755 : : *
756 : : * Returns: ref counted @label if @label is in tree OR
757 : : * ref counted label that is equiv to @label in tree
758 : : * else NULL if @label or equiv is not in tree
759 : : */
760 : : static struct aa_label *__label_find(struct aa_label *label)
761 : : {
762 : : AA_BUG(!label);
763 : :
764 : 0 : return __vec_find(label->vec, label->size);
765 : : }
766 : :
767 : :
768 : : /**
769 : : * aa_label_remove - remove a label from the labelset
770 : : * @label: label to remove
771 : : *
772 : : * Returns: true if @label was removed from the tree
773 : : * else @label was not in tree so it could not be removed
774 : : */
775 : 0 : bool aa_label_remove(struct aa_label *label)
776 : : {
777 : 0 : struct aa_labelset *ls = labels_set(label);
778 : : unsigned long flags;
779 : : bool res;
780 : :
781 : : AA_BUG(!ls);
782 : :
783 : 0 : write_lock_irqsave(&ls->lock, flags);
784 : 0 : res = __label_remove(label, ns_unconfined(labels_ns(label)));
785 : 0 : write_unlock_irqrestore(&ls->lock, flags);
786 : :
787 : 0 : return res;
788 : : }
789 : :
790 : : /**
791 : : * aa_label_replace - replace a label @old with a new version @new
792 : : * @old: label to replace
793 : : * @new: label replacing @old
794 : : *
795 : : * Returns: true if @old was in tree and replaced
796 : : * else @old was not in tree, and @new was not inserted
797 : : */
798 : 0 : bool aa_label_replace(struct aa_label *old, struct aa_label *new)
799 : : {
800 : : unsigned long flags;
801 : : bool res;
802 : :
803 : 0 : if (name_is_shared(old, new) && labels_ns(old) == labels_ns(new)) {
804 : 0 : write_lock_irqsave(&labels_set(old)->lock, flags);
805 : 0 : if (old->proxy != new->proxy)
806 : 0 : __proxy_share(old, new);
807 : : else
808 : 0 : __aa_proxy_redirect(old, new);
809 : 0 : res = __label_replace(old, new);
810 : 0 : write_unlock_irqrestore(&labels_set(old)->lock, flags);
811 : : } else {
812 : : struct aa_label *l;
813 : 0 : struct aa_labelset *ls = labels_set(old);
814 : :
815 : 0 : write_lock_irqsave(&ls->lock, flags);
816 : 0 : res = __label_remove(old, new);
817 : 0 : if (labels_ns(old) != labels_ns(new)) {
818 : 0 : write_unlock_irqrestore(&ls->lock, flags);
819 : 0 : ls = labels_set(new);
820 : 0 : write_lock_irqsave(&ls->lock, flags);
821 : : }
822 : 0 : l = __label_insert(ls, new, true);
823 : 0 : res = (l == new);
824 : 0 : write_unlock_irqrestore(&ls->lock, flags);
825 : : aa_put_label(l);
826 : : }
827 : :
828 : 0 : return res;
829 : : }
830 : :
831 : : /**
832 : : * vec_find - find label @l in label set
833 : : * @vec: array of profiles to find equiv label for (NOT NULL)
834 : : * @n: length of @vec
835 : : *
836 : : * Returns: refcounted label if @vec equiv is in tree
837 : : * else NULL if @vec equiv is not in tree
838 : : */
839 : 0 : static struct aa_label *vec_find(struct aa_profile **vec, int n)
840 : : {
841 : : struct aa_labelset *ls;
842 : : struct aa_label *label;
843 : : unsigned long flags;
844 : :
845 : : AA_BUG(!vec);
846 : : AA_BUG(!*vec);
847 : : AA_BUG(n <= 0);
848 : :
849 : 0 : ls = vec_labelset(vec, n);
850 : 0 : read_lock_irqsave(&ls->lock, flags);
851 : 0 : label = __vec_find(vec, n);
852 : 0 : read_unlock_irqrestore(&ls->lock, flags);
853 : :
854 : 0 : return label;
855 : : }
856 : :
857 : : /* requires sort and merge done first */
858 : 0 : static struct aa_label *vec_create_and_insert_label(struct aa_profile **vec,
859 : : int len, gfp_t gfp)
860 : : {
861 : : struct aa_label *label = NULL;
862 : : struct aa_labelset *ls;
863 : : unsigned long flags;
864 : : struct aa_label *new;
865 : : int i;
866 : :
867 : : AA_BUG(!vec);
868 : :
869 : 0 : if (len == 1)
870 : 0 : return aa_get_label(&vec[0]->label);
871 : :
872 : 0 : ls = labels_set(&vec[len - 1]->label);
873 : :
874 : : /* TODO: enable when read side is lockless
875 : : * check if label exists before taking locks
876 : : */
877 : 0 : new = aa_label_alloc(len, NULL, gfp);
878 : 0 : if (!new)
879 : : return NULL;
880 : :
881 : 0 : for (i = 0; i < len; i++)
882 : 0 : new->vec[i] = aa_get_profile(vec[i]);
883 : :
884 : 0 : write_lock_irqsave(&ls->lock, flags);
885 : 0 : label = __label_insert(ls, new, false);
886 : 0 : write_unlock_irqrestore(&ls->lock, flags);
887 : 0 : label_free_or_put_new(label, new);
888 : :
889 : 0 : return label;
890 : : }
891 : :
892 : 0 : struct aa_label *aa_vec_find_or_create_label(struct aa_profile **vec, int len,
893 : : gfp_t gfp)
894 : : {
895 : 0 : struct aa_label *label = vec_find(vec, len);
896 : :
897 : 0 : if (label)
898 : : return label;
899 : :
900 : 0 : return vec_create_and_insert_label(vec, len, gfp);
901 : : }
902 : :
903 : : /**
904 : : * aa_label_find - find label @label in label set
905 : : * @label: label to find (NOT NULL)
906 : : *
907 : : * Requires: caller to hold a valid ref on l
908 : : *
909 : : * Returns: refcounted @label if @label is in tree
910 : : * refcounted label that is equiv to @label in tree
911 : : * else NULL if @label or equiv is not in tree
912 : : */
913 : 0 : struct aa_label *aa_label_find(struct aa_label *label)
914 : : {
915 : : AA_BUG(!label);
916 : :
917 : 0 : return vec_find(label->vec, label->size);
918 : : }
919 : :
920 : :
921 : : /**
922 : : * aa_label_insert - insert label @label into @ls or return existing label
923 : : * @ls - labelset to insert @label into
924 : : * @label - label to insert
925 : : *
926 : : * Requires: caller to hold a valid ref on @label
927 : : *
928 : : * Returns: ref counted @label if successful in inserting @label
929 : : * else ref counted equivalent label that is already in the set
930 : : */
931 : 0 : struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *label)
932 : : {
933 : : struct aa_label *l;
934 : : unsigned long flags;
935 : :
936 : : AA_BUG(!ls);
937 : : AA_BUG(!label);
938 : :
939 : : /* check if label exists before taking lock */
940 : 0 : if (!label_is_stale(label)) {
941 : 0 : read_lock_irqsave(&ls->lock, flags);
942 : : l = __label_find(label);
943 : 0 : read_unlock_irqrestore(&ls->lock, flags);
944 : 0 : if (l)
945 : : return l;
946 : : }
947 : :
948 : 0 : write_lock_irqsave(&ls->lock, flags);
949 : 0 : l = __label_insert(ls, label, false);
950 : 0 : write_unlock_irqrestore(&ls->lock, flags);
951 : :
952 : 0 : return l;
953 : : }
954 : :
955 : :
956 : : /**
957 : : * aa_label_next_in_merge - find the next profile when merging @a and @b
958 : : * @I: label iterator
959 : : * @a: label to merge
960 : : * @b: label to merge
961 : : *
962 : : * Returns: next profile
963 : : * else null if no more profiles
964 : : */
965 : 0 : struct aa_profile *aa_label_next_in_merge(struct label_it *I,
966 : : struct aa_label *a,
967 : : struct aa_label *b)
968 : : {
969 : : AA_BUG(!a);
970 : : AA_BUG(!b);
971 : : AA_BUG(!I);
972 : : AA_BUG(I->i < 0);
973 : : AA_BUG(I->i > a->size);
974 : : AA_BUG(I->j < 0);
975 : : AA_BUG(I->j > b->size);
976 : :
977 : 0 : if (I->i < a->size) {
978 : 0 : if (I->j < b->size) {
979 : 0 : int res = profile_cmp(a->vec[I->i], b->vec[I->j]);
980 : :
981 : 0 : if (res > 0)
982 : 0 : return b->vec[(I->j)++];
983 : 0 : if (res == 0)
984 : 0 : (I->j)++;
985 : : }
986 : :
987 : 0 : return a->vec[(I->i)++];
988 : : }
989 : :
990 : 0 : if (I->j < b->size)
991 : 0 : return b->vec[(I->j)++];
992 : :
993 : : return NULL;
994 : : }
995 : :
996 : : /**
997 : : * label_merge_cmp - cmp of @a merging with @b against @z for set ordering
998 : : * @a: label to merge then compare (NOT NULL)
999 : : * @b: label to merge then compare (NOT NULL)
1000 : : * @z: label to compare merge against (NOT NULL)
1001 : : *
1002 : : * Assumes: using the most recent versions of @a, @b, and @z
1003 : : *
1004 : : * Returns: <0 if a < b
1005 : : * ==0 if a == b
1006 : : * >0 if a > b
1007 : : */
1008 : 0 : static int label_merge_cmp(struct aa_label *a, struct aa_label *b,
1009 : : struct aa_label *z)
1010 : : {
1011 : : struct aa_profile *p = NULL;
1012 : 0 : struct label_it i = { };
1013 : : int k;
1014 : :
1015 : : AA_BUG(!a);
1016 : : AA_BUG(!b);
1017 : : AA_BUG(!z);
1018 : :
1019 : 0 : for (k = 0;
1020 : 0 : k < z->size && (p = aa_label_next_in_merge(&i, a, b));
1021 : 0 : k++) {
1022 : 0 : int res = profile_cmp(p, z->vec[k]);
1023 : :
1024 : 0 : if (res != 0)
1025 : 0 : return res;
1026 : : }
1027 : :
1028 : 0 : if (p)
1029 : : return 1;
1030 : 0 : else if (k < z->size)
1031 : : return -1;
1032 : 0 : return 0;
1033 : : }
1034 : :
1035 : : /**
1036 : : * label_merge_insert - create a new label by merging @a and @b
1037 : : * @new: preallocated label to merge into (NOT NULL)
1038 : : * @a: label to merge with @b (NOT NULL)
1039 : : * @b: label to merge with @a (NOT NULL)
1040 : : *
1041 : : * Requires: preallocated proxy
1042 : : *
1043 : : * Returns: ref counted label either @new if merge is unique
1044 : : * @a if @b is a subset of @a
1045 : : * @b if @a is a subset of @b
1046 : : *
1047 : : * NOTE: will not use @new if the merge results in @new == @a or @b
1048 : : *
1049 : : * Must be used within labelset write lock to avoid racing with
1050 : : * setting labels stale.
1051 : : */
1052 : 0 : static struct aa_label *label_merge_insert(struct aa_label *new,
1053 : : struct aa_label *a,
1054 : : struct aa_label *b)
1055 : : {
1056 : : struct aa_label *label;
1057 : : struct aa_labelset *ls;
1058 : : struct aa_profile *next;
1059 : : struct label_it i;
1060 : : unsigned long flags;
1061 : : int k = 0, invcount = 0;
1062 : : bool stale = false;
1063 : :
1064 : : AA_BUG(!a);
1065 : : AA_BUG(a->size < 0);
1066 : : AA_BUG(!b);
1067 : : AA_BUG(b->size < 0);
1068 : : AA_BUG(!new);
1069 : : AA_BUG(new->size < a->size + b->size);
1070 : :
1071 : 0 : label_for_each_in_merge(i, a, b, next) {
1072 : : AA_BUG(!next);
1073 : 0 : if (profile_is_stale(next)) {
1074 : 0 : new->vec[k] = aa_get_newest_profile(next);
1075 : : AA_BUG(!new->vec[k]->label.proxy);
1076 : : AA_BUG(!new->vec[k]->label.proxy->label);
1077 : 0 : if (next->label.proxy != new->vec[k]->label.proxy)
1078 : 0 : invcount++;
1079 : 0 : k++;
1080 : : stale = true;
1081 : : } else
1082 : 0 : new->vec[k++] = aa_get_profile(next);
1083 : : }
1084 : : /* set to actual size which is <= allocated len */
1085 : 0 : new->size = k;
1086 : 0 : new->vec[k] = NULL;
1087 : :
1088 : 0 : if (invcount) {
1089 : 0 : new->size -= aa_vec_unique(&new->vec[0], new->size,
1090 : : VEC_FLAG_TERMINATE);
1091 : : /* TODO: deal with reference labels */
1092 : 0 : if (new->size == 1) {
1093 : 0 : label = aa_get_label(&new->vec[0]->label);
1094 : 0 : return label;
1095 : : }
1096 : 0 : } else if (!stale) {
1097 : : /*
1098 : : * merge could be same as a || b, note: it is not possible
1099 : : * for new->size == a->size == b->size unless a == b
1100 : : */
1101 : 0 : if (k == a->size)
1102 : 0 : return aa_get_label(a);
1103 : 0 : else if (k == b->size)
1104 : 0 : return aa_get_label(b);
1105 : : }
1106 : 0 : if (vec_unconfined(new->vec, new->size))
1107 : 0 : new->flags |= FLAG_UNCONFINED;
1108 : 0 : ls = labels_set(new);
1109 : 0 : write_lock_irqsave(&ls->lock, flags);
1110 : 0 : label = __label_insert(labels_set(new), new, false);
1111 : 0 : write_unlock_irqrestore(&ls->lock, flags);
1112 : :
1113 : 0 : return label;
1114 : : }
1115 : :
1116 : : /**
1117 : : * labelset_of_merge - find which labelset a merged label should be inserted
1118 : : * @a: label to merge and insert
1119 : : * @b: label to merge and insert
1120 : : *
1121 : : * Returns: labelset that the merged label should be inserted into
1122 : : */
1123 : 0 : static struct aa_labelset *labelset_of_merge(struct aa_label *a,
1124 : : struct aa_label *b)
1125 : : {
1126 : 0 : struct aa_ns *nsa = labels_ns(a);
1127 : 0 : struct aa_ns *nsb = labels_ns(b);
1128 : :
1129 : 0 : if (ns_cmp(nsa, nsb) <= 0)
1130 : 0 : return &nsa->labels;
1131 : 0 : return &nsb->labels;
1132 : : }
1133 : :
1134 : : /**
1135 : : * __label_find_merge - find label that is equiv to merge of @a and @b
1136 : : * @ls: set of labels to search (NOT NULL)
1137 : : * @a: label to merge with @b (NOT NULL)
1138 : : * @b: label to merge with @a (NOT NULL)
1139 : : *
1140 : : * Requires: ls->lock read_lock held
1141 : : *
1142 : : * Returns: ref counted label that is equiv to merge of @a and @b
1143 : : * else NULL if merge of @a and @b is not in set
1144 : : */
1145 : 0 : static struct aa_label *__label_find_merge(struct aa_labelset *ls,
1146 : : struct aa_label *a,
1147 : : struct aa_label *b)
1148 : : {
1149 : : struct rb_node *node;
1150 : :
1151 : : AA_BUG(!ls);
1152 : : AA_BUG(!a);
1153 : : AA_BUG(!b);
1154 : :
1155 : 0 : if (a == b)
1156 : 0 : return __label_find(a);
1157 : :
1158 : 0 : node = ls->root.rb_node;
1159 : 0 : while (node) {
1160 : 0 : struct aa_label *this = container_of(node, struct aa_label,
1161 : : node);
1162 : 0 : int result = label_merge_cmp(a, b, this);
1163 : :
1164 : 0 : if (result < 0)
1165 : 0 : node = node->rb_left;
1166 : 0 : else if (result > 0)
1167 : 0 : node = node->rb_right;
1168 : : else
1169 : 0 : return __aa_get_label(this);
1170 : : }
1171 : :
1172 : : return NULL;
1173 : : }
1174 : :
1175 : :
1176 : : /**
1177 : : * aa_label_find_merge - find label that is equiv to merge of @a and @b
1178 : : * @a: label to merge with @b (NOT NULL)
1179 : : * @b: label to merge with @a (NOT NULL)
1180 : : *
1181 : : * Requires: labels be fully constructed with a valid ns
1182 : : *
1183 : : * Returns: ref counted label that is equiv to merge of @a and @b
1184 : : * else NULL if merge of @a and @b is not in set
1185 : : */
1186 : 0 : struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b)
1187 : : {
1188 : : struct aa_labelset *ls;
1189 : : struct aa_label *label, *ar = NULL, *br = NULL;
1190 : : unsigned long flags;
1191 : :
1192 : : AA_BUG(!a);
1193 : : AA_BUG(!b);
1194 : :
1195 : 0 : if (label_is_stale(a))
1196 : 0 : a = ar = aa_get_newest_label(a);
1197 : 0 : if (label_is_stale(b))
1198 : 0 : b = br = aa_get_newest_label(b);
1199 : 0 : ls = labelset_of_merge(a, b);
1200 : 0 : read_lock_irqsave(&ls->lock, flags);
1201 : 0 : label = __label_find_merge(ls, a, b);
1202 : 0 : read_unlock_irqrestore(&ls->lock, flags);
1203 : : aa_put_label(ar);
1204 : : aa_put_label(br);
1205 : :
1206 : 0 : return label;
1207 : : }
1208 : :
1209 : : /**
1210 : : * aa_label_merge - attempt to insert new merged label of @a and @b
1211 : : * @ls: set of labels to insert label into (NOT NULL)
1212 : : * @a: label to merge with @b (NOT NULL)
1213 : : * @b: label to merge with @a (NOT NULL)
1214 : : * @gfp: memory allocation type
1215 : : *
1216 : : * Requires: caller to hold valid refs on @a and @b
1217 : : * labels be fully constructed with a valid ns
1218 : : *
1219 : : * Returns: ref counted new label if successful in inserting merge of a & b
1220 : : * else ref counted equivalent label that is already in the set.
1221 : : * else NULL if could not create label (-ENOMEM)
1222 : : */
1223 : 0 : struct aa_label *aa_label_merge(struct aa_label *a, struct aa_label *b,
1224 : : gfp_t gfp)
1225 : : {
1226 : : struct aa_label *label = NULL;
1227 : :
1228 : : AA_BUG(!a);
1229 : : AA_BUG(!b);
1230 : :
1231 : 0 : if (a == b)
1232 : 0 : return aa_get_newest_label(a);
1233 : :
1234 : : /* TODO: enable when read side is lockless
1235 : : * check if label exists before taking locks
1236 : : if (!label_is_stale(a) && !label_is_stale(b))
1237 : : label = aa_label_find_merge(a, b);
1238 : : */
1239 : :
1240 : : if (!label) {
1241 : : struct aa_label *new;
1242 : :
1243 : 0 : a = aa_get_newest_label(a);
1244 : 0 : b = aa_get_newest_label(b);
1245 : :
1246 : : /* could use label_merge_len(a, b), but requires double
1247 : : * comparison for small savings
1248 : : */
1249 : 0 : new = aa_label_alloc(a->size + b->size, NULL, gfp);
1250 : 0 : if (!new)
1251 : : goto out;
1252 : :
1253 : 0 : label = label_merge_insert(new, a, b);
1254 : 0 : label_free_or_put_new(label, new);
1255 : : out:
1256 : : aa_put_label(a);
1257 : : aa_put_label(b);
1258 : : }
1259 : :
1260 : 0 : return label;
1261 : : }
1262 : :
1263 : : static inline bool label_is_visible(struct aa_profile *profile,
1264 : : struct aa_label *label)
1265 : : {
1266 : : return aa_ns_visible(profile->ns, labels_ns(label), true);
1267 : : }
1268 : :
1269 : : /* match a profile and its associated ns component if needed
1270 : : * Assumes visibility test has already been done.
1271 : : * If a subns profile is not to be matched should be prescreened with
1272 : : * visibility test.
1273 : : */
1274 : 0 : static inline unsigned int match_component(struct aa_profile *profile,
1275 : : struct aa_profile *tp,
1276 : : unsigned int state)
1277 : : {
1278 : : const char *ns_name;
1279 : :
1280 : 0 : if (profile->ns == tp->ns)
1281 : 0 : return aa_dfa_match(profile->policy.dfa, state, tp->base.hname);
1282 : :
1283 : : /* try matching with namespace name and then profile */
1284 : 0 : ns_name = aa_ns_name(profile->ns, tp->ns, true);
1285 : 0 : state = aa_dfa_match_len(profile->policy.dfa, state, ":", 1);
1286 : 0 : state = aa_dfa_match(profile->policy.dfa, state, ns_name);
1287 : 0 : state = aa_dfa_match_len(profile->policy.dfa, state, ":", 1);
1288 : 0 : return aa_dfa_match(profile->policy.dfa, state, tp->base.hname);
1289 : : }
1290 : :
1291 : : /**
1292 : : * label_compound_match - find perms for full compound label
1293 : : * @profile: profile to find perms for
1294 : : * @label: label to check access permissions for
1295 : : * @start: state to start match in
1296 : : * @subns: whether to do permission checks on components in a subns
1297 : : * @request: permissions to request
1298 : : * @perms: perms struct to set
1299 : : *
1300 : : * Returns: 0 on success else ERROR
1301 : : *
1302 : : * For the label A//&B//&C this does the perm match for A//&B//&C
1303 : : * @perms should be preinitialized with allperms OR a previous permission
1304 : : * check to be stacked.
1305 : : */
1306 : 0 : static int label_compound_match(struct aa_profile *profile,
1307 : : struct aa_label *label,
1308 : : unsigned int state, bool subns, u32 request,
1309 : : struct aa_perms *perms)
1310 : : {
1311 : : struct aa_profile *tp;
1312 : : struct label_it i;
1313 : :
1314 : : /* find first subcomponent that is visible */
1315 : 0 : label_for_each(i, label, tp) {
1316 : 0 : if (!aa_ns_visible(profile->ns, tp->ns, subns))
1317 : 0 : continue;
1318 : 0 : state = match_component(profile, tp, state);
1319 : 0 : if (!state)
1320 : : goto fail;
1321 : : goto next;
1322 : : }
1323 : :
1324 : : /* no component visible */
1325 : 0 : *perms = allperms;
1326 : 0 : return 0;
1327 : :
1328 : : next:
1329 : 0 : label_for_each_cont(i, label, tp) {
1330 : 0 : if (!aa_ns_visible(profile->ns, tp->ns, subns))
1331 : 0 : continue;
1332 : 0 : state = aa_dfa_match(profile->policy.dfa, state, "//&");
1333 : 0 : state = match_component(profile, tp, state);
1334 : 0 : if (!state)
1335 : : goto fail;
1336 : : }
1337 : 0 : aa_compute_perms(profile->policy.dfa, state, perms);
1338 : 0 : aa_apply_modes_to_perms(profile, perms);
1339 : 0 : if ((perms->allow & request) != request)
1340 : : return -EACCES;
1341 : :
1342 : 0 : return 0;
1343 : :
1344 : : fail:
1345 : 0 : *perms = nullperms;
1346 : 0 : return state;
1347 : : }
1348 : :
1349 : : /**
1350 : : * label_components_match - find perms for all subcomponents of a label
1351 : : * @profile: profile to find perms for
1352 : : * @label: label to check access permissions for
1353 : : * @start: state to start match in
1354 : : * @subns: whether to do permission checks on components in a subns
1355 : : * @request: permissions to request
1356 : : * @perms: an initialized perms struct to add accumulation to
1357 : : *
1358 : : * Returns: 0 on success else ERROR
1359 : : *
1360 : : * For the label A//&B//&C this does the perm match for each of A and B and C
1361 : : * @perms should be preinitialized with allperms OR a previous permission
1362 : : * check to be stacked.
1363 : : */
1364 : 0 : static int label_components_match(struct aa_profile *profile,
1365 : : struct aa_label *label, unsigned int start,
1366 : : bool subns, u32 request,
1367 : : struct aa_perms *perms)
1368 : : {
1369 : : struct aa_profile *tp;
1370 : : struct label_it i;
1371 : : struct aa_perms tmp;
1372 : : unsigned int state = 0;
1373 : :
1374 : : /* find first subcomponent to test */
1375 : 0 : label_for_each(i, label, tp) {
1376 : 0 : if (!aa_ns_visible(profile->ns, tp->ns, subns))
1377 : 0 : continue;
1378 : 0 : state = match_component(profile, tp, start);
1379 : 0 : if (!state)
1380 : : goto fail;
1381 : : goto next;
1382 : : }
1383 : :
1384 : : /* no subcomponents visible - no change in perms */
1385 : : return 0;
1386 : :
1387 : : next:
1388 : 0 : aa_compute_perms(profile->policy.dfa, state, &tmp);
1389 : 0 : aa_apply_modes_to_perms(profile, &tmp);
1390 : 0 : aa_perms_accum(perms, &tmp);
1391 : 0 : label_for_each_cont(i, label, tp) {
1392 : 0 : if (!aa_ns_visible(profile->ns, tp->ns, subns))
1393 : 0 : continue;
1394 : 0 : state = match_component(profile, tp, start);
1395 : 0 : if (!state)
1396 : : goto fail;
1397 : 0 : aa_compute_perms(profile->policy.dfa, state, &tmp);
1398 : 0 : aa_apply_modes_to_perms(profile, &tmp);
1399 : 0 : aa_perms_accum(perms, &tmp);
1400 : : }
1401 : :
1402 : 0 : if ((perms->allow & request) != request)
1403 : : return -EACCES;
1404 : :
1405 : 0 : return 0;
1406 : :
1407 : : fail:
1408 : 0 : *perms = nullperms;
1409 : 0 : return -EACCES;
1410 : : }
1411 : :
1412 : : /**
1413 : : * aa_label_match - do a multi-component label match
1414 : : * @profile: profile to match against (NOT NULL)
1415 : : * @label: label to match (NOT NULL)
1416 : : * @state: state to start in
1417 : : * @subns: whether to match subns components
1418 : : * @request: permission request
1419 : : * @perms: Returns computed perms (NOT NULL)
1420 : : *
1421 : : * Returns: the state the match finished in, may be the none matching state
1422 : : */
1423 : 0 : int aa_label_match(struct aa_profile *profile, struct aa_label *label,
1424 : : unsigned int state, bool subns, u32 request,
1425 : : struct aa_perms *perms)
1426 : : {
1427 : 0 : int error = label_compound_match(profile, label, state, subns, request,
1428 : : perms);
1429 : 0 : if (!error)
1430 : : return error;
1431 : :
1432 : 0 : *perms = allperms;
1433 : 0 : return label_components_match(profile, label, state, subns, request,
1434 : : perms);
1435 : : }
1436 : :
1437 : :
1438 : : /**
1439 : : * aa_update_label_name - update a label to have a stored name
1440 : : * @ns: ns being viewed from (NOT NULL)
1441 : : * @label: label to update (NOT NULL)
1442 : : * @gfp: type of memory allocation
1443 : : *
1444 : : * Requires: labels_set(label) not locked in caller
1445 : : *
1446 : : * note: only updates the label name if it does not have a name already
1447 : : * and if it is in the labelset
1448 : : */
1449 : 0 : bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp)
1450 : : {
1451 : : struct aa_labelset *ls;
1452 : : unsigned long flags;
1453 : : char __counted *name;
1454 : : bool res = false;
1455 : :
1456 : : AA_BUG(!ns);
1457 : : AA_BUG(!label);
1458 : :
1459 : 0 : if (label->hname || labels_ns(label) != ns)
1460 : : return res;
1461 : :
1462 : 0 : if (aa_label_acntsxprint(&name, ns, label, FLAGS_NONE, gfp) == -1)
1463 : : return res;
1464 : :
1465 : 0 : ls = labels_set(label);
1466 : 0 : write_lock_irqsave(&ls->lock, flags);
1467 : 0 : if (!label->hname && label->flags & FLAG_IN_TREE) {
1468 : 0 : label->hname = name;
1469 : 0 : res = true;
1470 : : } else
1471 : 0 : aa_put_str(name);
1472 : 0 : write_unlock_irqrestore(&ls->lock, flags);
1473 : :
1474 : 0 : return res;
1475 : : }
1476 : :
1477 : : /*
1478 : : * cached label name is present and visible
1479 : : * @label->hname only exists if label is namespace hierachical
1480 : : */
1481 : : static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label,
1482 : : int flags)
1483 : : {
1484 : 0 : if (label->hname && (!ns || labels_ns(label) == ns) &&
1485 : 0 : !(flags & ~FLAG_SHOW_MODE))
1486 : : return true;
1487 : :
1488 : : return false;
1489 : : }
1490 : :
1491 : : /* helper macro for snprint routines */
1492 : : #define update_for_len(total, len, size, str) \
1493 : : do { \
1494 : : size_t ulen = len; \
1495 : : \
1496 : : AA_BUG(len < 0); \
1497 : : total += ulen; \
1498 : : ulen = min(ulen, size); \
1499 : : size -= ulen; \
1500 : : str += ulen; \
1501 : : } while (0)
1502 : :
1503 : : /**
1504 : : * aa_profile_snxprint - print a profile name to a buffer
1505 : : * @str: buffer to write to. (MAY BE NULL if @size == 0)
1506 : : * @size: size of buffer
1507 : : * @view: namespace profile is being viewed from
1508 : : * @profile: profile to view (NOT NULL)
1509 : : * @flags: whether to include the mode string
1510 : : * @prev_ns: last ns printed when used in compound print
1511 : : *
1512 : : * Returns: size of name written or would be written if larger than
1513 : : * available buffer
1514 : : *
1515 : : * Note: will not print anything if the profile is not visible
1516 : : */
1517 : 0 : static int aa_profile_snxprint(char *str, size_t size, struct aa_ns *view,
1518 : : struct aa_profile *profile, int flags,
1519 : : struct aa_ns **prev_ns)
1520 : : {
1521 : : const char *ns_name = NULL;
1522 : :
1523 : : AA_BUG(!str && size != 0);
1524 : : AA_BUG(!profile);
1525 : :
1526 : 0 : if (!view)
1527 : 0 : view = profiles_ns(profile);
1528 : :
1529 : 0 : if (view != profile->ns &&
1530 : 0 : (!prev_ns || (*prev_ns != profile->ns))) {
1531 : 0 : if (prev_ns)
1532 : 0 : *prev_ns = profile->ns;
1533 : 0 : ns_name = aa_ns_name(view, profile->ns,
1534 : 0 : flags & FLAG_VIEW_SUBNS);
1535 : 0 : if (ns_name == aa_hidden_ns_name) {
1536 : 0 : if (flags & FLAG_HIDDEN_UNCONFINED)
1537 : 0 : return snprintf(str, size, "%s", "unconfined");
1538 : 0 : return snprintf(str, size, "%s", ns_name);
1539 : : }
1540 : : }
1541 : :
1542 : 0 : if ((flags & FLAG_SHOW_MODE) && profile != profile->ns->unconfined) {
1543 : 0 : const char *modestr = aa_profile_mode_names[profile->mode];
1544 : :
1545 : 0 : if (ns_name)
1546 : 0 : return snprintf(str, size, ":%s:%s (%s)", ns_name,
1547 : : profile->base.hname, modestr);
1548 : 0 : return snprintf(str, size, "%s (%s)", profile->base.hname,
1549 : : modestr);
1550 : : }
1551 : :
1552 : 0 : if (ns_name)
1553 : 0 : return snprintf(str, size, ":%s:%s", ns_name,
1554 : : profile->base.hname);
1555 : 0 : return snprintf(str, size, "%s", profile->base.hname);
1556 : : }
1557 : :
1558 : 0 : static const char *label_modename(struct aa_ns *ns, struct aa_label *label,
1559 : : int flags)
1560 : : {
1561 : : struct aa_profile *profile;
1562 : : struct label_it i;
1563 : : int mode = -1, count = 0;
1564 : :
1565 : 0 : label_for_each(i, label, profile) {
1566 : 0 : if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) {
1567 : 0 : count++;
1568 : 0 : if (profile == profile->ns->unconfined)
1569 : : /* special case unconfined so stacks with
1570 : : * unconfined don't report as mixed. ie.
1571 : : * profile_foo//&:ns1:unconfined (mixed)
1572 : : */
1573 : 0 : continue;
1574 : 0 : if (mode == -1)
1575 : 0 : mode = profile->mode;
1576 : 0 : else if (mode != profile->mode)
1577 : : return "mixed";
1578 : : }
1579 : : }
1580 : :
1581 : 0 : if (count == 0)
1582 : : return "-";
1583 : 0 : if (mode == -1)
1584 : : /* everything was unconfined */
1585 : : mode = APPARMOR_UNCONFINED;
1586 : :
1587 : 0 : return aa_profile_mode_names[mode];
1588 : : }
1589 : :
1590 : : /* if any visible label is not unconfined the display_mode returns true */
1591 : 0 : static inline bool display_mode(struct aa_ns *ns, struct aa_label *label,
1592 : : int flags)
1593 : : {
1594 : 0 : if ((flags & FLAG_SHOW_MODE)) {
1595 : : struct aa_profile *profile;
1596 : : struct label_it i;
1597 : :
1598 : 0 : label_for_each(i, label, profile) {
1599 : 0 : if (aa_ns_visible(ns, profile->ns,
1600 : 0 : flags & FLAG_VIEW_SUBNS) &&
1601 : 0 : profile != profile->ns->unconfined)
1602 : : return true;
1603 : : }
1604 : : /* only ns->unconfined in set of profiles in ns */
1605 : : return false;
1606 : : }
1607 : :
1608 : : return false;
1609 : : }
1610 : :
1611 : : /**
1612 : : * aa_label_snxprint - print a label name to a string buffer
1613 : : * @str: buffer to write to. (MAY BE NULL if @size == 0)
1614 : : * @size: size of buffer
1615 : : * @ns: namespace profile is being viewed from
1616 : : * @label: label to view (NOT NULL)
1617 : : * @flags: whether to include the mode string
1618 : : *
1619 : : * Returns: size of name written or would be written if larger than
1620 : : * available buffer
1621 : : *
1622 : : * Note: labels do not have to be strictly hierarchical to the ns as
1623 : : * objects may be shared across different namespaces and thus
1624 : : * pickup labeling from each ns. If a particular part of the
1625 : : * label is not visible it will just be excluded. And if none
1626 : : * of the label is visible "---" will be used.
1627 : : */
1628 : 0 : int aa_label_snxprint(char *str, size_t size, struct aa_ns *ns,
1629 : : struct aa_label *label, int flags)
1630 : : {
1631 : : struct aa_profile *profile;
1632 : 0 : struct aa_ns *prev_ns = NULL;
1633 : : struct label_it i;
1634 : : int count = 0, total = 0;
1635 : : ssize_t len;
1636 : :
1637 : : AA_BUG(!str && size != 0);
1638 : : AA_BUG(!label);
1639 : :
1640 : 0 : if (flags & FLAG_ABS_ROOT) {
1641 : 0 : ns = root_ns;
1642 : 0 : len = snprintf(str, size, "=");
1643 : 0 : update_for_len(total, len, size, str);
1644 : 0 : } else if (!ns) {
1645 : 0 : ns = labels_ns(label);
1646 : : }
1647 : :
1648 : 0 : label_for_each(i, label, profile) {
1649 : 0 : if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) {
1650 : 0 : if (count > 0) {
1651 : 0 : len = snprintf(str, size, "//&");
1652 : 0 : update_for_len(total, len, size, str);
1653 : : }
1654 : 0 : len = aa_profile_snxprint(str, size, ns, profile,
1655 : : flags & FLAG_VIEW_SUBNS,
1656 : : &prev_ns);
1657 : 0 : update_for_len(total, len, size, str);
1658 : 0 : count++;
1659 : : }
1660 : : }
1661 : :
1662 : 0 : if (count == 0) {
1663 : 0 : if (flags & FLAG_HIDDEN_UNCONFINED)
1664 : 0 : return snprintf(str, size, "%s", "unconfined");
1665 : 0 : return snprintf(str, size, "%s", aa_hidden_ns_name);
1666 : : }
1667 : :
1668 : : /* count == 1 && ... is for backwards compat where the mode
1669 : : * is not displayed for 'unconfined' in the current ns
1670 : : */
1671 : 0 : if (display_mode(ns, label, flags)) {
1672 : 0 : len = snprintf(str, size, " (%s)",
1673 : : label_modename(ns, label, flags));
1674 : 0 : update_for_len(total, len, size, str);
1675 : : }
1676 : :
1677 : 0 : return total;
1678 : : }
1679 : : #undef update_for_len
1680 : :
1681 : : /**
1682 : : * aa_label_asxprint - allocate a string buffer and print label into it
1683 : : * @strp: Returns - the allocated buffer with the label name. (NOT NULL)
1684 : : * @ns: namespace profile is being viewed from
1685 : : * @label: label to view (NOT NULL)
1686 : : * @flags: flags controlling what label info is printed
1687 : : * @gfp: kernel memory allocation type
1688 : : *
1689 : : * Returns: size of name written or would be written if larger than
1690 : : * available buffer
1691 : : */
1692 : 0 : int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label,
1693 : : int flags, gfp_t gfp)
1694 : : {
1695 : : int size;
1696 : :
1697 : : AA_BUG(!strp);
1698 : : AA_BUG(!label);
1699 : :
1700 : 0 : size = aa_label_snxprint(NULL, 0, ns, label, flags);
1701 : 0 : if (size < 0)
1702 : : return size;
1703 : :
1704 : 0 : *strp = kmalloc(size + 1, gfp);
1705 : 0 : if (!*strp)
1706 : : return -ENOMEM;
1707 : 0 : return aa_label_snxprint(*strp, size + 1, ns, label, flags);
1708 : : }
1709 : :
1710 : : /**
1711 : : * aa_label_acntsxprint - allocate a __counted string buffer and print label
1712 : : * @strp: buffer to write to. (MAY BE NULL if @size == 0)
1713 : : * @ns: namespace profile is being viewed from
1714 : : * @label: label to view (NOT NULL)
1715 : : * @flags: flags controlling what label info is printed
1716 : : * @gfp: kernel memory allocation type
1717 : : *
1718 : : * Returns: size of name written or would be written if larger than
1719 : : * available buffer
1720 : : */
1721 : 0 : int aa_label_acntsxprint(char __counted **strp, struct aa_ns *ns,
1722 : : struct aa_label *label, int flags, gfp_t gfp)
1723 : : {
1724 : : int size;
1725 : :
1726 : : AA_BUG(!strp);
1727 : : AA_BUG(!label);
1728 : :
1729 : 0 : size = aa_label_snxprint(NULL, 0, ns, label, flags);
1730 : 0 : if (size < 0)
1731 : : return size;
1732 : :
1733 : 0 : *strp = aa_str_alloc(size + 1, gfp);
1734 : 0 : if (!*strp)
1735 : : return -ENOMEM;
1736 : 0 : return aa_label_snxprint(*strp, size + 1, ns, label, flags);
1737 : : }
1738 : :
1739 : :
1740 : 0 : void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns,
1741 : : struct aa_label *label, int flags, gfp_t gfp)
1742 : : {
1743 : : const char *str;
1744 : 0 : char *name = NULL;
1745 : : int len;
1746 : :
1747 : : AA_BUG(!ab);
1748 : : AA_BUG(!label);
1749 : :
1750 : 0 : if (!use_label_hname(ns, label, flags) ||
1751 : 0 : display_mode(ns, label, flags)) {
1752 : 0 : len = aa_label_asxprint(&name, ns, label, flags, gfp);
1753 : 0 : if (len == -1) {
1754 : : AA_DEBUG("label print error");
1755 : 0 : return;
1756 : : }
1757 : 0 : str = name;
1758 : : } else {
1759 : 0 : str = (char *) label->hname;
1760 : 0 : len = strlen(str);
1761 : : }
1762 : 0 : if (audit_string_contains_control(str, len))
1763 : 0 : audit_log_n_hex(ab, str, len);
1764 : : else
1765 : 0 : audit_log_n_string(ab, str, len);
1766 : :
1767 : 0 : kfree(name);
1768 : : }
1769 : :
1770 : 0 : void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns,
1771 : : struct aa_label *label, int flags, gfp_t gfp)
1772 : : {
1773 : : AA_BUG(!f);
1774 : : AA_BUG(!label);
1775 : :
1776 : 0 : if (!use_label_hname(ns, label, flags)) {
1777 : : char *str;
1778 : : int len;
1779 : :
1780 : 0 : len = aa_label_asxprint(&str, ns, label, flags, gfp);
1781 : 0 : if (len == -1) {
1782 : : AA_DEBUG("label print error");
1783 : 0 : return;
1784 : : }
1785 : 0 : seq_printf(f, "%s", str);
1786 : 0 : kfree(str);
1787 : 0 : } else if (display_mode(ns, label, flags))
1788 : 0 : seq_printf(f, "%s (%s)", label->hname,
1789 : : label_modename(ns, label, flags));
1790 : : else
1791 : 0 : seq_printf(f, "%s", label->hname);
1792 : : }
1793 : :
1794 : 0 : void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags,
1795 : : gfp_t gfp)
1796 : : {
1797 : : AA_BUG(!label);
1798 : :
1799 : 0 : if (!use_label_hname(ns, label, flags)) {
1800 : : char *str;
1801 : : int len;
1802 : :
1803 : 0 : len = aa_label_asxprint(&str, ns, label, flags, gfp);
1804 : 0 : if (len == -1) {
1805 : : AA_DEBUG("label print error");
1806 : 0 : return;
1807 : : }
1808 : 0 : pr_info("%s", str);
1809 : 0 : kfree(str);
1810 : 0 : } else if (display_mode(ns, label, flags))
1811 : 0 : pr_info("%s (%s)", label->hname,
1812 : : label_modename(ns, label, flags));
1813 : : else
1814 : 0 : pr_info("%s", label->hname);
1815 : : }
1816 : :
1817 : 0 : void aa_label_audit(struct audit_buffer *ab, struct aa_label *label, gfp_t gfp)
1818 : : {
1819 : 0 : struct aa_ns *ns = aa_get_current_ns();
1820 : :
1821 : 0 : aa_label_xaudit(ab, ns, label, FLAG_VIEW_SUBNS, gfp);
1822 : 0 : aa_put_ns(ns);
1823 : 0 : }
1824 : :
1825 : 0 : void aa_label_seq_print(struct seq_file *f, struct aa_label *label, gfp_t gfp)
1826 : : {
1827 : 0 : struct aa_ns *ns = aa_get_current_ns();
1828 : :
1829 : 0 : aa_label_seq_xprint(f, ns, label, FLAG_VIEW_SUBNS, gfp);
1830 : 0 : aa_put_ns(ns);
1831 : 0 : }
1832 : :
1833 : 0 : void aa_label_printk(struct aa_label *label, gfp_t gfp)
1834 : : {
1835 : 0 : struct aa_ns *ns = aa_get_current_ns();
1836 : :
1837 : 0 : aa_label_xprintk(ns, label, FLAG_VIEW_SUBNS, gfp);
1838 : 0 : aa_put_ns(ns);
1839 : 0 : }
1840 : :
1841 : 0 : static int label_count_strn_entries(const char *str, size_t n)
1842 : : {
1843 : 0 : const char *end = str + n;
1844 : : const char *split;
1845 : : int count = 1;
1846 : :
1847 : : AA_BUG(!str);
1848 : :
1849 : 0 : for (split = aa_label_strn_split(str, end - str);
1850 : : split;
1851 : 0 : split = aa_label_strn_split(str, end - str)) {
1852 : 0 : count++;
1853 : 0 : str = split + 3;
1854 : : }
1855 : :
1856 : 0 : return count;
1857 : : }
1858 : :
1859 : : /*
1860 : : * ensure stacks with components like
1861 : : * :ns:A//&B
1862 : : * have :ns: applied to both 'A' and 'B' by making the lookup relative
1863 : : * to the base if the lookup specifies an ns, else making the stacked lookup
1864 : : * relative to the last embedded ns in the string.
1865 : : */
1866 : 0 : static struct aa_profile *fqlookupn_profile(struct aa_label *base,
1867 : : struct aa_label *currentbase,
1868 : : const char *str, size_t n)
1869 : : {
1870 : 0 : const char *first = skipn_spaces(str, n);
1871 : :
1872 : 0 : if (first && *first == ':')
1873 : 0 : return aa_fqlookupn_profile(base, str, n);
1874 : :
1875 : 0 : return aa_fqlookupn_profile(currentbase, str, n);
1876 : : }
1877 : :
1878 : : /**
1879 : : * aa_label_strn_parse - parse, validate and convert a text string to a label
1880 : : * @base: base label to use for lookups (NOT NULL)
1881 : : * @str: null terminated text string (NOT NULL)
1882 : : * @n: length of str to parse, will stop at \0 if encountered before n
1883 : : * @gfp: allocation type
1884 : : * @create: true if should create compound labels if they don't exist
1885 : : * @force_stack: true if should stack even if no leading &
1886 : : *
1887 : : * Returns: the matching refcounted label if present
1888 : : * else ERRPTR
1889 : : */
1890 : 0 : struct aa_label *aa_label_strn_parse(struct aa_label *base, const char *str,
1891 : : size_t n, gfp_t gfp, bool create,
1892 : : bool force_stack)
1893 : : {
1894 : : DEFINE_VEC(profile, vec);
1895 : : struct aa_label *label, *currbase = base;
1896 : : int i, len, stack = 0, error;
1897 : 0 : const char *end = str + n;
1898 : : const char *split;
1899 : :
1900 : : AA_BUG(!base);
1901 : : AA_BUG(!str);
1902 : :
1903 : 0 : str = skipn_spaces(str, n);
1904 : 0 : if (str == NULL || (*str == '=' && base != &root_ns->unconfined->label))
1905 : : return ERR_PTR(-EINVAL);
1906 : :
1907 : 0 : len = label_count_strn_entries(str, end - str);
1908 : 0 : if (*str == '&' || force_stack) {
1909 : : /* stack on top of base */
1910 : 0 : stack = base->size;
1911 : 0 : len += stack;
1912 : 0 : if (*str == '&')
1913 : 0 : str++;
1914 : : }
1915 : :
1916 : 0 : error = vec_setup(profile, vec, len, gfp);
1917 : 0 : if (error)
1918 : 0 : return ERR_PTR(error);
1919 : :
1920 : 0 : for (i = 0; i < stack; i++)
1921 : 0 : vec[i] = aa_get_profile(base->vec[i]);
1922 : :
1923 : 0 : for (split = aa_label_strn_split(str, end - str), i = stack;
1924 : 0 : split && i < len; i++) {
1925 : 0 : vec[i] = fqlookupn_profile(base, currbase, str, split - str);
1926 : 0 : if (!vec[i])
1927 : : goto fail;
1928 : : /*
1929 : : * if component specified a new ns it becomes the new base
1930 : : * so that subsequent lookups are relative to it
1931 : : */
1932 : 0 : if (vec[i]->ns != labels_ns(currbase))
1933 : 0 : currbase = &vec[i]->label;
1934 : 0 : str = split + 3;
1935 : 0 : split = aa_label_strn_split(str, end - str);
1936 : : }
1937 : : /* last element doesn't have a split */
1938 : 0 : if (i < len) {
1939 : 0 : vec[i] = fqlookupn_profile(base, currbase, str, end - str);
1940 : 0 : if (!vec[i])
1941 : : goto fail;
1942 : : }
1943 : 0 : if (len == 1)
1944 : : /* no need to free vec as len < LOCAL_VEC_ENTRIES */
1945 : 0 : return &vec[0]->label;
1946 : :
1947 : 0 : len -= aa_vec_unique(vec, len, VEC_FLAG_TERMINATE);
1948 : : /* TODO: deal with reference labels */
1949 : 0 : if (len == 1) {
1950 : 0 : label = aa_get_label(&vec[0]->label);
1951 : 0 : goto out;
1952 : : }
1953 : :
1954 : 0 : if (create)
1955 : 0 : label = aa_vec_find_or_create_label(vec, len, gfp);
1956 : : else
1957 : 0 : label = vec_find(vec, len);
1958 : 0 : if (!label)
1959 : : goto fail;
1960 : :
1961 : : out:
1962 : : /* use adjusted len from after vec_unique, not original */
1963 : 0 : vec_cleanup(profile, vec, len);
1964 : 0 : return label;
1965 : :
1966 : : fail:
1967 : : label = ERR_PTR(-ENOENT);
1968 : : goto out;
1969 : : }
1970 : :
1971 : 0 : struct aa_label *aa_label_parse(struct aa_label *base, const char *str,
1972 : : gfp_t gfp, bool create, bool force_stack)
1973 : : {
1974 : 0 : return aa_label_strn_parse(base, str, strlen(str), gfp, create,
1975 : : force_stack);
1976 : : }
1977 : :
1978 : : /**
1979 : : * aa_labelset_destroy - remove all labels from the label set
1980 : : * @ls: label set to cleanup (NOT NULL)
1981 : : *
1982 : : * Labels that are removed from the set may still exist beyond the set
1983 : : * being destroyed depending on their reference counting
1984 : : */
1985 : 0 : void aa_labelset_destroy(struct aa_labelset *ls)
1986 : : {
1987 : : struct rb_node *node;
1988 : : unsigned long flags;
1989 : :
1990 : : AA_BUG(!ls);
1991 : :
1992 : 0 : write_lock_irqsave(&ls->lock, flags);
1993 : 0 : for (node = rb_first(&ls->root); node; node = rb_first(&ls->root)) {
1994 : 0 : struct aa_label *this = rb_entry(node, struct aa_label, node);
1995 : :
1996 : 0 : if (labels_ns(this) != root_ns)
1997 : 0 : __label_remove(this,
1998 : 0 : ns_unconfined(labels_ns(this)->parent));
1999 : : else
2000 : 0 : __label_remove(this, NULL);
2001 : : }
2002 : 0 : write_unlock_irqrestore(&ls->lock, flags);
2003 : 0 : }
2004 : :
2005 : : /*
2006 : : * @ls: labelset to init (NOT NULL)
2007 : : */
2008 : 0 : void aa_labelset_init(struct aa_labelset *ls)
2009 : : {
2010 : : AA_BUG(!ls);
2011 : :
2012 : 0 : rwlock_init(&ls->lock);
2013 : 0 : ls->root = RB_ROOT;
2014 : 0 : }
2015 : :
2016 : 0 : static struct aa_label *labelset_next_stale(struct aa_labelset *ls)
2017 : : {
2018 : : struct aa_label *label;
2019 : : struct rb_node *node;
2020 : : unsigned long flags;
2021 : :
2022 : : AA_BUG(!ls);
2023 : :
2024 : 0 : read_lock_irqsave(&ls->lock, flags);
2025 : :
2026 : 0 : __labelset_for_each(ls, node) {
2027 : 0 : label = rb_entry(node, struct aa_label, node);
2028 : 0 : if ((label_is_stale(label) ||
2029 : 0 : vec_is_stale(label->vec, label->size)) &&
2030 : : __aa_get_label(label))
2031 : : goto out;
2032 : :
2033 : : }
2034 : : label = NULL;
2035 : :
2036 : : out:
2037 : 0 : read_unlock_irqrestore(&ls->lock, flags);
2038 : :
2039 : 0 : return label;
2040 : : }
2041 : :
2042 : : /**
2043 : : * __label_update - insert updated version of @label into labelset
2044 : : * @label - the label to update/replace
2045 : : *
2046 : : * Returns: new label that is up to date
2047 : : * else NULL on failure
2048 : : *
2049 : : * Requires: @ns lock be held
2050 : : *
2051 : : * Note: worst case is the stale @label does not get updated and has
2052 : : * to be updated at a later time.
2053 : : */
2054 : 0 : static struct aa_label *__label_update(struct aa_label *label)
2055 : : {
2056 : : struct aa_label *new, *tmp;
2057 : : struct aa_labelset *ls;
2058 : : unsigned long flags;
2059 : : int i, invcount = 0;
2060 : :
2061 : : AA_BUG(!label);
2062 : : AA_BUG(!mutex_is_locked(&labels_ns(label)->lock));
2063 : :
2064 : 0 : new = aa_label_alloc(label->size, label->proxy, GFP_KERNEL);
2065 : 0 : if (!new)
2066 : : return NULL;
2067 : :
2068 : : /*
2069 : : * while holding the ns_lock will stop profile replacement, removal,
2070 : : * and label updates, label merging and removal can be occurring
2071 : : */
2072 : 0 : ls = labels_set(label);
2073 : 0 : write_lock_irqsave(&ls->lock, flags);
2074 : 0 : for (i = 0; i < label->size; i++) {
2075 : : AA_BUG(!label->vec[i]);
2076 : 0 : new->vec[i] = aa_get_newest_profile(label->vec[i]);
2077 : : AA_BUG(!new->vec[i]);
2078 : : AA_BUG(!new->vec[i]->label.proxy);
2079 : : AA_BUG(!new->vec[i]->label.proxy->label);
2080 : 0 : if (new->vec[i]->label.proxy != label->vec[i]->label.proxy)
2081 : 0 : invcount++;
2082 : : }
2083 : :
2084 : : /* updated stale label by being removed/renamed from labelset */
2085 : 0 : if (invcount) {
2086 : 0 : new->size -= aa_vec_unique(&new->vec[0], new->size,
2087 : : VEC_FLAG_TERMINATE);
2088 : : /* TODO: deal with reference labels */
2089 : 0 : if (new->size == 1) {
2090 : 0 : tmp = aa_get_label(&new->vec[0]->label);
2091 : : AA_BUG(tmp == label);
2092 : 0 : goto remove;
2093 : : }
2094 : 0 : if (labels_set(label) != labels_set(new)) {
2095 : 0 : write_unlock_irqrestore(&ls->lock, flags);
2096 : 0 : tmp = aa_label_insert(labels_set(new), new);
2097 : 0 : write_lock_irqsave(&ls->lock, flags);
2098 : 0 : goto remove;
2099 : : }
2100 : : } else
2101 : : AA_BUG(labels_ns(label) != labels_ns(new));
2102 : :
2103 : 0 : tmp = __label_insert(labels_set(label), new, true);
2104 : : remove:
2105 : : /* ensure label is removed, and redirected correctly */
2106 : 0 : __label_remove(label, tmp);
2107 : 0 : write_unlock_irqrestore(&ls->lock, flags);
2108 : 0 : label_free_or_put_new(tmp, new);
2109 : :
2110 : 0 : return tmp;
2111 : : }
2112 : :
2113 : : /**
2114 : : * __labelset_update - update labels in @ns
2115 : : * @ns: namespace to update labels in (NOT NULL)
2116 : : *
2117 : : * Requires: @ns lock be held
2118 : : *
2119 : : * Walk the labelset ensuring that all labels are up to date and valid
2120 : : * Any label that has a stale component is marked stale and replaced and
2121 : : * by an updated version.
2122 : : *
2123 : : * If failures happen due to memory pressures then stale labels will
2124 : : * be left in place until the next pass.
2125 : : */
2126 : 0 : static void __labelset_update(struct aa_ns *ns)
2127 : : {
2128 : : struct aa_label *label;
2129 : :
2130 : : AA_BUG(!ns);
2131 : : AA_BUG(!mutex_is_locked(&ns->lock));
2132 : :
2133 : : do {
2134 : 0 : label = labelset_next_stale(&ns->labels);
2135 : 0 : if (label) {
2136 : 0 : struct aa_label *l = __label_update(label);
2137 : :
2138 : : aa_put_label(l);
2139 : : aa_put_label(label);
2140 : : }
2141 : 0 : } while (label);
2142 : 0 : }
2143 : :
2144 : : /**
2145 : : * __aa_labelset_udate_subtree - update all labels with a stale component
2146 : : * @ns: ns to start update at (NOT NULL)
2147 : : *
2148 : : * Requires: @ns lock be held
2149 : : *
2150 : : * Invalidates labels based on @p in @ns and any children namespaces.
2151 : : */
2152 : 0 : void __aa_labelset_update_subtree(struct aa_ns *ns)
2153 : : {
2154 : : struct aa_ns *child;
2155 : :
2156 : : AA_BUG(!ns);
2157 : : AA_BUG(!mutex_is_locked(&ns->lock));
2158 : :
2159 : 0 : __labelset_update(ns);
2160 : :
2161 : 0 : list_for_each_entry(child, &ns->sub_ns, base.list) {
2162 : 0 : mutex_lock_nested(&child->lock, child->level);
2163 : 0 : __aa_labelset_update_subtree(child);
2164 : 0 : mutex_unlock(&child->lock);
2165 : : }
2166 : 0 : }
|