]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - security/apparmor/label.c
Revert "UBUNTU: SAUCE: apparmor: Fix: oops do to invalid null ptr deref in label...
[mirror_ubuntu-artful-kernel.git] / security / apparmor / label.c
CommitLineData
6bfc18ae
JJ
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor label definitions
5 *
6 * Copyright 2013 Canonical Ltd.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2 of the
11 * License.
12 */
13
14#include <linux/audit.h>
15#include <linux/seq_file.h>
16
17#include "include/apparmor.h"
18#include "include/label.h"
19#include "include/policy.h"
20#include "include/sid.h"
21
22
23/*
24 * the aa_label represents the set of profiles confining an object
25 *
26 * Labels maintain a reference count to the set of pointers they reference
27 * Labels are ref counted by
28 * tasks and object via the security field/security context off the field
29 * code - will take a ref count on a label if it needs the label
30 * beyond what is possible with an rcu_read_lock.
31 * profiles - each profile is a label
32 * sids - a pinned sid will keep a refcount of the label it is
33 * referencing
34 * objects - inode, files, sockets, ...
35 *
36 * Labels are not ref counted by the label set, so they maybe removed and
37 * freed when no longer in use.
38 *
39 */
40
41static void free_replacedby(struct aa_replacedby *r)
42{
43 if (r) {
44 /* r->label will not updated any more as r is dead */
45 aa_put_label(rcu_dereference_protected(r->label, true));
1963692b 46 kzfree(r);
6bfc18ae
JJ
47 }
48}
49
50void aa_free_replacedby_kref(struct kref *kref)
51{
52 struct aa_replacedby *r = container_of(kref, struct aa_replacedby,
53 count);
54 free_replacedby(r);
55}
56
8ac21d39 57struct aa_replacedby *aa_alloc_replacedby(struct aa_label *l)
6bfc18ae
JJ
58{
59 struct aa_replacedby *r;
60
8ac21d39 61 r = kzalloc(sizeof(struct aa_replacedby), GFP_KERNEL);
6bfc18ae
JJ
62 if (r) {
63 kref_init(&r->count);
64 rcu_assign_pointer(r->label, aa_get_label(l));
65 }
66 return r;
67}
68
69/* requires profile list write lock held */
70void __aa_update_replacedby(struct aa_label *orig, struct aa_label *new)
71{
72 struct aa_label *tmp;
73
74 AA_BUG(!orig);
75 AA_BUG(!new);
4d69b183 76 AA_BUG(!mutex_is_locked(&labels_ns(orig)->lock));
6bfc18ae
JJ
77
78 tmp = rcu_dereference_protected(orig->replacedby->label,
79 &labels_ns(orig)->lock);
80 rcu_assign_pointer(orig->replacedby->label, aa_get_label(new));
81 orig->flags |= FLAG_INVALID;
82 aa_put_label(tmp);
83}
84
85/* helper fn for label_for_each_confined */
86int aa_label_next_confined(struct aa_label *l, int i)
87{
88 AA_BUG(!l);
89 AA_BUG(i < 0);
90
91 for (; i < l->size; i++) {
92 if (!profile_unconfined(l->ent[i]))
93 return i;
94 }
95
96 return i;
97}
98
99#if 0
100static int label_profile_pos(struct aa_label *l, struct aa_profile *profile)
101{
102 struct aa_profile *p;
103 struct label_it i;
104
105 AA_BUG(!profile);
106 AA_BUG(!l);
107
108 label_for_each(i, l, p) {
109 if (p == profile)
110 return i.i;
111 }
112
113 return -1;
114}
115#endif
116
117#if 0
118static bool profile_in_label(struct aa_profile *profile, struct aa_label *l)
119{
120 return label_profile_pos(l, profile) != -1;
121}
122#endif
123
124static bool label_profiles_unconfined(struct aa_label *label)
125{
126 struct aa_profile *profile;
127 struct label_it i;
128
129 AA_BUG(!label);
130
131 label_for_each(i, label, profile) {
132 if (!profile_unconfined(profile))
133 return false;
134 }
135
136 return true;
137}
138
139static int profile_cmp(struct aa_profile *a, struct aa_profile *b);
140/**
141 * aa_label_next_not_in_set - return the next profile of @sub not in @set
142 * @I: label iterator
143 * @set: label to test against
144 * @sub: label to if is subset of @set
145 *
146 * Returns: profile in @sub that is not in @set, with iterator set pos after
147 * else NULL if @sub is a subset of @set
148 */
d39820a1
JJ
149struct aa_profile * aa_label_next_not_in_set(struct label_it *I,
150 struct aa_label *set,
151 struct aa_label *sub)
6bfc18ae
JJ
152{
153 AA_BUG(!set);
154 AA_BUG(!I);
155 AA_BUG(I->i < 0);
156 AA_BUG(I->i > set->size);
157 AA_BUG(!sub);
158 AA_BUG(I->j < 0);
159 AA_BUG(I->j > sub->size);
160
161 while (I->j < sub->size && I->i < set->size) {
162 int res = profile_cmp(sub->ent[I->j], set->ent[I->i]);
163 if (res == 0) {
164 (I->j)++;
165 (I->i)++;
166 } else if (res > 0)
167 (I->i)++;
168 else
169 return sub->ent[(I->j)++];
170 }
171
172 if (I->j < sub->size)
173 return sub->ent[(I->j)++];
174
175 return NULL;
176}
177
178/**
179 * aa_label_is_subset - test if @sub is a subset of @set
180 * @set: label to test against
181 * @sub: label to test if is subset of @set
182 *
183 * Returns: true if @sub is subset of @set
184 * else false
185 */
186bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub)
187{
188 struct label_it i = { };
189
190 AA_BUG(!set);
191 AA_BUG(!sub);
192
193 if (sub == set)
194 return true;
195
d39820a1 196 return aa_label_next_not_in_set(&i, set, sub) == NULL;
6bfc18ae
JJ
197}
198
199void aa_label_destroy(struct aa_label *label)
200{
201 AA_BUG(!label);
202
203 if (label_invalid(label))
204 labelsetstats_dec(labels_set(label), invalid);
205
206 if (!label_isprofile(label)) {
207 struct aa_profile *profile;
208 struct label_it i;
209
210 aa_put_str(label->hname);
211
1963692b 212 label_for_each(i, label, profile)
6bfc18ae
JJ
213 aa_put_profile(profile);
214 }
1963692b 215
6bfc18ae
JJ
216 aa_free_sid(label->sid);
217 aa_put_replacedby(label->replacedby);
218}
219
220void aa_label_free(struct aa_label *label)
221{
222 if (!label)
223 return;
224
225 aa_label_destroy(label);
226 labelstats_inc(freed);
1963692b 227 kzfree(label);
6bfc18ae
JJ
228}
229
e6ce3c3c 230static void label_free_rcu(struct rcu_head *head)
6bfc18ae 231{
e6ce3c3c
JJ
232 struct aa_label *l = container_of(head, struct aa_label, rcu);
233
6bfc18ae
JJ
234 if (l->flags & FLAG_NS_COUNT)
235 aa_free_namespace(labels_ns(l));
236 else if (label_isprofile(l))
237 aa_free_profile(labels_profile(l));
238 else
239 aa_label_free(l);
240}
241
242bool aa_label_remove(struct aa_labelset *ls, struct aa_label *label);
243void aa_label_kref(struct kref *kref)
244{
245 struct aa_label *l = container_of(kref, struct aa_label, count);
246 struct aa_namespace *ns = labels_ns(l);
247
248 if (!ns) {
249 /* never live, no rcu callback needed, just using the fn */
e6ce3c3c 250 label_free_rcu(&l->rcu);
6bfc18ae
JJ
251 return;
252 }
253
e6ce3c3c
JJ
254 (void) aa_label_remove(&ns->labels, l);
255
6bfc18ae
JJ
256 /* TODO: if compound label and not invalid add to reclaim cache */
257 call_rcu(&l->rcu, label_free_rcu);
258}
259
260bool aa_label_init(struct aa_label *label, int size)
261{
262 AA_BUG(!label);
263 AA_BUG(size < 1);
264
265 label->sid = aa_alloc_sid();
266 if (label->sid == AA_SID_INVALID)
267 return false;
268
269 label->size = size; /* doesn't include null */
270 label->ent[size] = NULL; /* null terminate */
271 kref_init(&label->count);
272 RB_CLEAR_NODE(&label->node);
273
274 return true;
275}
276
277/**
278 * aa_label_alloc - allocate a label with a profile vector of @size length
279 * @size: size of profile vector in the label
280 * @gfp: memory allocation type
281 *
282 * Returns: new label
283 * else NULL if failed
284 */
f126fd25 285struct aa_label *aa_label_alloc(int size, gfp_t gfp)
6bfc18ae
JJ
286{
287 struct aa_label *label;
288
289 AA_BUG(size < 1);
290
291 /* vector: size - 2 (size of array in label struct) + 1 for null */
292 label = kzalloc(sizeof(*label) + sizeof(struct aa_label *) * (size - 1),
293 gfp);
294 AA_DEBUG("%s (%p)\n", __func__, label);
295 if (!label)
296 goto fail;
297
298 if (!aa_label_init(label, size))
299 goto fail;
300
301 labelstats_inc(allocated);
302
303 return label;
304
305fail:
306 kfree(label);
307 labelstats_inc(failed);
308
309 return NULL;
310}
311
67194e9d 312static bool __aa_label_remove(struct aa_labelset *ls, struct aa_label *label)
6bfc18ae
JJ
313{
314 AA_BUG(!ls);
315 AA_BUG(!label);
316 AA_BUG(!write_is_locked(&ls->lock));
317 AA_BUG(labels_set(label) != ls);
318
319 if (label_invalid(label))
320 labelstats_dec(invalid_intree);
321 else
322 __label_invalidate(label);
323
324 if (label->flags & FLAG_IN_TREE) {
325 labelsetstats_dec(ls, intree);
326 rb_erase(&label->node, &ls->root);
327 label->flags &= ~FLAG_IN_TREE;
328 return true;
329 }
330
331 return false;
332}
333
334/**
335 * aa_label_remove - remove a label from the labelset
336 * @ls: set to remove the label from
337 * @l: label to remove
338 *
339 * Returns: true if @l was removed from the tree
340 * else @l was not in tree so it could not be removed
341 */
342bool aa_label_remove(struct aa_labelset *ls, struct aa_label *l)
343{
344 unsigned long flags;
345 bool res;
346
347 write_lock_irqsave(&ls->lock, flags);
67194e9d 348 res = __aa_label_remove(ls, l);
6bfc18ae
JJ
349 write_unlock_irqrestore(&ls->lock, flags);
350
351 return res;
352}
353
709bba29 354#if 0
6bfc18ae
JJ
355/* don't use when using ptr comparisons because nodes should never be
356 * the same
357 */
358static bool __aa_label_replace(struct aa_labelset *ls, struct aa_label *old,
359 struct aa_label *new)
360{
361 AA_BUG(!ls);
362 AA_BUG(!old);
363 AA_BUG(!new);
364 AA_BUG(!write_is_locked(&ls->lock));
365 AA_BUG(labels_set(old) != ls);
366 AA_BUG(new->flags & FLAG_IN_TREE);
367
368 if (label_invalid(old))
369 labelstats_dec(invalid_intree);
370 else
371 __label_invalidate(old);
372
373 if (old->flags & FLAG_IN_TREE) {
374 rb_replace_node(&old->node, &new->node, &ls->root);
375 old->flags &= ~FLAG_IN_TREE;
376 new->flags |= FLAG_IN_TREE;
377 return true;
378 }
379
380 return false;
381}
709bba29 382#endif
6bfc18ae
JJ
383
384static struct aa_label *__aa_label_insert(struct aa_labelset *ls,
709bba29 385 struct aa_label *l);
6bfc18ae
JJ
386
387static struct aa_label *__aa_label_remove_and_insert(struct aa_labelset *ls,
388 struct aa_label *remove,
e23c92ae 389 struct aa_label *insert)
6bfc18ae
JJ
390{
391 AA_BUG(!ls);
392 AA_BUG(!remove);
393 AA_BUG(!insert);
394 AA_BUG(!write_is_locked(&ls->lock));
395 AA_BUG(labels_set(remove) != ls);
396 AA_BUG(insert->flags & FLAG_IN_TREE);
397
67194e9d 398 __aa_label_remove(ls, remove);
709bba29 399 return __aa_label_insert(ls, insert);
6bfc18ae
JJ
400}
401
402struct aa_label *aa_label_remove_and_insert(struct aa_labelset *ls,
403 struct aa_label *remove,
404 struct aa_label *insert)
405{
406 unsigned long flags;
407 struct aa_label *l;
408
409 write_lock_irqsave(&ls->lock, flags);
e23c92ae 410 l = aa_get_label(__aa_label_remove_and_insert(ls, remove, insert));
6bfc18ae
JJ
411 write_unlock_irqrestore(&ls->lock, flags);
412
413 return l;
414}
415
416/**
417 * aa_label_replace - replace a label @old with a new version @new
4d69b183 418 * @ls: labelset being manipulated
6bfc18ae
JJ
419 * @old: label to replace
420 * @new: label replacing @old
421 *
422 * Returns: true if @old was in tree and replaced
423 * else @old was not in tree, and @new was not inserted
424 */
4d69b183
JJ
425bool aa_label_replace(struct aa_labelset *ls, struct aa_label *old,
426 struct aa_label *new)
6bfc18ae 427{
4d69b183 428 struct aa_label *l;
6bfc18ae
JJ
429 unsigned long flags;
430 bool res;
431
4d69b183 432 write_lock_irqsave(&ls->lock, flags);
e23c92ae 433 if (!(old->flags & FLAG_IN_TREE))
709bba29 434 l = __aa_label_insert(ls, new);
e23c92ae
JJ
435 else
436 l = __aa_label_remove_and_insert(ls, old, new);
4d69b183
JJ
437 res = (l == new);
438 write_unlock_irqrestore(&ls->lock, flags);
6bfc18ae
JJ
439
440 return res;
441}
442
443static int ns_cmp(struct aa_namespace *a, struct aa_namespace *b)
444{
445 int res;
446
447 AA_BUG(!a);
448 AA_BUG(!b);
449 AA_BUG(!a->base.name);
450 AA_BUG(!b->base.name);
451
452 if (a == b)
453 return 0;
454
455 res = a->level - b->level;
456 if (res)
457 return res;
458
459 return strcmp(a->base.name, b->base.name);
460}
461
462/**
463 * profile_cmp - profile comparision for set ordering
464 * @a: profile to compare (NOT NULL)
465 * @b: profile to compare (NOT NULL)
466 *
467 * Returns: <0 if a < b
468 * ==0 if a == b
469 * >0 if a > b
470 */
471static int profile_cmp(struct aa_profile *a, struct aa_profile *b)
472{
473 int res;
474
475 AA_BUG(!a);
476 AA_BUG(!b);
477 AA_BUG(!a->ns);
478 AA_BUG(!b->ns);
479 AA_BUG(!a->base.hname);
480 AA_BUG(!b->base.hname);
481
482 if (a == b || a->base.hname == b->base.hname)
483 return 0;
484 res = ns_cmp(a->ns, b->ns);
485 if (res)
486 return res;
487
488 return strcmp(a->base.hname, b->base.hname);
489}
490
491/**
492 * label_vec_cmp - label comparision for set ordering
493 * @a: label to compare (NOT NULL)
494 * @vec: vector of profiles to compare (NOT NULL)
495 * @n: length of @vec
496 *
497 * Returns: <0 if a < vec
498 * ==0 if a == vec
499 * >0 if a > vec
500 */
501static int label_vec_cmp(struct aa_label *a, struct aa_profile **vec, int n)
502{
503 int i;
504
505 AA_BUG(!a);
506 AA_BUG(!vec);
507 AA_BUG(!*vec);
508 AA_BUG(n <= 0);
509
510 for (i = 0; i < a->size && i < n; i++) {
511 int res = profile_cmp(a->ent[i], vec[i]);
512 if (res != 0)
513 return res;
514 }
515
516 return a->size - n;
517}
518
519/**
520 * label_cmp - label comparision for set ordering
521 * @a: label to compare (NOT NULL)
522 * @b: label to compare (NOT NULL)
523 *
524 * Returns: <0 if a < b
525 * ==0 if a == b
526 * >0 if a > b
527 */
528static int label_cmp(struct aa_label *a, struct aa_label *b)
529{
530 AA_BUG(!b);
531
532 if (a == b)
533 return 0;
534
535 return label_vec_cmp(a, b->ent, b->size);
536}
537
538/**
539 * __aa_label_vec_find - find label that matches @vec in label set
540 * @ls: set of labels to search (NOT NULL)
541 * @vec: vec of profiles to find matching label for (NOT NULL)
542 * @n: length of @vec
543 *
544 * Requires: @ls lock held
545 * caller to hold a valid ref on l
546 *
e23c92ae 547 * Returns: unref counted @label if matching label is in tree
6bfc18ae
JJ
548 * else NULL if @vec equiv is not in tree
549 */
550static struct aa_label *__aa_label_vec_find(struct aa_labelset *ls,
551 struct aa_profile **vec, int n)
552{
553 struct rb_node *node;
554
555 AA_BUG(!ls);
556 AA_BUG(!vec);
557 AA_BUG(!*vec);
558 AA_BUG(n <= 0);
559
560 node = ls->root.rb_node;
561 while (node) {
562 struct aa_label *this = rb_entry(node, struct aa_label, node);
563 int result = label_vec_cmp(this, vec, n);
564
565 if (result > 0)
566 node = node->rb_left;
567 else if (result < 0)
568 node = node->rb_right;
569 else
e23c92ae 570 return this;
6bfc18ae
JJ
571 }
572
573 return NULL;
574}
575
576/**
577 * __aa_label_find - find label @l in label set
578 * @ls: set of labels to search (NOT NULL)
579 * @l: label to find (NOT NULL)
580 *
581 * Requires: @ls lock held
582 * caller to hold a valid ref on l
583 *
e23c92ae
JJ
584 * Returns: unref counted @l if @l is in tree
585 * unref counted label that is equiv to @l in tree
6bfc18ae
JJ
586 * else NULL if @l or equiv is not in tree
587 */
588static struct aa_label *__aa_label_find(struct aa_labelset *ls,
589 struct aa_label *l)
590{
591 AA_BUG(!l);
592
593 return __aa_label_vec_find(ls, l->ent, l->size);
594}
595
596/**
597 * aa_label_vec_find - find label @l in label set
598 * @ls: set of labels to search (NOT NULL)
599 * @vec: array of profiles to find equiv label for (NOT NULL)
600 * @n: length of @vec
601 *
602 * Returns: refcounted label if @vec equiv is in tree
603 * else NULL if @vec equiv is not in tree
604 */
605struct aa_label *aa_label_vec_find(struct aa_labelset *ls,
606 struct aa_profile **vec,
607 int n)
608{
609 struct aa_label *label;
610 unsigned long flags;
611
612 AA_BUG(!ls);
613 AA_BUG(!vec);
614 AA_BUG(!*vec);
615 AA_BUG(n <= 0);
616
617 read_lock_irqsave(&ls->lock, flags);
e23c92ae 618 label = aa_get_label(__aa_label_vec_find(ls, vec, n));
6bfc18ae
JJ
619 labelstats_inc(sread);
620 read_unlock_irqrestore(&ls->lock, flags);
621
622 return label;
623}
624
625/**
626 * aa_label_find - find label @l in label set
627 * @ls: set of labels to search (NOT NULL)
628 * @l: label to find (NOT NULL)
629 *
630 * Requires: caller to hold a valid ref on l
631 *
632 * Returns: refcounted @l if @l is in tree
633 * refcounted label that is equiv to @l in tree
634 * else NULL if @l or equiv is not in tree
635 */
636struct aa_label *aa_label_find(struct aa_labelset *ls, struct aa_label *l)
637{
638 AA_BUG(!l);
639
640 return aa_label_vec_find(ls, l->ent, l->size);
641}
642
643/**
644 * __aa_label_insert - attempt to insert @l into a label set
645 * @ls: set of labels to insert @l into (NOT NULL)
646 * @l: new label to insert (NOT NULL)
709bba29 647 *
6bfc18ae
JJ
648 * Requires: @ls->lock
649 * caller to hold a valid ref on l
93e7aa83 650 *
e23c92ae
JJ
651 * Returns: @l if successful in inserting @l
652 * else ref counted equivalent label that is already in the set.
6bfc18ae
JJ
653 */
654static struct aa_label *__aa_label_insert(struct aa_labelset *ls,
709bba29 655 struct aa_label *l)
6bfc18ae
JJ
656{
657 struct rb_node **new, *parent = NULL;
658
659 AA_BUG(!ls);
660 AA_BUG(!l);
661 AA_BUG(!write_is_locked(&ls->lock));
662 AA_BUG(l->flags & FLAG_IN_TREE);
663
664 /* Figure out where to put new node */
665 new = &ls->root.rb_node;
666 while (*new) {
667 struct aa_label *this = rb_entry(*new, struct aa_label, node);
668 int result = label_cmp(l, this);
669
670 parent = *new;
671 if (result == 0) {
672 labelsetstats_inc(ls, existing);
709bba29 673 return this;
6bfc18ae
JJ
674 } else if (result < 0)
675 new = &((*new)->rb_left);
676 else /* (result > 0) */
677 new = &((*new)->rb_right);
678 }
679
680 /* Add new node and rebalance tree. */
681 rb_link_node(&l->node, parent, new);
682 rb_insert_color(&l->node, &ls->root);
683 l->flags |= FLAG_IN_TREE;
684 labelsetstats_inc(ls, insert);
685 labelsetstats_inc(ls, intree);
686
709bba29 687 return l;
6bfc18ae
JJ
688}
689
690/**
691 * aa_label_insert - insert label @l into @ls or return existing label
692 * @ls - labelset to insert @l into
693 * @l - label to insert
694 *
695 * Requires: caller to hold a valid ref on l
696 *
697 * Returns: ref counted @l if successful in inserting @l
698 * else ref counted equivalent label that is already in the set
699 */
700struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *l)
701{
702 struct aa_label *label;
703 unsigned long flags;
704
705 AA_BUG(!ls);
706 AA_BUG(!l);
707
708 /* check if label exists before taking lock */
709 if (!label_invalid(l)) {
710 read_lock_irqsave(&ls->lock, flags);
e23c92ae 711 label = aa_get_label(__aa_label_find(ls, l));
6bfc18ae
JJ
712 read_unlock_irqrestore(&ls->lock, flags);
713 labelstats_inc(fread);
714 if (label)
715 return label;
716 }
717
718 write_lock_irqsave(&ls->lock, flags);
709bba29 719 label = aa_get_label(__aa_label_insert(ls, l));
6bfc18ae
JJ
720 write_unlock_irqrestore(&ls->lock, flags);
721
722 return label;
723}
724
1c7d0095 725struct aa_label *aa_label_vec_find_or_create(struct aa_labelset *ls,
6bfc18ae
JJ
726 struct aa_profile **vec, int len)
727{
728 struct aa_label *label = aa_label_vec_find(ls, vec, len);
729 if (label)
730 return label;
731
732 return aa_label_vec_merge(vec, len, GFP_KERNEL);
733}
734
735/**
736 * aa_label_next_in_merge - find the next profile when merging @a and @b
737 * @I: label iterator
738 * @a: label to merge
739 * @b: label to merge
740 *
741 * Returns: next profile
742 * else null if no more profiles
743 */
744struct aa_profile *aa_label_next_in_merge(struct label_it *I,
745 struct aa_label *a,
746 struct aa_label *b)
747{
748 AA_BUG(!a);
749 AA_BUG(!b);
750 AA_BUG(!I);
751 AA_BUG(I->i < 0);
752 AA_BUG(I->i > a->size);
753 AA_BUG(I->j < 0);
754 AA_BUG(I->j > b->size);
755
756 if (I->i < a->size) {
757 if (I->j < b->size) {
758 int res = profile_cmp(a->ent[I->i], b->ent[I->j]);
759 if (res > 0)
760 return b->ent[(I->j)++];
761 if (res == 0)
762 (I->j)++;
763 }
764
765 return a->ent[(I->i)++];
766 }
767
768 if (I->j < b->size)
769 return b->ent[(I->j)++];
770
771 return NULL;
772}
773
774/**
775 * label_merge_cmp - cmp of @a merging with @b against @z for set ordering
776 * @a: label to merge then compare (NOT NULL)
777 * @b: label to merge then compare (NOT NULL)
778 * @z: label to compare merge against (NOT NULL)
779 *
780 * Assumes: using the most recent versions of @a, @b, and @z
781 *
782 * Returns: <0 if a < b
783 * ==0 if a == b
784 * >0 if a > b
785 */
786static int label_merge_cmp(struct aa_label *a, struct aa_label *b,
787 struct aa_label *z)
788{
789 struct aa_profile *p = NULL;
790 struct label_it i = { };
791 int k;
792
793 AA_BUG(!a);
794 AA_BUG(!b);
795 AA_BUG(!z);
796
797 for (k = 0;
798 k < z->size && (p = aa_label_next_in_merge(&i, a, b));
799 k++) {
800 int res = profile_cmp(p, z->ent[k]);
801
802 if (res != 0)
803 return res;
804 }
805
806 if (p)
807 return 1;
808 else if (k < z->size)
809 return -1;
810 return 0;
811}
812
813#if 0
814/**
815 * label_merge_len - find the length of the merge of @a and @b
816 * @a: label to merge (NOT NULL)
817 * @b: label to merge (NOT NULL)
818 *
819 * Assumes: using newest versions of labels @a and @b
820 *
821 * Returns: length of a label vector for merge of @a and @b
822 */
823static int label_merge_len(struct aa_label *a, struct aa_label *b)
824{
825 int len = a->size + b->size;
826 int i, j;
827
828 AA_BUG(!a);
829 AA_BUG(!b);
830
831 /* find entries in common and remove from count */
832 for (i = j = 0; i < a->size && j < b->size; ) {
833 int res = profile_cmp(a->ent[i], b->ent[j]);
834 if (res == 0) {
835 len--;
836 i++;
837 j++;
838 } else if (res < 0)
839 i++;
840 else
841 j++;
842 }
843
844 return len;
845}
846#endif
847
848/**
849 * aa_sort_and_merge_profiles - canonical sort and merge a list of profiles
850 * @n: number of refcounted profiles in the list (@n > 0)
851 * @ps: list of profiles to sort and merge
852 *
853 * Returns: the number of duplicates eliminated == references put
854 */
855static int aa_sort_and_merge_profiles(int n, struct aa_profile **ps)
856{
857 int i, dups = 0;
858
859 AA_BUG(n < 1);
860 AA_BUG(!ps);
861
862 /* label lists are usually small so just use insertion sort */
863 for (i = 1; i < n; i++) {
864 struct aa_profile *tmp = ps[i];
865 int pos, j;
866
867 for (pos = i - 1 - dups; pos >= 0; pos--) {
868 int res = profile_cmp(ps[pos], tmp);
869 if (res == 0) {
870 aa_put_profile(tmp);
871 dups++;
872 goto continue_outer;
873 } else if (res < 0)
874 break;
875 }
876 pos++;
877
878 for (j = i - dups; j > pos; j--)
879 ps[j] = ps[j - 1];
880 ps[pos] = tmp;
881 continue_outer:
882 ; /* sigh empty statement required after the label */
883 }
884
885 return dups;
886}
887
888/**
709bba29 889 * __label_merge - create a new label by merging @a and @b
6bfc18ae
JJ
890 * @l: preallocated label to merge into (NOT NULL)
891 * @a: label to merge with @b (NOT NULL)
892 * @b: label to merge with @a (NOT NULL)
893 *
894 * Returns: ref counted label either l if merge is unique
895 * a if b is a subset of a
896 * b if a is a subset of b
897 *
898 * NOTE: will not use l if the merge results in l == a or b
899 *
900 * Must be used within labelset write lock to avoid racing with
901 * label invalidation.
902 */
709bba29
JJ
903static struct aa_label *__label_merge(struct aa_label *l, struct aa_label *a,
904 struct aa_label *b)
6bfc18ae
JJ
905{
906 struct aa_profile *next;
907 struct label_it i;
908 int k = 0, invcount = 0;
909
910 AA_BUG(!a);
911 AA_BUG(a->size < 0);
912 AA_BUG(!b);
913 AA_BUG(b->size < 0);
914 AA_BUG(!l);
915 AA_BUG(l->size < a->size + b->size);
916
7e972668
JJ
917 if (a == b)
918 return aa_get_label(a);
919
6bfc18ae
JJ
920 label_for_each_in_merge(i, a, b, next) {
921 if (PROFILE_INVALID(next)) {
922 l->ent[k] = aa_get_newest_profile(next);
923 if (next->label.replacedby !=
924 l->ent[k]->label.replacedby)
925 invcount++;
926 k++;
927 } else
928 l->ent[k++] = aa_get_profile(next);
929 }
930 /* set to actual size which is <= allocated len */
931 l->size = k;
932 l->ent[k] = NULL;
933
934 if (invcount) {
935 l->size -= aa_sort_and_merge_profiles(l->size, &l->ent[0]);
709bba29
JJ
936 if (label_profiles_unconfined(l))
937 l->flags |= FLAG_UNCONFINED;
938 } else {
939 /* merge is same as at least one of the labels */
6bfc18ae
JJ
940 if (k == a->size)
941 return aa_get_label(a);
942 else if (k == b->size)
943 return aa_get_label(b);
709bba29
JJ
944
945 l->flags |= a->flags & b->flags & FLAG_UNCONFINED;
6bfc18ae 946 }
e23c92ae
JJ
947
948 return aa_get_label(l);
6bfc18ae
JJ
949}
950
951/**
952 * labelset_of_merge - find into which labelset a merged label should be inserted
953 * @a: label to merge and insert
954 * @b: label to merge and insert
955 *
956 * Returns: labelset that the merged label should be inserted into
957 */
958static struct aa_labelset *labelset_of_merge(struct aa_label *a, struct aa_label *b)
959{
960 struct aa_namespace *nsa = labels_ns(a);
961 struct aa_namespace *nsb = labels_ns(b);
962
963 if (ns_cmp(nsa, nsb) <= 0)
964 return &nsa->labels;
965 return &nsb->labels;
966}
967
968/**
969 * __aa_label_find_merge - find label that is equiv to merge of @a and @b
970 * @ls: set of labels to search (NOT NULL)
971 * @a: label to merge with @b (NOT NULL)
972 * @b: label to merge with @a (NOT NULL)
973 *
974 * Requires: read_lock held
975 *
e23c92ae 976 * Returns: unref counted label that is equiv to merge of @a and @b
6bfc18ae
JJ
977 * else NULL if merge of @a and @b is not in set
978 */
979static struct aa_label *__aa_label_find_merge(struct aa_labelset *ls,
980 struct aa_label *a,
981 struct aa_label *b)
982{
983 struct rb_node *node;
984
985 AA_BUG(!ls);
986 AA_BUG(!a);
987 AA_BUG(!b);
988
989 if (a == b)
990 return __aa_label_find(ls, a);
991
992 node = ls->root.rb_node;
993 while (node) {
994 struct aa_label *this = container_of(node, struct aa_label,
995 node);
996 int result = label_merge_cmp(a, b, this);
997
998 if (result < 0)
999 node = node->rb_left;
1000 else if (result > 0)
1001 node = node->rb_right;
1002 else
e23c92ae 1003 return this;
6bfc18ae
JJ
1004 }
1005
1006 return NULL;
1007}
1008
1009
1010/**
1011 * __aa_label_find_merge - find label that is equiv to merge of @a and @b
1012 * @a: label to merge with @b (NOT NULL)
1013 * @b: label to merge with @a (NOT NULL)
1014 *
1015 * Requires: labels be fully constructed with a valid ns
1016 *
1017 * Returns: ref counted label that is equiv to merge of @a and @b
1018 * else NULL if merge of @a and @b is not in set
1019 */
1020struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b)
1021{
1022 struct aa_labelset *ls;
1023 struct aa_label *label, *ar = NULL, *br = NULL;
1024 unsigned long flags;
1025
1026 AA_BUG(!a);
1027 AA_BUG(!b);
1028
1029 ls = labelset_of_merge(a, b);
1030 read_lock_irqsave(&ls->lock, flags);
1031 if (label_invalid(a))
1032 a = ar = aa_get_newest_label(a);
1033 if (label_invalid(b))
1034 b = br = aa_get_newest_label(b);
e23c92ae 1035 label = aa_get_label(__aa_label_find_merge(ls, a, b));
6bfc18ae
JJ
1036 read_unlock_irqrestore(&ls->lock, flags);
1037 aa_put_label(ar);
1038 aa_put_label(br);
1039 labelsetstats_inc(ls, msread);
1040
1041 return label;
1042}
1043
1044/**
1045 * aa_label_merge - attempt to insert new merged label of @a and @b
1046 * @ls: set of labels to insert label into (NOT NULL)
1047 * @a: label to merge with @b (NOT NULL)
1048 * @b: label to merge with @a (NOT NULL)
1049 * @gfp: memory allocation type
1050 *
1051 * Requires: caller to hold valid refs on @a and @b
1052 * labels be fully constructed with a valid ns
1053 *
1054 * Returns: ref counted new label if successful in inserting merge of a & b
1055 * else ref counted equivalent label that is already in the set.
1056 * else NULL if could not create label (-ENOMEM)
1057 */
1058struct aa_label *aa_label_merge(struct aa_label *a, struct aa_label *b,
1059 gfp_t gfp)
1060{
1061 struct aa_label *label = NULL;
1062 struct aa_labelset *ls;
1063 unsigned long flags;
1064
1065 AA_BUG(!a);
1066 AA_BUG(!b);
1067
1068 if (a == b)
1069 return aa_get_newest_label(a);
1070
1071 ls = labelset_of_merge(a, b);
1072
1073 /* TODO: enable when read side is lockless
1074 * check if label exists before taking locks
1075 if (!label_invalid(a) && !label_invalid(b))
1076 label = aa_label_find_merge(a, b);
1077 */
1078
1079 if (!label) {
709bba29 1080 struct aa_label *new, *l;
6bfc18ae
JJ
1081
1082 a = aa_get_newest_label(a);
1083 b = aa_get_newest_label(b);
1084
1085 /* could use label_merge_len(a, b), but requires double
1086 * comparison for small savings
1087 */
f126fd25 1088 new = aa_label_alloc(a->size + b->size, gfp);
6bfc18ae 1089 if (!new)
03c5aa50 1090 return NULL;
93e7aa83 1091
6bfc18ae 1092 write_lock_irqsave(&ls->lock, flags);
709bba29
JJ
1093 l = __label_merge(new, a, b);
1094 if (l != new) {
7e972668
JJ
1095 /* new may not be fully setup so no put_label */
1096 aa_label_free(new);
1097 new = NULL;
1098 }
709bba29
JJ
1099 if (!(l->flags & FLAG_IN_TREE))
1100 label = aa_get_label(__aa_label_insert(ls, l));
1101 write_unlock_irqrestore(&ls->lock, flags);
6bfc18ae 1102 aa_put_label(new);
709bba29 1103 aa_put_label(l);
6bfc18ae
JJ
1104 aa_put_label(a);
1105 aa_put_label(b);
1106 }
1107
1108 return label;
1109}
1110
1111/* requires sort and merge done first */
1112struct aa_label *aa_label_vec_merge(struct aa_profile **vec, int len,
1113 gfp_t gfp)
1114{
1115 struct aa_label *label = NULL;
1116 struct aa_labelset *ls;
1117 unsigned long flags;
1118 struct aa_label *new;
1119 int i;
1120
1121 AA_BUG(!vec);
1122
1123 if (len == 1)
1124 return aa_get_label(&vec[0]->label);
1125
1126 ls = labels_set(&vec[len - 1]->label);
1127
1128 /* TODO: enable when read side is lockless
1129 * check if label exists before taking locks
1130 */
f126fd25 1131 new = aa_label_alloc(len, gfp);
6bfc18ae
JJ
1132 if (!new)
1133 return NULL;
1134
8812fb2d 1135 write_lock_irqsave(&ls->lock, flags);
6bfc18ae
JJ
1136 for (i = 0; i < len; i++) {
1137 new->ent[i] = aa_get_profile(vec[i]);
709bba29 1138 label = __aa_label_insert(ls, new);
e23c92ae
JJ
1139 if (label != new) {
1140 aa_get_label(label);
1141 /* not fully constructed don't put */
1142 aa_label_free(new);
1143 }
6bfc18ae
JJ
1144 }
1145 write_unlock_irqrestore(&ls->lock, flags);
1146
1147 return label;
1148}
1149
1150/**
1151 * aa_update_label_name - update a label to have a stored name
1152 * @ns: ns being viewed from (NOT NULL)
1153 * @label: label to update (NOT NULL)
1154 * @gfp: type of memory allocation
1155 *
1156 * Requires: labels_set(label) not locked in caller
1157 *
1158 * note: only updates the label name if it does not have a name already
1159 * and if it is in the labelset
1160 */
1161bool aa_update_label_name(struct aa_namespace *ns, struct aa_label *label,
1162 gfp_t gfp)
1163{
1164 struct aa_labelset *ls;
1165 unsigned long flags;
1166 char __counted *name;
1167 bool res = false;
1168
1169 AA_BUG(!ns);
1170 AA_BUG(!label);
1171
1172 if (label->hname || labels_ns(label) != ns)
1173 return res;
1174
1175 if (aa_label_acntsprint(&name, ns, label, false, gfp) == -1)
1176 return res;
1177
1178 ls = labels_set(label);
1179 write_lock_irqsave(&ls->lock, flags);
1180 if (!label->hname && label->flags & FLAG_IN_TREE) {
1181 label->hname = name;
1182 res = true;
1183 } else
1184 aa_put_str(name);
1185 write_unlock_irqrestore(&ls->lock, flags);
1186
1187 return res;
1188}
1189
1190/* cached label name is present and visible
1191 * @label->hname only exists if label is namespace hierachical */
1192static inline bool label_name_visible(struct aa_namespace *ns,
1193 struct aa_label *label)
1194{
1195 if (label->hname && labels_ns(label) == ns)
1196 return true;
1197
1198 return false;
1199}
1200
1201/* helper macro for snprint routines */
1202#define update_for_len(total, len, size, str) \
1203do { \
1204 AA_BUG(len < 0); \
1205 total += len; \
1206 len = min(len, size); \
1207 size -= len; \
1208 str += len; \
1209} while (0)
1210
1211/**
1212 * aa_modename_snprint - print the mode name of a profile or label to a buffer
1213 * @str: buffer to write to (MAY BE NULL if @size == 0)
1214 * @size: size of buffer
d0f3986b 1215 * @ns: namespace profile is being viewed from (NOT NULL)
6bfc18ae
JJ
1216 * @label: label to print the mode of (NOT NULL)
1217 *
1218 * Returns: size of name written or would be written if larger than
1219 * available buffer
1220 *
1221 * Note: will print every mode name visible (mode1)(mode2)(mode3)
1222 * this is likely not what is desired for most interfaces
1223 * use aa_mode_snprint to get the standard mode format
1224 */
1225static int aa_modename_snprint(char *str, size_t size, struct aa_namespace *ns,
1226 struct aa_label *label)
1227{
1228 struct aa_profile *profile;
1229 struct label_it i;
1230 int total = 0;
1231 size_t len;
1232
1233 label_for_each(i, label, profile) {
1234 const char *modestr;
1235 if (!aa_ns_visible(ns, profile->ns))
1236 continue;
1237 /* no mode for 'unconfined' */
1238 if (profile_unconfined(profile) &&
1239 profile == profile->ns->unconfined)
1240 break;
1241 modestr = aa_profile_mode_names[profile->mode];
1242 len = snprintf(str, size, "(%s)", modestr);
1243 update_for_len(total, len, size, str);
1244 }
1245
1246 return total;
1247}
1248
1249/**
1250 * aa_modechr_snprint - print the mode chr of a profile or labels to a buffer
1251 * @str: buffer to write to (MAY BE NULL if @size == 0)
1252 * @size: size of buffer
d0f3986b 1253 * @ns: namespace profile is being viewed from (NOT NULL)
6bfc18ae
JJ
1254 * @label: label to print the mode chr of (NOT NULL)
1255 *
1256 * Returns: size of mode string written or would be written if larger than
1257 * available buffer
1258 *
1259 * Note: will print the chr of every visible profile (123)
1260 * this is likely not what is desired for most interfaces
1261 * use aa_mode_snprint to get the standard mode format
1262 */
1263static int aa_modechr_snprint(char *str, size_t size, struct aa_namespace *ns,
1264 struct aa_label *label)
1265{
1266 struct aa_profile *profile;
1267 struct label_it i;
1268 int total = 0;
1269 size_t len;
1270
1271 len = snprintf(str, size, "(");
1272 update_for_len(total, len, size, str);
1273 label_for_each(i, label, profile) {
1274 const char *modestr;
1275 if (!aa_ns_visible(ns, profile->ns))
1276 continue;
1277 modestr = aa_profile_mode_names[profile->mode];
1278 /* just the first char of the modestr */
1279 len = snprintf(str, size, "%c", *modestr);
1280 update_for_len(total, len, size, str);
1281 }
1282 len = snprintf(str, size, ")");
1283 update_for_len(total, len, size, str);
1284
1285 return total;
1286}
1287
1288/**
1289 * aa_mode_snprint - print the mode of a profile or label to a buffer
1290 * @str: buffer to write to (MAY BE NULL if @size == 0)
1291 * @size: size of buffer
d0f3986b 1292 * @ns: namespace profile is being viewed from (NOT NULL)
6bfc18ae
JJ
1293 * @label: label to print the mode of (NOT NULL)
1294 * @count: number of label entries to be printed (<= 0 if unknown)
1295 *
1296 * Returns: size of name written or would be written if larger than
1297 * available buffer
1298 *
1299 * Note: dynamically switches between mode name, and mode char format as
1300 * appropriate
1301 * will not print anything if the label is not visible
1302 */
1303static int aa_mode_snprint(char *str, size_t size, struct aa_namespace *ns,
1304 struct aa_label *label, int count)
1305{
1306 struct aa_profile *profile;
1307 struct label_it i;
1308
1309 if (count <= 0) {
1310 count = 0;
1311 label_for_each(i, label, profile) {
1312 if (aa_ns_visible(ns, profile->ns))
1313 count++;
1314 }
1315 }
1316
1317 if (count == 0)
1318 return 0;
1319
1320 if (count == 1)
1321 return aa_modename_snprint(str, size, ns, label);
1322
1323 return aa_modechr_snprint(str, size, ns, label);
1324}
1325
1326/**
1327 * aa_snprint_profile - print a profile name to a buffer
1328 * @str: buffer to write to. (MAY BE NULL if @size == 0)
1329 * @size: size of buffer
d0f3986b 1330 * @ns: namespace profile is being viewed from (NOT NULL)
6bfc18ae
JJ
1331 * @profile: profile to view (NOT NULL)
1332 * @mode: whether to include the mode string
1333 *
1334 * Returns: size of name written or would be written if larger than
1335 * available buffer
1336 *
1337 * Note: will not print anything if the profile is not visible
1338 */
1339int aa_profile_snprint(char *str, size_t size, struct aa_namespace *ns,
1340 struct aa_profile *profile, bool mode)
1341{
d0f3986b 1342 const char *ns_name = aa_ns_name(ns, profile->ns);
6bfc18ae
JJ
1343
1344 AA_BUG(!str && size != 0);
d0f3986b 1345 AA_BUG(!ns);
6bfc18ae
JJ
1346 AA_BUG(!profile);
1347
1348 if (!ns_name)
1349 return 0;
1350
1351 if (mode && profile != profile->ns->unconfined) {
1352 const char *modestr = aa_profile_mode_names[profile->mode];
1353 if (strlen(ns_name))
1354 return snprintf(str, size, ":%s://%s (%s)", ns_name,
1355 profile->base.hname, modestr);
1356 return snprintf(str, size, "%s (%s)", profile->base.hname,
1357 modestr);
1358 }
1359
1360 if (strlen(ns_name))
1361 return snprintf(str, size, ":%s://%s", ns_name,
1362 profile->base.hname);
1363 return snprintf(str, size, "%s", profile->base.hname);
1364}
1365
1366/**
1367 * aa_label_snprint - print a label name to a string buffer
1368 * @str: buffer to write to. (MAY BE NULL if @size == 0)
1369 * @size: size of buffer
d0f3986b 1370 * @ns: namespace profile is being viewed from (NOT NULL)
6bfc18ae
JJ
1371 * @label: label to view (NOT NULL)
1372 * @mode: whether to include the mode string
1373 *
1374 * Returns: size of name written or would be written if larger than
1375 * available buffer
1376 *
1377 * Note: labels do not have to be strictly hierarchical to the ns as
1378 * objects may be shared across different namespaces and thus
1379 * pickup labeling from each ns. If a particular part of the
1380 * label is not visible it will just be excluded. And if none
1381 * of the label is visible "---" will be used.
1382 */
1383int aa_label_snprint(char *str, size_t size, struct aa_namespace *ns,
1384 struct aa_label *label, bool mode)
1385{
1386 struct aa_profile *profile;
1387 struct label_it i;
1388 int count = 0, total = 0;
1389 size_t len;
1390
1391 AA_BUG(!str && size != 0);
d0f3986b 1392 AA_BUG(!ns);
6bfc18ae
JJ
1393 AA_BUG(!label);
1394
1395 label_for_each(i, label, profile) {
1396 if (aa_ns_visible(ns, profile->ns)) {
1397 if (count > 0) {
1398 len = snprintf(str, size, "//&");
1399 update_for_len(total, len, size, str);
1400 }
1401 len = aa_profile_snprint(str, size, ns, profile, false);
1402 update_for_len(total, len, size, str);
1403 count++;
1404 }
1405 }
1406
1407 if (count == 0)
1408 return snprintf(str, size, aa_hidden_ns_name);
1409
1410 /* count == 1 && ... is for backwards compat where the mode
1411 * is not displayed for 'unconfined' in the current ns
1412 */
1413 if (mode &&
1414 !(count == 1 && labels_ns(label) == ns &&
1415 labels_profile(label) == ns->unconfined)) {
1416 len = snprintf(str, size, " ");
1417 update_for_len(total, len, size, str);
1418 len = aa_mode_snprint(str, size, ns, label, count);
1419 update_for_len(total, len, size, str);
1420 }
1421
1422 return total;
1423}
1424#undef update_for_len
1425
1426/**
1427 * aa_label_asprint - allocate a string buffer and print label into it
1428 * @strp: Returns - the allocated buffer with the label name. (NOT NULL)
d0f3986b 1429 * @ns: namespace profile is being viewed from (NOT NULL)
6bfc18ae
JJ
1430 * @label: label to view (NOT NULL)
1431 * @mode: whether to include the mode string
1432 * @gfp: kernel memory allocation type
1433 *
1434 * Returns: size of name written or would be written if larger than
1435 * available buffer
1436 */
1437int aa_label_asprint(char **strp, struct aa_namespace *ns,
1438 struct aa_label *label, bool mode, gfp_t gfp)
1439{
1440 int size;
1441
1442 AA_BUG(!strp);
d0f3986b 1443 AA_BUG(!ns);
6bfc18ae
JJ
1444 AA_BUG(!label);
1445
1446 size = aa_label_snprint(NULL, 0, ns, label, mode);
1447 if (size < 0)
1448 return size;
1449
1450 *strp = kmalloc(size + 1, gfp);
1451 if (!*strp)
1452 return -ENOMEM;
1453 return aa_label_snprint(*strp, size + 1, ns, label, mode);
1454}
1455
1456/**
1457 * aa_label_acntsprint - allocate a __counted string buffer and print label
1458 * @strp: buffer to write to. (MAY BE NULL if @size == 0)
d0f3986b 1459 * @ns: namespace profile is being viewed from (NOT NULL)
6bfc18ae
JJ
1460 * @label: label to view (NOT NULL)
1461 * @mode: whether to include the mode string
1462 * @gfp: kernel memory allocation type
1463 *
1464 * Returns: size of name written or would be written if larger than
1465 * available buffer
1466 */
1467int aa_label_acntsprint(char __counted **strp, struct aa_namespace *ns,
1468 struct aa_label *label, bool mode, gfp_t gfp)
1469{
1470 int size;
1471
1472 AA_BUG(!strp);
d0f3986b 1473 AA_BUG(!ns);
6bfc18ae
JJ
1474 AA_BUG(!label);
1475
1476 size = aa_label_snprint(NULL, 0, ns, label, mode);
1477 if (size < 0)
1478 return size;
1479
1480 *strp = aa_str_alloc(size + 1, gfp);
1481 if (!*strp)
1482 return -ENOMEM;
1483 return aa_label_snprint(*strp, size + 1, ns, label, mode);
1484}
1485
1486
1487void aa_label_audit(struct audit_buffer *ab, struct aa_namespace *ns,
1488 struct aa_label *label, bool mode, gfp_t gfp)
1489{
1490 const char *str;
1491 char *name = NULL;
1492 int len;
1493
1494 AA_BUG(!ab);
d0f3986b 1495 AA_BUG(!ns);
6bfc18ae
JJ
1496 AA_BUG(!label);
1497
1498 if (label_name_visible(ns, label)) {
1499 str = (char *) label->hname;
1500 len = strlen(str);
1501 } else {
1502 labelstats_inc(audit_name_alloc);
1503 len = aa_label_asprint(&name, ns, label, mode, gfp);
1504 if (len == -1) {
1505 labelstats_inc(audit_name_fail);
1506 AA_DEBUG("label print error");
1507 return;
1508 }
1509 str = name;
1510 }
1511
1512 if (audit_string_contains_control(str, len))
1513 audit_log_n_hex(ab, str, len);
1514 else
1515 audit_log_n_string(ab, str, len);
1516
1517 kfree(name);
1518}
1519
1520void aa_label_seq_print(struct seq_file *f, struct aa_namespace *ns,
1521 struct aa_label *label, bool mode, gfp_t gfp)
1522{
1523 AA_BUG(!f);
d0f3986b 1524 AA_BUG(!ns);
6bfc18ae
JJ
1525 AA_BUG(!label);
1526
1527 if (!label_name_visible(ns, label)) {
1528 char *str;
1529 int len;
1530
1531 labelstats_inc(seq_print_name_alloc);
1532 len = aa_label_asprint(&str, ns, label, mode, gfp);
1533 if (len == -1) {
1534 labelstats_inc(seq_print_name_fail);
1535 AA_DEBUG("label print error");
1536 return;
1537 }
1538 seq_printf(f, "%s", str);
1539 kfree(str);
1540 } else
1541 seq_printf(f, "%s", label->hname);
1542}
1543
1544void aa_label_printk(struct aa_namespace *ns, struct aa_label *label, bool mode,
1545 gfp_t gfp)
1546{
1547 char *str;
1548 int len;
1549
d0f3986b 1550 AA_BUG(!ns);
6bfc18ae
JJ
1551 AA_BUG(!label);
1552
1553 if (!label_name_visible(ns, label)) {
1554 labelstats_inc(printk_name_alloc);
1555 len = aa_label_asprint(&str, ns, label, mode, gfp);
1556 if (len == -1) {
1557 labelstats_inc(printk_name_fail);
1558 AA_DEBUG("label print error");
1559 return;
1560 }
1561 printk("%s", str);
1562 kfree(str);
1563 } else
1564 printk("%s", label->hname);
1565}
1566
1567static int label_count_str_entries(const char *str)
1568{
1569 const char *split;
1570 int count = 1;
1571
1572 AA_BUG(!str);
1573
1574 for (split = strstr(str, "//&"); split; split = strstr(str, "//&")) {
1575 count++;
1576 str = split + 3;
1577 }
1578
1579 return count;
1580}
1581
1582/**
1583 * aa_label_parse - parse, validate and convert a text string to a label
1584 * @base: base label to use for lookups (NOT NULL)
1585 * @str: null terminated text string (NOT NULL)
1586 * @gfp: allocation type
1587 * @create: true if should create compound labels if they don't exist
1588 *
1589 * Returns: the matching refcounted label if present
1590 * else ERRPTR
1591 */
1592struct aa_label *aa_label_parse(struct aa_label *base, char *str, gfp_t gfp,
1593 bool create)
1594{
1595 DEFINE_PROFILE_VEC(vec, tmp);
1596 struct aa_label *l;
1597 int i, len, error;
1598 char *split;
1599
1600 AA_BUG(!base);
1601 AA_BUG(!str);
1602
1603 len = label_count_str_entries(str);
1604 error = aa_setup_profile_vec(vec, tmp, len);
1605 if (error)
1606 return ERR_PTR(error);
1607
1608 for (split = strstr(str, "//&"), i = 0; split && i < len; i++) {
1609 vec[i] = aa_fqlookupn_profile(base, str, split - str);
1610 if (!vec[i])
1611 goto fail;
1612 str = split + 3;
1613 split = strstr(str, "//&");
1614 }
1615 vec[i] = aa_fqlookupn_profile(base, str, strlen(str));
1616 if (!vec[i])
1617 goto fail;
1618 if (len == 1)
1619 /* no need to free vec as len < LOCAL_VEC_ENTRIES */
1620 return &vec[0]->label;
1621
1622 i = aa_sort_and_merge_profiles(len, vec);
1623 len -= i;
1624
1625 if (create)
1626 l = aa_label_vec_find_or_create(labels_set(base), vec, len);
1627 else
1628 l = aa_label_vec_find(labels_set(base), vec, len);
1629 if (!l)
1630 l = ERR_PTR(-ENOENT);
1631
1632out:
1633 /* use adjusted len from after sort_and_merge, not original */
1634 aa_cleanup_profile_vec(vec, tmp, len);
1635 return l;
1636
1637fail:
1638 l = ERR_PTR(-ENOENT);
1639 goto out;
1640}
1641
1642
1643/**
1644 * aa_labelset_destroy - remove all labels from the label set
1645 * @ls: label set to cleanup (NOT NULL)
1646 *
1647 * Labels that are removed from the set may still exist beyond the set
1648 * being destroyed depending on their reference counting
1649 */
1650void aa_labelset_destroy(struct aa_labelset *ls)
1651{
1652 struct rb_node *node;
1653 unsigned long flags;
1654
1655 AA_BUG(!ls);
1656
1657 write_lock_irqsave(&ls->lock, flags);
1658 for (node = rb_first(&ls->root); node; node = rb_first(&ls->root)) {
1659 struct aa_label *this = rb_entry(node, struct aa_label, node);
67194e9d 1660 __aa_label_remove(ls, this);
6bfc18ae
JJ
1661 }
1662 write_unlock_irqrestore(&ls->lock, flags);
1663}
1664
1665/*
1666 * @ls: labelset to init (NOT NULL)
1667 */
1668void aa_labelset_init(struct aa_labelset *ls)
1669{
1670 AA_BUG(!ls);
1671
1672 rwlock_init(&ls->lock);
1673 ls->root = RB_ROOT;
1674 labelstats_init(&ls);
1675}
1676
1677static struct aa_label *labelset_next_invalid(struct aa_labelset *ls)
1678{
1679 struct aa_label *label;
1680 struct rb_node *node;
1681 unsigned long flags;
1682
1683 AA_BUG(!ls);
1684
1685 read_lock_irqsave(&ls->lock, flags);
1686
1687 __labelset_for_each(ls, node) {
17aa743a
JJ
1688 struct aa_profile *p;
1689 struct label_it i;
1690
6bfc18ae 1691 label = rb_entry(node, struct aa_label, node);
e23c92ae 1692 if (label_invalid(label))
6bfc18ae
JJ
1693 goto out;
1694
e23c92ae
JJ
1695 label_for_each(i, label, p) {
1696 if (PROFILE_INVALID(p))
1697 goto out;
1698 }
6bfc18ae
JJ
1699 }
1700 label = NULL;
1701
1702out:
e23c92ae 1703 aa_get_label(label);
6bfc18ae
JJ
1704 read_unlock_irqrestore(&ls->lock, flags);
1705
1706 return label;
1707}
1708
1709/**
1710 * __label_update - insert updated version of @label into labelset
1711 * @label - the label to update/repace
1712 *
1713 * Returns: new label that is up to date
1714 * else NULL on failure
1715 *
1716 * Requires: @ns lock be held
1717 *
1718 * Note: worst case is the stale @label does not get updated and has
1719 * to be updated at a later time.
1720 */
1721static struct aa_label *__label_update(struct aa_label *label)
1722{
1723 struct aa_label *l, *tmp;
1724 struct aa_labelset *ls;
1725 struct aa_profile *p;
1726 struct label_it i;
1727 unsigned long flags;
1728 int invcount = 0;
1729
1730 AA_BUG(!label);
1731 AA_BUG(!mutex_is_locked(&labels_ns(label)->lock));
1732
f126fd25 1733 l = aa_label_alloc(label->size, GFP_KERNEL);
6bfc18ae
JJ
1734 if (!l)
1735 return NULL;
1736
f126fd25 1737 if (!label->replacedby) {
8ac21d39 1738 struct aa_replacedby *r = aa_alloc_replacedby(l);
f126fd25
JJ
1739 if (!r) {
1740 aa_put_label(l);
1741 return NULL;
1742 }
1743 /* only label update will set replacedby so ns lock is enough */
1744 label->replacedby = r;
1745 }
1746
6bfc18ae
JJ
1747 /* while holding the ns_lock will stop profile replacement, removal,
1748 * and label updates, label merging and removal can be occuring
1749 */
a4d2e2f9 1750
6bfc18ae
JJ
1751 ls = labels_set(label);
1752 write_lock_irqsave(&ls->lock, flags);
a4d2e2f9
JJ
1753 /* circular ref only broken by replace or remove */
1754 l->replacedby = aa_get_replacedby(label->replacedby);
1755 __aa_update_replacedby(label, l);
1756
6bfc18ae
JJ
1757 label_for_each(i, label, p) {
1758 l->ent[i.i] = aa_get_newest_profile(p);
1759 if (&l->ent[i.i]->label.replacedby != &p->label.replacedby)
1760 invcount++;
1761 }
1762
1763 /* updated label invalidated by being removed/renamed from labelset */
1764 if (invcount) {
1765 l->size -= aa_sort_and_merge_profiles(l->size, &l->ent[0]);
7e972668 1766 if (labels_set(label) == labels_set(l)) {
a4fb04fb 1767 AA_BUG(__aa_label_remove_and_insert(labels_set(label), label, l) != l);
7e972668 1768 } else {
8caa4d52 1769 aa_label_remove(labels_set(label), label);
7e972668 1770 goto other_ls_insert;
6bfc18ae 1771 }
7e972668 1772 } else {
0fe6d20b 1773 AA_BUG(labels_ns(label) != labels_ns(l));
a4fb04fb 1774 AA_BUG(__aa_label_remove_and_insert(labels_set(label), label, l) != l);
7e972668 1775 }
6bfc18ae 1776 write_unlock_irqrestore(&ls->lock, flags);
a4d2e2f9 1777
7e972668 1778 return l;
6bfc18ae 1779
7e972668
JJ
1780other_ls_insert:
1781 write_unlock_irqrestore(&ls->lock, flags);
1782 tmp = aa_label_insert(labels_set(l), l);
1783 if (tmp != l) {
1784 aa_put_label(l);
1785 l = tmp;
2c5f23c4 1786 }
7e972668
JJ
1787
1788 return l;
6bfc18ae
JJ
1789}
1790
1791/**
1792 * __labelset_update - invalidate and update labels in @ns
1793 * @ns: namespace to update and invalidate labels in (NOT NULL)
1794 *
1795 * Requires: @ns lock be held
1796 *
1797 * Walk the labelset ensuring that all labels are up to date and valid
1798 * Any label that is outdated is replaced and by an updated version
1799 * invalidated and removed from the tree.
1800 *
1801 * If failures happen due to memory pressures then stale labels will
1802 * be left in place until the next pass.
1803 */
1804static void __labelset_update(struct aa_namespace *ns)
1805{
1806 struct aa_label *label;
1807
1808 AA_BUG(!ns);
1809 AA_BUG(!mutex_is_locked(&ns->lock));
1810
1811 do {
1812 label = labelset_next_invalid(&ns->labels);
1813 if (label) {
1814 struct aa_label *l;
1815 l = __label_update(label);
1816 aa_put_label(l);
1817 aa_put_label(label);
1818 }
1819 } while (label);
1820}
1821
1822/**
1823 * __aa_labelset_invalidate_all - invalidate labels in @ns and below
1824 * @ns: ns to start invalidation at (NOT NULL)
1825 *
1826 * Requires: @ns lock be held
1827 *
1828 * Invalidates labels based on @p in @ns and any children namespaces.
1829*/
1830void __aa_labelset_update_all(struct aa_namespace *ns)
1831{
1832 struct aa_namespace *child;
1833
1834 AA_BUG(!ns);
1835 AA_BUG(!mutex_is_locked(&ns->lock));
1836
1837 __labelset_update(ns);
1838
1839 list_for_each_entry(child, &ns->sub_ns, base.list) {
1840 mutex_lock(&child->lock);
1841 __aa_labelset_update_all(child);
1842 mutex_unlock(&child->lock);
1843 }
1844}