Lines Matching +full:in +full:- +full:tree

1 // SPDX-License-Identifier: GPL-2.0
54 * audit_tree_group->mark_mutex. Thus as long as we hold
55 * audit_tree_group->mark_mutex and check that the mark is alive by
61 * the same tree.
63 * time and used in AUDIT_TREE rule matching.
68 * tree.chunks anchors chunk.owners[].list hash_lock
69 * tree.rules anchors rule.rlist audit_filter_mutex
70 * chunk.trees anchors tree.same_root hash_lock
74 * tree is refcounted; one reference for "some rules on rules_list refer to
86 * revert - several operations have very unpleasant cleanup logics and
95 struct audit_tree *tree; in alloc_tree() local
97 tree = kmalloc(struct_size(tree, pathname, strlen(s) + 1), GFP_KERNEL); in alloc_tree()
98 if (tree) { in alloc_tree()
99 refcount_set(&tree->count, 1); in alloc_tree()
100 tree->goner = 0; in alloc_tree()
101 INIT_LIST_HEAD(&tree->chunks); in alloc_tree()
102 INIT_LIST_HEAD(&tree->rules); in alloc_tree()
103 INIT_LIST_HEAD(&tree->list); in alloc_tree()
104 INIT_LIST_HEAD(&tree->same_root); in alloc_tree()
105 tree->root = NULL; in alloc_tree()
106 strcpy(tree->pathname, s); in alloc_tree()
108 return tree; in alloc_tree()
111 static inline void get_tree(struct audit_tree *tree) in get_tree() argument
113 refcount_inc(&tree->count); in get_tree()
116 static inline void put_tree(struct audit_tree *tree) in put_tree() argument
118 if (refcount_dec_and_test(&tree->count)) in put_tree()
119 kfree_rcu(tree, head); in put_tree()
122 /* to avoid bringing the entire thing in audit.h */
123 const char *audit_tree_path(struct audit_tree *tree) in audit_tree_path() argument
125 return tree->pathname; in audit_tree_path()
132 for (i = 0; i < chunk->count; i++) { in free_chunk()
133 if (chunk->owners[i].owner) in free_chunk()
134 put_tree(chunk->owners[i].owner); in free_chunk()
141 if (atomic_long_dec_and_test(&chunk->refs)) in audit_put_chunk()
158 call_rcu(&chunk->head, __put_chunk); in audit_mark_put_chunk()
168 return audit_mark(mark)->chunk; in mark_chunk()
183 fsnotify_init_mark(&amark->mark, audit_tree_group); in alloc_mark()
184 amark->mark.mask = FS_IN_IGNORED; in alloc_mark()
185 return &amark->mark; in alloc_mark()
197 INIT_LIST_HEAD(&chunk->hash); in alloc_chunk()
198 INIT_LIST_HEAD(&chunk->trees); in alloc_chunk()
199 chunk->count = count; in alloc_chunk()
200 atomic_long_set(&chunk->refs, 1); in alloc_chunk()
202 INIT_LIST_HEAD(&chunk->owners[i].list); in alloc_chunk()
203 chunk->owners[i].index = i; in alloc_chunk()
212 /* Function to return search key in our hash from inode. */
215 /* Use address pointed to by connector->obj as the key */ in inode_to_key()
216 return (unsigned long)&inode->i_fsnotify_marks; in inode_to_key()
225 /* hash_lock & mark->group->mark_mutex is held by caller */
231 * Make sure chunk is fully initialized before making it visible in the in insert_hash()
232 * hash. Pairs with a data dependency barrier in READ_ONCE() in in insert_hash()
236 WARN_ON_ONCE(!chunk->key); in insert_hash()
237 list = chunk_hash(chunk->key); in insert_hash()
238 list_add_rcu(&chunk->hash, list); in insert_hash()
250 * We use a data dependency barrier in READ_ONCE() to make sure in audit_tree_lookup()
253 if (READ_ONCE(p->key) == key) { in audit_tree_lookup()
254 atomic_long_inc(&p->refs); in audit_tree_lookup()
261 bool audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree) in audit_tree_match() argument
264 for (n = 0; n < chunk->count; n++) in audit_tree_match()
265 if (chunk->owners[n].owner == tree) in audit_tree_match()
274 int index = p->index & ~(1U<<31); in find_chunk()
275 p -= index; in find_chunk()
286 audit_mark(mark)->chunk = chunk; in replace_mark_chunk()
288 chunk->mark = mark; in replace_mark_chunk()
290 old->mark = NULL; in replace_mark_chunk()
298 new->key = old->key; in replace_chunk()
299 list_splice_init(&old->trees, &new->trees); in replace_chunk()
300 list_for_each_entry(owner, &new->trees, same_root) in replace_chunk()
301 owner->root = new; in replace_chunk()
302 for (i = j = 0; j < old->count; i++, j++) { in replace_chunk()
303 if (!old->owners[j].owner) { in replace_chunk()
304 i--; in replace_chunk()
307 owner = old->owners[j].owner; in replace_chunk()
308 new->owners[i].owner = owner; in replace_chunk()
309 new->owners[i].index = old->owners[j].index - j + i; in replace_chunk()
313 list_replace_init(&old->owners[j].list, &new->owners[i].list); in replace_chunk()
315 replace_mark_chunk(old->mark, new); in replace_chunk()
317 * Make sure chunk is fully initialized before making it visible in the in replace_chunk()
318 * hash. Pairs with a data dependency barrier in READ_ONCE() in in replace_chunk()
322 list_replace_rcu(&old->hash, &new->hash); in replace_chunk()
327 struct audit_tree *owner = p->owner; in remove_chunk_node()
329 if (owner->root == chunk) { in remove_chunk_node()
330 list_del_init(&owner->same_root); in remove_chunk_node()
331 owner->root = NULL; in remove_chunk_node()
333 list_del_init(&p->list); in remove_chunk_node()
334 p->owner = NULL; in remove_chunk_node()
343 for (i = 0; i < chunk->count; i++) in chunk_count_trees()
344 if (chunk->owners[i].owner) in chunk_count_trees()
359 if (!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) || in untag_chunk()
366 list_del_init(&chunk->trees); in untag_chunk()
367 list_del_rcu(&chunk->hash); in untag_chunk()
396 /* Call with group->mark_mutex held, releases it */
397 static int create_chunk(struct inode *inode, struct audit_tree *tree) in create_chunk() argument
404 return -ENOMEM; in create_chunk()
411 return -ENOMEM; in create_chunk()
418 return -ENOSPC; in create_chunk()
422 if (tree->goner) { in create_chunk()
432 chunk->owners[0].index = (1U << 31); in create_chunk()
433 chunk->owners[0].owner = tree; in create_chunk()
434 get_tree(tree); in create_chunk()
435 list_add(&chunk->owners[0].list, &tree->chunks); in create_chunk()
436 if (!tree->root) { in create_chunk()
437 tree->root = chunk; in create_chunk()
438 list_add(&tree->same_root, &chunk->trees); in create_chunk()
440 chunk->key = inode_to_key(inode); in create_chunk()
450 * we get notification through ->freeing_mark callback and cleanup in create_chunk()
457 /* the first tagged inode becomes root of tree */
458 static int tag_chunk(struct inode *inode, struct audit_tree *tree) in tag_chunk() argument
468 return create_chunk(inode, tree); in tag_chunk()
478 for (n = 0; n < old->count; n++) { in tag_chunk()
479 if (old->owners[n].owner == tree) { in tag_chunk()
488 chunk = alloc_chunk(old->count + 1); in tag_chunk()
492 return -ENOMEM; in tag_chunk()
496 if (tree->goner) { in tag_chunk()
503 p = &chunk->owners[chunk->count - 1]; in tag_chunk()
504 p->index = (chunk->count - 1) | (1U<<31); in tag_chunk()
505 p->owner = tree; in tag_chunk()
506 get_tree(tree); in tag_chunk()
507 list_add(&p->list, &tree->chunks); in tag_chunk()
508 if (!tree->root) { in tag_chunk()
509 tree->root = chunk; in tag_chunk()
510 list_add(&tree->same_root, &chunk->trees); in tag_chunk()
536 audit_log_untrustedstring(ab, rule->tree->pathname); in audit_tree_log_remove_rule()
537 audit_log_key(ab, rule->filterkey); in audit_tree_log_remove_rule()
538 audit_log_format(ab, " list=%d res=1", rule->listnr); in audit_tree_log_remove_rule()
542 static void kill_rules(struct audit_context *context, struct audit_tree *tree) in kill_rules() argument
547 list_for_each_entry_safe(rule, next, &tree->rules, rlist) { in kill_rules()
550 list_del_init(&rule->rlist); in kill_rules()
551 if (rule->tree) { in kill_rules()
552 /* not a half-baked one */ in kill_rules()
554 if (entry->rule.exe) in kill_rules()
555 audit_remove_mark(entry->rule.exe); in kill_rules()
556 rule->tree = NULL; in kill_rules()
557 list_del_rcu(&entry->list); in kill_rules()
558 list_del(&entry->rule.list); in kill_rules()
559 call_rcu(&entry->rcu, audit_free_rule_rcu); in kill_rules()
565 * Remove tree from chunks. If 'tagged' is set, remove tree only from tagged
572 while (!list_empty(&victim->chunks)) { in prune_tree_chunks()
577 p = list_first_entry(&victim->chunks, struct audit_node, list); in prune_tree_chunks()
579 if (tagged && !(p->index & (1U<<31))) in prune_tree_chunks()
582 mark = chunk->mark; in prune_tree_chunks()
607 /* trim the uncommitted chunks from tree */
609 static void trim_marked(struct audit_tree *tree) in trim_marked() argument
613 if (tree->goner) { in trim_marked()
618 for (p = tree->chunks.next; p != &tree->chunks; p = q) { in trim_marked()
620 q = p->next; in trim_marked()
621 if (node->index & (1U<<31)) { in trim_marked()
623 list_add(p, &tree->chunks); in trim_marked()
628 prune_tree_chunks(tree, true); in trim_marked()
631 if (!tree->root && !tree->goner) { in trim_marked()
632 tree->goner = 1; in trim_marked()
635 kill_rules(audit_context(), tree); in trim_marked()
636 list_del_init(&tree->list); in trim_marked()
638 prune_one(tree); in trim_marked()
649 struct audit_tree *tree; in audit_remove_tree_rule() local
650 tree = rule->tree; in audit_remove_tree_rule()
651 if (tree) { in audit_remove_tree_rule()
653 list_del_init(&rule->rlist); in audit_remove_tree_rule()
654 if (list_empty(&tree->rules) && !tree->goner) { in audit_remove_tree_rule()
655 tree->root = NULL; in audit_remove_tree_rule()
656 list_del_init(&tree->same_root); in audit_remove_tree_rule()
657 tree->goner = 1; in audit_remove_tree_rule()
658 list_move(&tree->list, &prune_list); in audit_remove_tree_rule()
659 rule->tree = NULL; in audit_remove_tree_rule()
664 rule->tree = NULL; in audit_remove_tree_rule()
673 return inode_to_key(d_backing_inode(mnt->mnt_root)) == in compare_root()
684 struct audit_tree *tree; in audit_trim_trees() local
690 tree = container_of(cursor.next, struct audit_tree, list); in audit_trim_trees()
691 get_tree(tree); in audit_trim_trees()
692 list_move(&cursor, &tree->list); in audit_trim_trees()
695 err = kern_path(tree->pathname, 0, &path); in audit_trim_trees()
705 list_for_each_entry(node, &tree->chunks, list) { in audit_trim_trees()
708 node->index |= 1U<<31; in audit_trim_trees()
710 (void *)(chunk->key), in audit_trim_trees()
712 node->index &= ~(1U<<31); in audit_trim_trees()
715 trim_marked(tree); in audit_trim_trees()
718 put_tree(tree); in audit_trim_trees()
729 (rule->listnr != AUDIT_FILTER_EXIT && in audit_make_tree()
730 rule->listnr != AUDIT_FILTER_URING_EXIT) || in audit_make_tree()
732 rule->inode_f || rule->watch || rule->tree) in audit_make_tree()
733 return -EINVAL; in audit_make_tree()
734 rule->tree = alloc_tree(pathname); in audit_make_tree()
735 if (!rule->tree) in audit_make_tree()
736 return -ENOMEM; in audit_make_tree()
740 void audit_put_tree(struct audit_tree *tree) in audit_put_tree() argument
742 put_tree(tree); in audit_put_tree()
747 return tag_chunk(d_backing_inode(mnt->mnt_root), arg); in tag_mount()
770 list_del_init(&victim->list); in prune_tree_thread()
794 return -ENOMEM; in audit_launch_prune()
802 struct audit_tree *seed = rule->tree, *tree; in audit_add_tree_rule() local
807 rule->tree = NULL; in audit_add_tree_rule()
808 list_for_each_entry(tree, &tree_list, list) { in audit_add_tree_rule()
809 if (!strcmp(seed->pathname, tree->pathname)) { in audit_add_tree_rule()
811 rule->tree = tree; in audit_add_tree_rule()
812 list_add(&rule->rlist, &tree->rules); in audit_add_tree_rule()
816 tree = seed; in audit_add_tree_rule()
817 list_add(&tree->list, &tree_list); in audit_add_tree_rule()
818 list_add(&rule->rlist, &tree->rules); in audit_add_tree_rule()
819 /* do not set rule->tree yet */ in audit_add_tree_rule()
828 err = kern_path(tree->pathname, 0, &path); in audit_add_tree_rule()
838 get_tree(tree); in audit_add_tree_rule()
839 err = iterate_mounts(tag_mount, tree, mnt); in audit_add_tree_rule()
845 list_for_each_entry(node, &tree->chunks, list) in audit_add_tree_rule()
846 node->index &= ~(1U<<31); in audit_add_tree_rule()
849 trim_marked(tree); in audit_add_tree_rule()
854 if (list_empty(&rule->rlist)) { in audit_add_tree_rule()
855 put_tree(tree); in audit_add_tree_rule()
856 return -ENOENT; in audit_add_tree_rule()
858 rule->tree = tree; in audit_add_tree_rule()
859 put_tree(tree); in audit_add_tree_rule()
864 list_del_init(&tree->list); in audit_add_tree_rule()
865 list_del_init(&tree->rules); in audit_add_tree_rule()
866 put_tree(tree); in audit_add_tree_rule()
897 struct audit_tree *tree; in audit_tag_tree() local
900 tree = container_of(cursor.next, struct audit_tree, list); in audit_tag_tree()
901 get_tree(tree); in audit_tag_tree()
902 list_move(&cursor, &tree->list); in audit_tag_tree()
905 err = kern_path(tree->pathname, 0, &path2); in audit_tag_tree()
912 put_tree(tree); in audit_tag_tree()
917 failed = iterate_mounts(tag_mount, tree, tagged); in audit_tag_tree()
919 put_tree(tree); in audit_tag_tree()
926 if (!tree->goner) { in audit_tag_tree()
927 list_move(&tree->list, &tree_list); in audit_tag_tree()
930 put_tree(tree); in audit_tag_tree()
934 struct audit_tree *tree; in audit_tag_tree() local
936 tree = container_of(barrier.prev, struct audit_tree, list); in audit_tag_tree()
937 get_tree(tree); in audit_tag_tree()
938 list_move(&tree->list, &barrier); in audit_tag_tree()
944 list_for_each_entry(node, &tree->chunks, list) in audit_tag_tree()
945 node->index &= ~(1U<<31); in audit_tag_tree()
948 trim_marked(tree); in audit_tag_tree()
951 put_tree(tree); in audit_tag_tree()
974 struct list_head *list = &context->killed_trees; in audit_kill_trees()
982 victim = list_entry(list->next, struct audit_tree, list); in audit_kill_trees()
984 list_del_init(&victim->list); in audit_kill_trees()
1010 while (!list_empty(&chunk->trees)) { in evict_chunk()
1011 owner = list_entry(chunk->trees.next, in evict_chunk()
1013 owner->goner = 1; in evict_chunk()
1014 owner->root = NULL; in evict_chunk()
1015 list_del_init(&owner->same_root); in evict_chunk()
1019 list_move(&owner->list, &prune_list); in evict_chunk()
1022 list_move(&owner->list, postponed); in evict_chunk()
1026 list_del_rcu(&chunk->hash); in evict_chunk()
1027 for (n = 0; n < chunk->count; n++) in evict_chunk()
1028 list_del_init(&chunk->owners[n].list); in evict_chunk()
1047 fsnotify_group_lock(mark->group); in audit_tree_freeing_mark()
1052 fsnotify_group_unlock(mark->group); in audit_tree_freeing_mark()
1062 BUG_ON(refcount_read(&mark->refcnt) < 1); in audit_tree_freeing_mark()