xref: /openbmc/linux/kernel/audit_tree.c (revision b4c30aad)
174c3cbe3SAl Viro #include "audit.h"
274c3cbe3SAl Viro #include <linux/inotify.h>
374c3cbe3SAl Viro #include <linux/namei.h>
474c3cbe3SAl Viro #include <linux/mount.h>
5916d7576SAl Viro #include <linux/kthread.h>
674c3cbe3SAl Viro 
774c3cbe3SAl Viro struct audit_tree;
874c3cbe3SAl Viro struct audit_chunk;
974c3cbe3SAl Viro 
1074c3cbe3SAl Viro struct audit_tree {
1174c3cbe3SAl Viro 	atomic_t count;
1274c3cbe3SAl Viro 	int goner;
1374c3cbe3SAl Viro 	struct audit_chunk *root;
1474c3cbe3SAl Viro 	struct list_head chunks;
1574c3cbe3SAl Viro 	struct list_head rules;
1674c3cbe3SAl Viro 	struct list_head list;
1774c3cbe3SAl Viro 	struct list_head same_root;
1874c3cbe3SAl Viro 	struct rcu_head head;
1974c3cbe3SAl Viro 	char pathname[];
2074c3cbe3SAl Viro };
2174c3cbe3SAl Viro 
2274c3cbe3SAl Viro struct audit_chunk {
2374c3cbe3SAl Viro 	struct list_head hash;
2474c3cbe3SAl Viro 	struct inotify_watch watch;
2574c3cbe3SAl Viro 	struct list_head trees;		/* with root here */
2674c3cbe3SAl Viro 	int dead;
2774c3cbe3SAl Viro 	int count;
288f7b0ba1SAl Viro 	atomic_long_t refs;
2974c3cbe3SAl Viro 	struct rcu_head head;
3074c3cbe3SAl Viro 	struct node {
3174c3cbe3SAl Viro 		struct list_head list;
3274c3cbe3SAl Viro 		struct audit_tree *owner;
3374c3cbe3SAl Viro 		unsigned index;		/* index; upper bit indicates 'will prune' */
3474c3cbe3SAl Viro 	} owners[];
3574c3cbe3SAl Viro };
3674c3cbe3SAl Viro 
3774c3cbe3SAl Viro static LIST_HEAD(tree_list);
3874c3cbe3SAl Viro static LIST_HEAD(prune_list);
3974c3cbe3SAl Viro 
4074c3cbe3SAl Viro /*
4174c3cbe3SAl Viro  * One struct chunk is attached to each inode of interest.
4274c3cbe3SAl Viro  * We replace struct chunk on tagging/untagging.
4374c3cbe3SAl Viro  * Rules have pointer to struct audit_tree.
4474c3cbe3SAl Viro  * Rules have struct list_head rlist forming a list of rules over
4574c3cbe3SAl Viro  * the same tree.
4674c3cbe3SAl Viro  * References to struct chunk are collected at audit_inode{,_child}()
4774c3cbe3SAl Viro  * time and used in AUDIT_TREE rule matching.
4874c3cbe3SAl Viro  * These references are dropped at the same time we are calling
4974c3cbe3SAl Viro  * audit_free_names(), etc.
5074c3cbe3SAl Viro  *
5174c3cbe3SAl Viro  * Cyclic lists galore:
5274c3cbe3SAl Viro  * tree.chunks anchors chunk.owners[].list			hash_lock
5374c3cbe3SAl Viro  * tree.rules anchors rule.rlist				audit_filter_mutex
5474c3cbe3SAl Viro  * chunk.trees anchors tree.same_root				hash_lock
5574c3cbe3SAl Viro  * chunk.hash is a hash with middle bits of watch.inode as
5674c3cbe3SAl Viro  * a hash function.						RCU, hash_lock
5774c3cbe3SAl Viro  *
5874c3cbe3SAl Viro  * tree is refcounted; one reference for "some rules on rules_list refer to
5974c3cbe3SAl Viro  * it", one for each chunk with pointer to it.
6074c3cbe3SAl Viro  *
618f7b0ba1SAl Viro  * chunk is refcounted by embedded inotify_watch + .refs (non-zero refcount
628f7b0ba1SAl Viro  * of watch contributes 1 to .refs).
6374c3cbe3SAl Viro  *
6474c3cbe3SAl Viro  * node.index allows to get from node.list to containing chunk.
6574c3cbe3SAl Viro  * MSB of that sucker is stolen to mark taggings that we might have to
6674c3cbe3SAl Viro  * revert - several operations have very unpleasant cleanup logics and
6774c3cbe3SAl Viro  * that makes a difference.  Some.
6874c3cbe3SAl Viro  */
6974c3cbe3SAl Viro 
7074c3cbe3SAl Viro static struct inotify_handle *rtree_ih;
7174c3cbe3SAl Viro 
7274c3cbe3SAl Viro static struct audit_tree *alloc_tree(const char *s)
7374c3cbe3SAl Viro {
7474c3cbe3SAl Viro 	struct audit_tree *tree;
7574c3cbe3SAl Viro 
7674c3cbe3SAl Viro 	tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL);
7774c3cbe3SAl Viro 	if (tree) {
7874c3cbe3SAl Viro 		atomic_set(&tree->count, 1);
7974c3cbe3SAl Viro 		tree->goner = 0;
8074c3cbe3SAl Viro 		INIT_LIST_HEAD(&tree->chunks);
8174c3cbe3SAl Viro 		INIT_LIST_HEAD(&tree->rules);
8274c3cbe3SAl Viro 		INIT_LIST_HEAD(&tree->list);
8374c3cbe3SAl Viro 		INIT_LIST_HEAD(&tree->same_root);
8474c3cbe3SAl Viro 		tree->root = NULL;
8574c3cbe3SAl Viro 		strcpy(tree->pathname, s);
8674c3cbe3SAl Viro 	}
8774c3cbe3SAl Viro 	return tree;
8874c3cbe3SAl Viro }
8974c3cbe3SAl Viro 
9074c3cbe3SAl Viro static inline void get_tree(struct audit_tree *tree)
9174c3cbe3SAl Viro {
9274c3cbe3SAl Viro 	atomic_inc(&tree->count);
9374c3cbe3SAl Viro }
9474c3cbe3SAl Viro 
9574c3cbe3SAl Viro static void __put_tree(struct rcu_head *rcu)
9674c3cbe3SAl Viro {
9774c3cbe3SAl Viro 	struct audit_tree *tree = container_of(rcu, struct audit_tree, head);
9874c3cbe3SAl Viro 	kfree(tree);
9974c3cbe3SAl Viro }
10074c3cbe3SAl Viro 
10174c3cbe3SAl Viro static inline void put_tree(struct audit_tree *tree)
10274c3cbe3SAl Viro {
10374c3cbe3SAl Viro 	if (atomic_dec_and_test(&tree->count))
10474c3cbe3SAl Viro 		call_rcu(&tree->head, __put_tree);
10574c3cbe3SAl Viro }
10674c3cbe3SAl Viro 
10774c3cbe3SAl Viro /* to avoid bringing the entire thing in audit.h */
10874c3cbe3SAl Viro const char *audit_tree_path(struct audit_tree *tree)
10974c3cbe3SAl Viro {
11074c3cbe3SAl Viro 	return tree->pathname;
11174c3cbe3SAl Viro }
11274c3cbe3SAl Viro 
11374c3cbe3SAl Viro static struct audit_chunk *alloc_chunk(int count)
11474c3cbe3SAl Viro {
11574c3cbe3SAl Viro 	struct audit_chunk *chunk;
11674c3cbe3SAl Viro 	size_t size;
11774c3cbe3SAl Viro 	int i;
11874c3cbe3SAl Viro 
11974c3cbe3SAl Viro 	size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node);
12074c3cbe3SAl Viro 	chunk = kzalloc(size, GFP_KERNEL);
12174c3cbe3SAl Viro 	if (!chunk)
12274c3cbe3SAl Viro 		return NULL;
12374c3cbe3SAl Viro 
12474c3cbe3SAl Viro 	INIT_LIST_HEAD(&chunk->hash);
12574c3cbe3SAl Viro 	INIT_LIST_HEAD(&chunk->trees);
12674c3cbe3SAl Viro 	chunk->count = count;
1278f7b0ba1SAl Viro 	atomic_long_set(&chunk->refs, 1);
12874c3cbe3SAl Viro 	for (i = 0; i < count; i++) {
12974c3cbe3SAl Viro 		INIT_LIST_HEAD(&chunk->owners[i].list);
13074c3cbe3SAl Viro 		chunk->owners[i].index = i;
13174c3cbe3SAl Viro 	}
13274c3cbe3SAl Viro 	inotify_init_watch(&chunk->watch);
13374c3cbe3SAl Viro 	return chunk;
13474c3cbe3SAl Viro }
13574c3cbe3SAl Viro 
1368f7b0ba1SAl Viro static void free_chunk(struct audit_chunk *chunk)
13774c3cbe3SAl Viro {
13874c3cbe3SAl Viro 	int i;
13974c3cbe3SAl Viro 
14074c3cbe3SAl Viro 	for (i = 0; i < chunk->count; i++) {
14174c3cbe3SAl Viro 		if (chunk->owners[i].owner)
14274c3cbe3SAl Viro 			put_tree(chunk->owners[i].owner);
14374c3cbe3SAl Viro 	}
14474c3cbe3SAl Viro 	kfree(chunk);
14574c3cbe3SAl Viro }
14674c3cbe3SAl Viro 
14774c3cbe3SAl Viro void audit_put_chunk(struct audit_chunk *chunk)
14874c3cbe3SAl Viro {
1498f7b0ba1SAl Viro 	if (atomic_long_dec_and_test(&chunk->refs))
1508f7b0ba1SAl Viro 		free_chunk(chunk);
1518f7b0ba1SAl Viro }
1528f7b0ba1SAl Viro 
1538f7b0ba1SAl Viro static void __put_chunk(struct rcu_head *rcu)
1548f7b0ba1SAl Viro {
1558f7b0ba1SAl Viro 	struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
1568f7b0ba1SAl Viro 	audit_put_chunk(chunk);
15774c3cbe3SAl Viro }
15874c3cbe3SAl Viro 
15974c3cbe3SAl Viro enum {HASH_SIZE = 128};
16074c3cbe3SAl Viro static struct list_head chunk_hash_heads[HASH_SIZE];
16174c3cbe3SAl Viro static __cacheline_aligned_in_smp DEFINE_SPINLOCK(hash_lock);
16274c3cbe3SAl Viro 
16374c3cbe3SAl Viro static inline struct list_head *chunk_hash(const struct inode *inode)
16474c3cbe3SAl Viro {
16574c3cbe3SAl Viro 	unsigned long n = (unsigned long)inode / L1_CACHE_BYTES;
16674c3cbe3SAl Viro 	return chunk_hash_heads + n % HASH_SIZE;
16774c3cbe3SAl Viro }
16874c3cbe3SAl Viro 
16974c3cbe3SAl Viro /* hash_lock is held by caller */
17074c3cbe3SAl Viro static void insert_hash(struct audit_chunk *chunk)
17174c3cbe3SAl Viro {
17274c3cbe3SAl Viro 	struct list_head *list = chunk_hash(chunk->watch.inode);
17374c3cbe3SAl Viro 	list_add_rcu(&chunk->hash, list);
17474c3cbe3SAl Viro }
17574c3cbe3SAl Viro 
17674c3cbe3SAl Viro /* called under rcu_read_lock */
17774c3cbe3SAl Viro struct audit_chunk *audit_tree_lookup(const struct inode *inode)
17874c3cbe3SAl Viro {
17974c3cbe3SAl Viro 	struct list_head *list = chunk_hash(inode);
1806793a051SPaul E. McKenney 	struct audit_chunk *p;
18174c3cbe3SAl Viro 
1826793a051SPaul E. McKenney 	list_for_each_entry_rcu(p, list, hash) {
18374c3cbe3SAl Viro 		if (p->watch.inode == inode) {
1848f7b0ba1SAl Viro 			atomic_long_inc(&p->refs);
18574c3cbe3SAl Viro 			return p;
18674c3cbe3SAl Viro 		}
18774c3cbe3SAl Viro 	}
18874c3cbe3SAl Viro 	return NULL;
18974c3cbe3SAl Viro }
19074c3cbe3SAl Viro 
19174c3cbe3SAl Viro int audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree)
19274c3cbe3SAl Viro {
19374c3cbe3SAl Viro 	int n;
19474c3cbe3SAl Viro 	for (n = 0; n < chunk->count; n++)
19574c3cbe3SAl Viro 		if (chunk->owners[n].owner == tree)
19674c3cbe3SAl Viro 			return 1;
19774c3cbe3SAl Viro 	return 0;
19874c3cbe3SAl Viro }
19974c3cbe3SAl Viro 
20074c3cbe3SAl Viro /* tagging and untagging inodes with trees */
20174c3cbe3SAl Viro 
2028f7b0ba1SAl Viro static struct audit_chunk *find_chunk(struct node *p)
20374c3cbe3SAl Viro {
2048f7b0ba1SAl Viro 	int index = p->index & ~(1U<<31);
2058f7b0ba1SAl Viro 	p -= index;
2068f7b0ba1SAl Viro 	return container_of(p, struct audit_chunk, owners[0]);
2078f7b0ba1SAl Viro }
2088f7b0ba1SAl Viro 
2098f7b0ba1SAl Viro static void untag_chunk(struct node *p)
2108f7b0ba1SAl Viro {
2118f7b0ba1SAl Viro 	struct audit_chunk *chunk = find_chunk(p);
21274c3cbe3SAl Viro 	struct audit_chunk *new;
21374c3cbe3SAl Viro 	struct audit_tree *owner;
21474c3cbe3SAl Viro 	int size = chunk->count - 1;
21574c3cbe3SAl Viro 	int i, j;
21674c3cbe3SAl Viro 
2178f7b0ba1SAl Viro 	if (!pin_inotify_watch(&chunk->watch)) {
2188f7b0ba1SAl Viro 		/*
2198f7b0ba1SAl Viro 		 * Filesystem is shutting down; all watches are getting
2208f7b0ba1SAl Viro 		 * evicted, just take it off the node list for this
2218f7b0ba1SAl Viro 		 * tree and let the eviction logics take care of the
2228f7b0ba1SAl Viro 		 * rest.
2238f7b0ba1SAl Viro 		 */
2248f7b0ba1SAl Viro 		owner = p->owner;
2258f7b0ba1SAl Viro 		if (owner->root == chunk) {
2268f7b0ba1SAl Viro 			list_del_init(&owner->same_root);
2278f7b0ba1SAl Viro 			owner->root = NULL;
2288f7b0ba1SAl Viro 		}
2298f7b0ba1SAl Viro 		list_del_init(&p->list);
2308f7b0ba1SAl Viro 		p->owner = NULL;
2318f7b0ba1SAl Viro 		put_tree(owner);
2328f7b0ba1SAl Viro 		return;
2338f7b0ba1SAl Viro 	}
2348f7b0ba1SAl Viro 
2358f7b0ba1SAl Viro 	spin_unlock(&hash_lock);
2368f7b0ba1SAl Viro 
2378f7b0ba1SAl Viro 	/*
2388f7b0ba1SAl Viro 	 * pin_inotify_watch() succeeded, so the watch won't go away
2398f7b0ba1SAl Viro 	 * from under us.
2408f7b0ba1SAl Viro 	 */
24174c3cbe3SAl Viro 	mutex_lock(&chunk->watch.inode->inotify_mutex);
24274c3cbe3SAl Viro 	if (chunk->dead) {
24374c3cbe3SAl Viro 		mutex_unlock(&chunk->watch.inode->inotify_mutex);
2448f7b0ba1SAl Viro 		goto out;
24574c3cbe3SAl Viro 	}
24674c3cbe3SAl Viro 
24774c3cbe3SAl Viro 	owner = p->owner;
24874c3cbe3SAl Viro 
24974c3cbe3SAl Viro 	if (!size) {
25074c3cbe3SAl Viro 		chunk->dead = 1;
25174c3cbe3SAl Viro 		spin_lock(&hash_lock);
25274c3cbe3SAl Viro 		list_del_init(&chunk->trees);
25374c3cbe3SAl Viro 		if (owner->root == chunk)
25474c3cbe3SAl Viro 			owner->root = NULL;
25574c3cbe3SAl Viro 		list_del_init(&p->list);
25674c3cbe3SAl Viro 		list_del_rcu(&chunk->hash);
25774c3cbe3SAl Viro 		spin_unlock(&hash_lock);
25874c3cbe3SAl Viro 		inotify_evict_watch(&chunk->watch);
25974c3cbe3SAl Viro 		mutex_unlock(&chunk->watch.inode->inotify_mutex);
26074c3cbe3SAl Viro 		put_inotify_watch(&chunk->watch);
2618f7b0ba1SAl Viro 		goto out;
26274c3cbe3SAl Viro 	}
26374c3cbe3SAl Viro 
26474c3cbe3SAl Viro 	new = alloc_chunk(size);
26574c3cbe3SAl Viro 	if (!new)
26674c3cbe3SAl Viro 		goto Fallback;
26774c3cbe3SAl Viro 	if (inotify_clone_watch(&chunk->watch, &new->watch) < 0) {
26874c3cbe3SAl Viro 		free_chunk(new);
26974c3cbe3SAl Viro 		goto Fallback;
27074c3cbe3SAl Viro 	}
27174c3cbe3SAl Viro 
27274c3cbe3SAl Viro 	chunk->dead = 1;
27374c3cbe3SAl Viro 	spin_lock(&hash_lock);
27474c3cbe3SAl Viro 	list_replace_init(&chunk->trees, &new->trees);
27574c3cbe3SAl Viro 	if (owner->root == chunk) {
27674c3cbe3SAl Viro 		list_del_init(&owner->same_root);
27774c3cbe3SAl Viro 		owner->root = NULL;
27874c3cbe3SAl Viro 	}
27974c3cbe3SAl Viro 
2806f5d5114SAl Viro 	for (i = j = 0; j <= size; i++, j++) {
28174c3cbe3SAl Viro 		struct audit_tree *s;
28274c3cbe3SAl Viro 		if (&chunk->owners[j] == p) {
28374c3cbe3SAl Viro 			list_del_init(&p->list);
28474c3cbe3SAl Viro 			i--;
28574c3cbe3SAl Viro 			continue;
28674c3cbe3SAl Viro 		}
28774c3cbe3SAl Viro 		s = chunk->owners[j].owner;
28874c3cbe3SAl Viro 		new->owners[i].owner = s;
28974c3cbe3SAl Viro 		new->owners[i].index = chunk->owners[j].index - j + i;
29074c3cbe3SAl Viro 		if (!s) /* result of earlier fallback */
29174c3cbe3SAl Viro 			continue;
29274c3cbe3SAl Viro 		get_tree(s);
2936f5d5114SAl Viro 		list_replace_init(&chunk->owners[j].list, &new->owners[i].list);
29474c3cbe3SAl Viro 	}
29574c3cbe3SAl Viro 
29674c3cbe3SAl Viro 	list_replace_rcu(&chunk->hash, &new->hash);
29774c3cbe3SAl Viro 	list_for_each_entry(owner, &new->trees, same_root)
29874c3cbe3SAl Viro 		owner->root = new;
29974c3cbe3SAl Viro 	spin_unlock(&hash_lock);
30074c3cbe3SAl Viro 	inotify_evict_watch(&chunk->watch);
30174c3cbe3SAl Viro 	mutex_unlock(&chunk->watch.inode->inotify_mutex);
30274c3cbe3SAl Viro 	put_inotify_watch(&chunk->watch);
3038f7b0ba1SAl Viro 	goto out;
30474c3cbe3SAl Viro 
30574c3cbe3SAl Viro Fallback:
30674c3cbe3SAl Viro 	// do the best we can
30774c3cbe3SAl Viro 	spin_lock(&hash_lock);
30874c3cbe3SAl Viro 	if (owner->root == chunk) {
30974c3cbe3SAl Viro 		list_del_init(&owner->same_root);
31074c3cbe3SAl Viro 		owner->root = NULL;
31174c3cbe3SAl Viro 	}
31274c3cbe3SAl Viro 	list_del_init(&p->list);
31374c3cbe3SAl Viro 	p->owner = NULL;
31474c3cbe3SAl Viro 	put_tree(owner);
31574c3cbe3SAl Viro 	spin_unlock(&hash_lock);
31674c3cbe3SAl Viro 	mutex_unlock(&chunk->watch.inode->inotify_mutex);
3178f7b0ba1SAl Viro out:
3188f7b0ba1SAl Viro 	unpin_inotify_watch(&chunk->watch);
3198f7b0ba1SAl Viro 	spin_lock(&hash_lock);
32074c3cbe3SAl Viro }
32174c3cbe3SAl Viro 
32274c3cbe3SAl Viro static int create_chunk(struct inode *inode, struct audit_tree *tree)
32374c3cbe3SAl Viro {
32474c3cbe3SAl Viro 	struct audit_chunk *chunk = alloc_chunk(1);
32574c3cbe3SAl Viro 	if (!chunk)
32674c3cbe3SAl Viro 		return -ENOMEM;
32774c3cbe3SAl Viro 
32874c3cbe3SAl Viro 	if (inotify_add_watch(rtree_ih, &chunk->watch, inode, IN_IGNORED | IN_DELETE_SELF) < 0) {
32974c3cbe3SAl Viro 		free_chunk(chunk);
33074c3cbe3SAl Viro 		return -ENOSPC;
33174c3cbe3SAl Viro 	}
33274c3cbe3SAl Viro 
33374c3cbe3SAl Viro 	mutex_lock(&inode->inotify_mutex);
33474c3cbe3SAl Viro 	spin_lock(&hash_lock);
33574c3cbe3SAl Viro 	if (tree->goner) {
33674c3cbe3SAl Viro 		spin_unlock(&hash_lock);
33774c3cbe3SAl Viro 		chunk->dead = 1;
33874c3cbe3SAl Viro 		inotify_evict_watch(&chunk->watch);
33974c3cbe3SAl Viro 		mutex_unlock(&inode->inotify_mutex);
34074c3cbe3SAl Viro 		put_inotify_watch(&chunk->watch);
34174c3cbe3SAl Viro 		return 0;
34274c3cbe3SAl Viro 	}
34374c3cbe3SAl Viro 	chunk->owners[0].index = (1U << 31);
34474c3cbe3SAl Viro 	chunk->owners[0].owner = tree;
34574c3cbe3SAl Viro 	get_tree(tree);
34674c3cbe3SAl Viro 	list_add(&chunk->owners[0].list, &tree->chunks);
34774c3cbe3SAl Viro 	if (!tree->root) {
34874c3cbe3SAl Viro 		tree->root = chunk;
34974c3cbe3SAl Viro 		list_add(&tree->same_root, &chunk->trees);
35074c3cbe3SAl Viro 	}
35174c3cbe3SAl Viro 	insert_hash(chunk);
35274c3cbe3SAl Viro 	spin_unlock(&hash_lock);
35374c3cbe3SAl Viro 	mutex_unlock(&inode->inotify_mutex);
35474c3cbe3SAl Viro 	return 0;
35574c3cbe3SAl Viro }
35674c3cbe3SAl Viro 
35774c3cbe3SAl Viro /* the first tagged inode becomes root of tree */
35874c3cbe3SAl Viro static int tag_chunk(struct inode *inode, struct audit_tree *tree)
35974c3cbe3SAl Viro {
36074c3cbe3SAl Viro 	struct inotify_watch *watch;
36174c3cbe3SAl Viro 	struct audit_tree *owner;
36274c3cbe3SAl Viro 	struct audit_chunk *chunk, *old;
36374c3cbe3SAl Viro 	struct node *p;
36474c3cbe3SAl Viro 	int n;
36574c3cbe3SAl Viro 
36674c3cbe3SAl Viro 	if (inotify_find_watch(rtree_ih, inode, &watch) < 0)
36774c3cbe3SAl Viro 		return create_chunk(inode, tree);
36874c3cbe3SAl Viro 
36974c3cbe3SAl Viro 	old = container_of(watch, struct audit_chunk, watch);
37074c3cbe3SAl Viro 
37174c3cbe3SAl Viro 	/* are we already there? */
37274c3cbe3SAl Viro 	spin_lock(&hash_lock);
37374c3cbe3SAl Viro 	for (n = 0; n < old->count; n++) {
37474c3cbe3SAl Viro 		if (old->owners[n].owner == tree) {
37574c3cbe3SAl Viro 			spin_unlock(&hash_lock);
376b4c30aadSAl Viro 			put_inotify_watch(&old->watch);
37774c3cbe3SAl Viro 			return 0;
37874c3cbe3SAl Viro 		}
37974c3cbe3SAl Viro 	}
38074c3cbe3SAl Viro 	spin_unlock(&hash_lock);
38174c3cbe3SAl Viro 
38274c3cbe3SAl Viro 	chunk = alloc_chunk(old->count + 1);
383b4c30aadSAl Viro 	if (!chunk) {
384b4c30aadSAl Viro 		put_inotify_watch(&old->watch);
38574c3cbe3SAl Viro 		return -ENOMEM;
386b4c30aadSAl Viro 	}
38774c3cbe3SAl Viro 
38874c3cbe3SAl Viro 	mutex_lock(&inode->inotify_mutex);
38974c3cbe3SAl Viro 	if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) {
39074c3cbe3SAl Viro 		mutex_unlock(&inode->inotify_mutex);
391318b6d3dSEric Paris 		put_inotify_watch(&old->watch);
39274c3cbe3SAl Viro 		free_chunk(chunk);
39374c3cbe3SAl Viro 		return -ENOSPC;
39474c3cbe3SAl Viro 	}
39574c3cbe3SAl Viro 	spin_lock(&hash_lock);
39674c3cbe3SAl Viro 	if (tree->goner) {
39774c3cbe3SAl Viro 		spin_unlock(&hash_lock);
39874c3cbe3SAl Viro 		chunk->dead = 1;
39974c3cbe3SAl Viro 		inotify_evict_watch(&chunk->watch);
40074c3cbe3SAl Viro 		mutex_unlock(&inode->inotify_mutex);
401318b6d3dSEric Paris 		put_inotify_watch(&old->watch);
40274c3cbe3SAl Viro 		put_inotify_watch(&chunk->watch);
40374c3cbe3SAl Viro 		return 0;
40474c3cbe3SAl Viro 	}
40574c3cbe3SAl Viro 	list_replace_init(&old->trees, &chunk->trees);
40674c3cbe3SAl Viro 	for (n = 0, p = chunk->owners; n < old->count; n++, p++) {
40774c3cbe3SAl Viro 		struct audit_tree *s = old->owners[n].owner;
40874c3cbe3SAl Viro 		p->owner = s;
40974c3cbe3SAl Viro 		p->index = old->owners[n].index;
41074c3cbe3SAl Viro 		if (!s) /* result of fallback in untag */
41174c3cbe3SAl Viro 			continue;
41274c3cbe3SAl Viro 		get_tree(s);
41374c3cbe3SAl Viro 		list_replace_init(&old->owners[n].list, &p->list);
41474c3cbe3SAl Viro 	}
41574c3cbe3SAl Viro 	p->index = (chunk->count - 1) | (1U<<31);
41674c3cbe3SAl Viro 	p->owner = tree;
41774c3cbe3SAl Viro 	get_tree(tree);
41874c3cbe3SAl Viro 	list_add(&p->list, &tree->chunks);
41974c3cbe3SAl Viro 	list_replace_rcu(&old->hash, &chunk->hash);
42074c3cbe3SAl Viro 	list_for_each_entry(owner, &chunk->trees, same_root)
42174c3cbe3SAl Viro 		owner->root = chunk;
42274c3cbe3SAl Viro 	old->dead = 1;
42374c3cbe3SAl Viro 	if (!tree->root) {
42474c3cbe3SAl Viro 		tree->root = chunk;
42574c3cbe3SAl Viro 		list_add(&tree->same_root, &chunk->trees);
42674c3cbe3SAl Viro 	}
42774c3cbe3SAl Viro 	spin_unlock(&hash_lock);
42874c3cbe3SAl Viro 	inotify_evict_watch(&old->watch);
42974c3cbe3SAl Viro 	mutex_unlock(&inode->inotify_mutex);
430b4c30aadSAl Viro 	put_inotify_watch(&old->watch); /* pair to inotify_find_watch */
431b4c30aadSAl Viro 	put_inotify_watch(&old->watch); /* and kill it */
43274c3cbe3SAl Viro 	return 0;
43374c3cbe3SAl Viro }
43474c3cbe3SAl Viro 
43574c3cbe3SAl Viro static void kill_rules(struct audit_tree *tree)
43674c3cbe3SAl Viro {
43774c3cbe3SAl Viro 	struct audit_krule *rule, *next;
43874c3cbe3SAl Viro 	struct audit_entry *entry;
43974c3cbe3SAl Viro 	struct audit_buffer *ab;
44074c3cbe3SAl Viro 
44174c3cbe3SAl Viro 	list_for_each_entry_safe(rule, next, &tree->rules, rlist) {
44274c3cbe3SAl Viro 		entry = container_of(rule, struct audit_entry, rule);
44374c3cbe3SAl Viro 
44474c3cbe3SAl Viro 		list_del_init(&rule->rlist);
44574c3cbe3SAl Viro 		if (rule->tree) {
44674c3cbe3SAl Viro 			/* not a half-baked one */
44774c3cbe3SAl Viro 			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
4489d960985SEric Paris 			audit_log_format(ab, "op=");
4499d960985SEric Paris 			audit_log_string(ab, "remove rule");
4509d960985SEric Paris 			audit_log_format(ab, " dir=");
45174c3cbe3SAl Viro 			audit_log_untrustedstring(ab, rule->tree->pathname);
4529d960985SEric Paris 			audit_log_key(ab, rule->filterkey);
45374c3cbe3SAl Viro 			audit_log_format(ab, " list=%d res=1", rule->listnr);
45474c3cbe3SAl Viro 			audit_log_end(ab);
45574c3cbe3SAl Viro 			rule->tree = NULL;
45674c3cbe3SAl Viro 			list_del_rcu(&entry->list);
457e45aa212SAl Viro 			list_del(&entry->rule.list);
45874c3cbe3SAl Viro 			call_rcu(&entry->rcu, audit_free_rule_rcu);
45974c3cbe3SAl Viro 		}
46074c3cbe3SAl Viro 	}
46174c3cbe3SAl Viro }
46274c3cbe3SAl Viro 
46374c3cbe3SAl Viro /*
46474c3cbe3SAl Viro  * finish killing struct audit_tree
46574c3cbe3SAl Viro  */
46674c3cbe3SAl Viro static void prune_one(struct audit_tree *victim)
46774c3cbe3SAl Viro {
46874c3cbe3SAl Viro 	spin_lock(&hash_lock);
46974c3cbe3SAl Viro 	while (!list_empty(&victim->chunks)) {
47074c3cbe3SAl Viro 		struct node *p;
47174c3cbe3SAl Viro 
47274c3cbe3SAl Viro 		p = list_entry(victim->chunks.next, struct node, list);
47374c3cbe3SAl Viro 
4748f7b0ba1SAl Viro 		untag_chunk(p);
47574c3cbe3SAl Viro 	}
47674c3cbe3SAl Viro 	spin_unlock(&hash_lock);
47774c3cbe3SAl Viro 	put_tree(victim);
47874c3cbe3SAl Viro }
47974c3cbe3SAl Viro 
48074c3cbe3SAl Viro /* trim the uncommitted chunks from tree */
48174c3cbe3SAl Viro 
48274c3cbe3SAl Viro static void trim_marked(struct audit_tree *tree)
48374c3cbe3SAl Viro {
48474c3cbe3SAl Viro 	struct list_head *p, *q;
48574c3cbe3SAl Viro 	spin_lock(&hash_lock);
48674c3cbe3SAl Viro 	if (tree->goner) {
48774c3cbe3SAl Viro 		spin_unlock(&hash_lock);
48874c3cbe3SAl Viro 		return;
48974c3cbe3SAl Viro 	}
49074c3cbe3SAl Viro 	/* reorder */
49174c3cbe3SAl Viro 	for (p = tree->chunks.next; p != &tree->chunks; p = q) {
49274c3cbe3SAl Viro 		struct node *node = list_entry(p, struct node, list);
49374c3cbe3SAl Viro 		q = p->next;
49474c3cbe3SAl Viro 		if (node->index & (1U<<31)) {
49574c3cbe3SAl Viro 			list_del_init(p);
49674c3cbe3SAl Viro 			list_add(p, &tree->chunks);
49774c3cbe3SAl Viro 		}
49874c3cbe3SAl Viro 	}
49974c3cbe3SAl Viro 
50074c3cbe3SAl Viro 	while (!list_empty(&tree->chunks)) {
50174c3cbe3SAl Viro 		struct node *node;
50274c3cbe3SAl Viro 
50374c3cbe3SAl Viro 		node = list_entry(tree->chunks.next, struct node, list);
50474c3cbe3SAl Viro 
50574c3cbe3SAl Viro 		/* have we run out of marked? */
50674c3cbe3SAl Viro 		if (!(node->index & (1U<<31)))
50774c3cbe3SAl Viro 			break;
50874c3cbe3SAl Viro 
5098f7b0ba1SAl Viro 		untag_chunk(node);
51074c3cbe3SAl Viro 	}
51174c3cbe3SAl Viro 	if (!tree->root && !tree->goner) {
51274c3cbe3SAl Viro 		tree->goner = 1;
51374c3cbe3SAl Viro 		spin_unlock(&hash_lock);
51474c3cbe3SAl Viro 		mutex_lock(&audit_filter_mutex);
51574c3cbe3SAl Viro 		kill_rules(tree);
51674c3cbe3SAl Viro 		list_del_init(&tree->list);
51774c3cbe3SAl Viro 		mutex_unlock(&audit_filter_mutex);
51874c3cbe3SAl Viro 		prune_one(tree);
51974c3cbe3SAl Viro 	} else {
52074c3cbe3SAl Viro 		spin_unlock(&hash_lock);
52174c3cbe3SAl Viro 	}
52274c3cbe3SAl Viro }
52374c3cbe3SAl Viro 
524916d7576SAl Viro static void audit_schedule_prune(void);
525916d7576SAl Viro 
52674c3cbe3SAl Viro /* called with audit_filter_mutex */
52774c3cbe3SAl Viro int audit_remove_tree_rule(struct audit_krule *rule)
52874c3cbe3SAl Viro {
52974c3cbe3SAl Viro 	struct audit_tree *tree;
53074c3cbe3SAl Viro 	tree = rule->tree;
53174c3cbe3SAl Viro 	if (tree) {
53274c3cbe3SAl Viro 		spin_lock(&hash_lock);
53374c3cbe3SAl Viro 		list_del_init(&rule->rlist);
53474c3cbe3SAl Viro 		if (list_empty(&tree->rules) && !tree->goner) {
53574c3cbe3SAl Viro 			tree->root = NULL;
53674c3cbe3SAl Viro 			list_del_init(&tree->same_root);
53774c3cbe3SAl Viro 			tree->goner = 1;
53874c3cbe3SAl Viro 			list_move(&tree->list, &prune_list);
53974c3cbe3SAl Viro 			rule->tree = NULL;
54074c3cbe3SAl Viro 			spin_unlock(&hash_lock);
54174c3cbe3SAl Viro 			audit_schedule_prune();
54274c3cbe3SAl Viro 			return 1;
54374c3cbe3SAl Viro 		}
54474c3cbe3SAl Viro 		rule->tree = NULL;
54574c3cbe3SAl Viro 		spin_unlock(&hash_lock);
54674c3cbe3SAl Viro 		return 1;
54774c3cbe3SAl Viro 	}
54874c3cbe3SAl Viro 	return 0;
54974c3cbe3SAl Viro }
55074c3cbe3SAl Viro 
55174c3cbe3SAl Viro void audit_trim_trees(void)
55274c3cbe3SAl Viro {
55374c3cbe3SAl Viro 	struct list_head cursor;
55474c3cbe3SAl Viro 
55574c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
55674c3cbe3SAl Viro 	list_add(&cursor, &tree_list);
55774c3cbe3SAl Viro 	while (cursor.next != &tree_list) {
55874c3cbe3SAl Viro 		struct audit_tree *tree;
55998bc993fSAl Viro 		struct path path;
56074c3cbe3SAl Viro 		struct vfsmount *root_mnt;
56174c3cbe3SAl Viro 		struct node *node;
56274c3cbe3SAl Viro 		struct list_head list;
56374c3cbe3SAl Viro 		int err;
56474c3cbe3SAl Viro 
56574c3cbe3SAl Viro 		tree = container_of(cursor.next, struct audit_tree, list);
56674c3cbe3SAl Viro 		get_tree(tree);
56774c3cbe3SAl Viro 		list_del(&cursor);
56874c3cbe3SAl Viro 		list_add(&cursor, &tree->list);
56974c3cbe3SAl Viro 		mutex_unlock(&audit_filter_mutex);
57074c3cbe3SAl Viro 
57198bc993fSAl Viro 		err = kern_path(tree->pathname, 0, &path);
57274c3cbe3SAl Viro 		if (err)
57374c3cbe3SAl Viro 			goto skip_it;
57474c3cbe3SAl Viro 
575589ff870SAl Viro 		root_mnt = collect_mounts(&path);
57698bc993fSAl Viro 		path_put(&path);
57774c3cbe3SAl Viro 		if (!root_mnt)
57874c3cbe3SAl Viro 			goto skip_it;
57974c3cbe3SAl Viro 
58074c3cbe3SAl Viro 		list_add_tail(&list, &root_mnt->mnt_list);
58174c3cbe3SAl Viro 		spin_lock(&hash_lock);
58274c3cbe3SAl Viro 		list_for_each_entry(node, &tree->chunks, list) {
58374c3cbe3SAl Viro 			struct audit_chunk *chunk = find_chunk(node);
58474c3cbe3SAl Viro 			struct inode *inode = chunk->watch.inode;
58574c3cbe3SAl Viro 			struct vfsmount *mnt;
58674c3cbe3SAl Viro 			node->index |= 1U<<31;
58774c3cbe3SAl Viro 			list_for_each_entry(mnt, &list, mnt_list) {
58874c3cbe3SAl Viro 				if (mnt->mnt_root->d_inode == inode) {
58974c3cbe3SAl Viro 					node->index &= ~(1U<<31);
59074c3cbe3SAl Viro 					break;
59174c3cbe3SAl Viro 				}
59274c3cbe3SAl Viro 			}
59374c3cbe3SAl Viro 		}
59474c3cbe3SAl Viro 		spin_unlock(&hash_lock);
59574c3cbe3SAl Viro 		trim_marked(tree);
59674c3cbe3SAl Viro 		put_tree(tree);
59774c3cbe3SAl Viro 		list_del_init(&list);
59874c3cbe3SAl Viro 		drop_collected_mounts(root_mnt);
59974c3cbe3SAl Viro skip_it:
60074c3cbe3SAl Viro 		mutex_lock(&audit_filter_mutex);
60174c3cbe3SAl Viro 	}
60274c3cbe3SAl Viro 	list_del(&cursor);
60374c3cbe3SAl Viro 	mutex_unlock(&audit_filter_mutex);
60474c3cbe3SAl Viro }
60574c3cbe3SAl Viro 
60674c3cbe3SAl Viro static int is_under(struct vfsmount *mnt, struct dentry *dentry,
60798bc993fSAl Viro 		    struct path *path)
60874c3cbe3SAl Viro {
60998bc993fSAl Viro 	if (mnt != path->mnt) {
61074c3cbe3SAl Viro 		for (;;) {
61174c3cbe3SAl Viro 			if (mnt->mnt_parent == mnt)
61274c3cbe3SAl Viro 				return 0;
61398bc993fSAl Viro 			if (mnt->mnt_parent == path->mnt)
61474c3cbe3SAl Viro 					break;
61574c3cbe3SAl Viro 			mnt = mnt->mnt_parent;
61674c3cbe3SAl Viro 		}
61774c3cbe3SAl Viro 		dentry = mnt->mnt_mountpoint;
61874c3cbe3SAl Viro 	}
61998bc993fSAl Viro 	return is_subdir(dentry, path->dentry);
62074c3cbe3SAl Viro }
62174c3cbe3SAl Viro 
62274c3cbe3SAl Viro int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
62374c3cbe3SAl Viro {
62474c3cbe3SAl Viro 
62574c3cbe3SAl Viro 	if (pathname[0] != '/' ||
62674c3cbe3SAl Viro 	    rule->listnr != AUDIT_FILTER_EXIT ||
6275af75d8dSAl Viro 	    op != Audit_equal ||
62874c3cbe3SAl Viro 	    rule->inode_f || rule->watch || rule->tree)
62974c3cbe3SAl Viro 		return -EINVAL;
63074c3cbe3SAl Viro 	rule->tree = alloc_tree(pathname);
63174c3cbe3SAl Viro 	if (!rule->tree)
63274c3cbe3SAl Viro 		return -ENOMEM;
63374c3cbe3SAl Viro 	return 0;
63474c3cbe3SAl Viro }
63574c3cbe3SAl Viro 
63674c3cbe3SAl Viro void audit_put_tree(struct audit_tree *tree)
63774c3cbe3SAl Viro {
63874c3cbe3SAl Viro 	put_tree(tree);
63974c3cbe3SAl Viro }
64074c3cbe3SAl Viro 
64174c3cbe3SAl Viro /* called with audit_filter_mutex */
64274c3cbe3SAl Viro int audit_add_tree_rule(struct audit_krule *rule)
64374c3cbe3SAl Viro {
64474c3cbe3SAl Viro 	struct audit_tree *seed = rule->tree, *tree;
64598bc993fSAl Viro 	struct path path;
64674c3cbe3SAl Viro 	struct vfsmount *mnt, *p;
64774c3cbe3SAl Viro 	struct list_head list;
64874c3cbe3SAl Viro 	int err;
64974c3cbe3SAl Viro 
65074c3cbe3SAl Viro 	list_for_each_entry(tree, &tree_list, list) {
65174c3cbe3SAl Viro 		if (!strcmp(seed->pathname, tree->pathname)) {
65274c3cbe3SAl Viro 			put_tree(seed);
65374c3cbe3SAl Viro 			rule->tree = tree;
65474c3cbe3SAl Viro 			list_add(&rule->rlist, &tree->rules);
65574c3cbe3SAl Viro 			return 0;
65674c3cbe3SAl Viro 		}
65774c3cbe3SAl Viro 	}
65874c3cbe3SAl Viro 	tree = seed;
65974c3cbe3SAl Viro 	list_add(&tree->list, &tree_list);
66074c3cbe3SAl Viro 	list_add(&rule->rlist, &tree->rules);
66174c3cbe3SAl Viro 	/* do not set rule->tree yet */
66274c3cbe3SAl Viro 	mutex_unlock(&audit_filter_mutex);
66374c3cbe3SAl Viro 
66498bc993fSAl Viro 	err = kern_path(tree->pathname, 0, &path);
66574c3cbe3SAl Viro 	if (err)
66674c3cbe3SAl Viro 		goto Err;
667589ff870SAl Viro 	mnt = collect_mounts(&path);
66898bc993fSAl Viro 	path_put(&path);
66974c3cbe3SAl Viro 	if (!mnt) {
67074c3cbe3SAl Viro 		err = -ENOMEM;
67174c3cbe3SAl Viro 		goto Err;
67274c3cbe3SAl Viro 	}
67374c3cbe3SAl Viro 	list_add_tail(&list, &mnt->mnt_list);
67474c3cbe3SAl Viro 
67574c3cbe3SAl Viro 	get_tree(tree);
67674c3cbe3SAl Viro 	list_for_each_entry(p, &list, mnt_list) {
67774c3cbe3SAl Viro 		err = tag_chunk(p->mnt_root->d_inode, tree);
67874c3cbe3SAl Viro 		if (err)
67974c3cbe3SAl Viro 			break;
68074c3cbe3SAl Viro 	}
68174c3cbe3SAl Viro 
68274c3cbe3SAl Viro 	list_del(&list);
68374c3cbe3SAl Viro 	drop_collected_mounts(mnt);
68474c3cbe3SAl Viro 
68574c3cbe3SAl Viro 	if (!err) {
68674c3cbe3SAl Viro 		struct node *node;
68774c3cbe3SAl Viro 		spin_lock(&hash_lock);
68874c3cbe3SAl Viro 		list_for_each_entry(node, &tree->chunks, list)
68974c3cbe3SAl Viro 			node->index &= ~(1U<<31);
69074c3cbe3SAl Viro 		spin_unlock(&hash_lock);
69174c3cbe3SAl Viro 	} else {
69274c3cbe3SAl Viro 		trim_marked(tree);
69374c3cbe3SAl Viro 		goto Err;
69474c3cbe3SAl Viro 	}
69574c3cbe3SAl Viro 
69674c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
69774c3cbe3SAl Viro 	if (list_empty(&rule->rlist)) {
69874c3cbe3SAl Viro 		put_tree(tree);
69974c3cbe3SAl Viro 		return -ENOENT;
70074c3cbe3SAl Viro 	}
70174c3cbe3SAl Viro 	rule->tree = tree;
70274c3cbe3SAl Viro 	put_tree(tree);
70374c3cbe3SAl Viro 
70474c3cbe3SAl Viro 	return 0;
70574c3cbe3SAl Viro Err:
70674c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
70774c3cbe3SAl Viro 	list_del_init(&tree->list);
70874c3cbe3SAl Viro 	list_del_init(&tree->rules);
70974c3cbe3SAl Viro 	put_tree(tree);
71074c3cbe3SAl Viro 	return err;
71174c3cbe3SAl Viro }
71274c3cbe3SAl Viro 
71374c3cbe3SAl Viro int audit_tag_tree(char *old, char *new)
71474c3cbe3SAl Viro {
71574c3cbe3SAl Viro 	struct list_head cursor, barrier;
71674c3cbe3SAl Viro 	int failed = 0;
71798bc993fSAl Viro 	struct path path;
71874c3cbe3SAl Viro 	struct vfsmount *tagged;
71974c3cbe3SAl Viro 	struct list_head list;
72074c3cbe3SAl Viro 	struct vfsmount *mnt;
72174c3cbe3SAl Viro 	struct dentry *dentry;
72274c3cbe3SAl Viro 	int err;
72374c3cbe3SAl Viro 
72498bc993fSAl Viro 	err = kern_path(new, 0, &path);
72574c3cbe3SAl Viro 	if (err)
72674c3cbe3SAl Viro 		return err;
727589ff870SAl Viro 	tagged = collect_mounts(&path);
72898bc993fSAl Viro 	path_put(&path);
72974c3cbe3SAl Viro 	if (!tagged)
73074c3cbe3SAl Viro 		return -ENOMEM;
73174c3cbe3SAl Viro 
73298bc993fSAl Viro 	err = kern_path(old, 0, &path);
73374c3cbe3SAl Viro 	if (err) {
73474c3cbe3SAl Viro 		drop_collected_mounts(tagged);
73574c3cbe3SAl Viro 		return err;
73674c3cbe3SAl Viro 	}
73798bc993fSAl Viro 	mnt = mntget(path.mnt);
73898bc993fSAl Viro 	dentry = dget(path.dentry);
73998bc993fSAl Viro 	path_put(&path);
74074c3cbe3SAl Viro 
74174c3cbe3SAl Viro 	list_add_tail(&list, &tagged->mnt_list);
74274c3cbe3SAl Viro 
74374c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
74474c3cbe3SAl Viro 	list_add(&barrier, &tree_list);
74574c3cbe3SAl Viro 	list_add(&cursor, &barrier);
74674c3cbe3SAl Viro 
74774c3cbe3SAl Viro 	while (cursor.next != &tree_list) {
74874c3cbe3SAl Viro 		struct audit_tree *tree;
74974c3cbe3SAl Viro 		struct vfsmount *p;
75074c3cbe3SAl Viro 
75174c3cbe3SAl Viro 		tree = container_of(cursor.next, struct audit_tree, list);
75274c3cbe3SAl Viro 		get_tree(tree);
75374c3cbe3SAl Viro 		list_del(&cursor);
75474c3cbe3SAl Viro 		list_add(&cursor, &tree->list);
75574c3cbe3SAl Viro 		mutex_unlock(&audit_filter_mutex);
75674c3cbe3SAl Viro 
75798bc993fSAl Viro 		err = kern_path(tree->pathname, 0, &path);
75874c3cbe3SAl Viro 		if (err) {
75974c3cbe3SAl Viro 			put_tree(tree);
76074c3cbe3SAl Viro 			mutex_lock(&audit_filter_mutex);
76174c3cbe3SAl Viro 			continue;
76274c3cbe3SAl Viro 		}
76374c3cbe3SAl Viro 
76474c3cbe3SAl Viro 		spin_lock(&vfsmount_lock);
76598bc993fSAl Viro 		if (!is_under(mnt, dentry, &path)) {
76674c3cbe3SAl Viro 			spin_unlock(&vfsmount_lock);
76798bc993fSAl Viro 			path_put(&path);
76874c3cbe3SAl Viro 			put_tree(tree);
76974c3cbe3SAl Viro 			mutex_lock(&audit_filter_mutex);
77074c3cbe3SAl Viro 			continue;
77174c3cbe3SAl Viro 		}
77274c3cbe3SAl Viro 		spin_unlock(&vfsmount_lock);
77398bc993fSAl Viro 		path_put(&path);
77474c3cbe3SAl Viro 
77574c3cbe3SAl Viro 		list_for_each_entry(p, &list, mnt_list) {
77674c3cbe3SAl Viro 			failed = tag_chunk(p->mnt_root->d_inode, tree);
77774c3cbe3SAl Viro 			if (failed)
77874c3cbe3SAl Viro 				break;
77974c3cbe3SAl Viro 		}
78074c3cbe3SAl Viro 
78174c3cbe3SAl Viro 		if (failed) {
78274c3cbe3SAl Viro 			put_tree(tree);
78374c3cbe3SAl Viro 			mutex_lock(&audit_filter_mutex);
78474c3cbe3SAl Viro 			break;
78574c3cbe3SAl Viro 		}
78674c3cbe3SAl Viro 
78774c3cbe3SAl Viro 		mutex_lock(&audit_filter_mutex);
78874c3cbe3SAl Viro 		spin_lock(&hash_lock);
78974c3cbe3SAl Viro 		if (!tree->goner) {
79074c3cbe3SAl Viro 			list_del(&tree->list);
79174c3cbe3SAl Viro 			list_add(&tree->list, &tree_list);
79274c3cbe3SAl Viro 		}
79374c3cbe3SAl Viro 		spin_unlock(&hash_lock);
79474c3cbe3SAl Viro 		put_tree(tree);
79574c3cbe3SAl Viro 	}
79674c3cbe3SAl Viro 
79774c3cbe3SAl Viro 	while (barrier.prev != &tree_list) {
79874c3cbe3SAl Viro 		struct audit_tree *tree;
79974c3cbe3SAl Viro 
80074c3cbe3SAl Viro 		tree = container_of(barrier.prev, struct audit_tree, list);
80174c3cbe3SAl Viro 		get_tree(tree);
80274c3cbe3SAl Viro 		list_del(&tree->list);
80374c3cbe3SAl Viro 		list_add(&tree->list, &barrier);
80474c3cbe3SAl Viro 		mutex_unlock(&audit_filter_mutex);
80574c3cbe3SAl Viro 
80674c3cbe3SAl Viro 		if (!failed) {
80774c3cbe3SAl Viro 			struct node *node;
80874c3cbe3SAl Viro 			spin_lock(&hash_lock);
80974c3cbe3SAl Viro 			list_for_each_entry(node, &tree->chunks, list)
81074c3cbe3SAl Viro 				node->index &= ~(1U<<31);
81174c3cbe3SAl Viro 			spin_unlock(&hash_lock);
81274c3cbe3SAl Viro 		} else {
81374c3cbe3SAl Viro 			trim_marked(tree);
81474c3cbe3SAl Viro 		}
81574c3cbe3SAl Viro 
81674c3cbe3SAl Viro 		put_tree(tree);
81774c3cbe3SAl Viro 		mutex_lock(&audit_filter_mutex);
81874c3cbe3SAl Viro 	}
81974c3cbe3SAl Viro 	list_del(&barrier);
82074c3cbe3SAl Viro 	list_del(&cursor);
82174c3cbe3SAl Viro 	list_del(&list);
82274c3cbe3SAl Viro 	mutex_unlock(&audit_filter_mutex);
82374c3cbe3SAl Viro 	dput(dentry);
82474c3cbe3SAl Viro 	mntput(mnt);
82574c3cbe3SAl Viro 	drop_collected_mounts(tagged);
82674c3cbe3SAl Viro 	return failed;
82774c3cbe3SAl Viro }
82874c3cbe3SAl Viro 
82974c3cbe3SAl Viro /*
83074c3cbe3SAl Viro  * That gets run when evict_chunk() ends up needing to kill audit_tree.
831916d7576SAl Viro  * Runs from a separate thread.
83274c3cbe3SAl Viro  */
833916d7576SAl Viro static int prune_tree_thread(void *unused)
83474c3cbe3SAl Viro {
835916d7576SAl Viro 	mutex_lock(&audit_cmd_mutex);
83674c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
83774c3cbe3SAl Viro 
83874c3cbe3SAl Viro 	while (!list_empty(&prune_list)) {
83974c3cbe3SAl Viro 		struct audit_tree *victim;
84074c3cbe3SAl Viro 
84174c3cbe3SAl Viro 		victim = list_entry(prune_list.next, struct audit_tree, list);
84274c3cbe3SAl Viro 		list_del_init(&victim->list);
84374c3cbe3SAl Viro 
84474c3cbe3SAl Viro 		mutex_unlock(&audit_filter_mutex);
84574c3cbe3SAl Viro 
84674c3cbe3SAl Viro 		prune_one(victim);
84774c3cbe3SAl Viro 
84874c3cbe3SAl Viro 		mutex_lock(&audit_filter_mutex);
84974c3cbe3SAl Viro 	}
85074c3cbe3SAl Viro 
85174c3cbe3SAl Viro 	mutex_unlock(&audit_filter_mutex);
852916d7576SAl Viro 	mutex_unlock(&audit_cmd_mutex);
853916d7576SAl Viro 	return 0;
854916d7576SAl Viro }
855916d7576SAl Viro 
856916d7576SAl Viro static void audit_schedule_prune(void)
857916d7576SAl Viro {
858916d7576SAl Viro 	kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
859916d7576SAl Viro }
860916d7576SAl Viro 
861916d7576SAl Viro /*
862916d7576SAl Viro  * ... and that one is done if evict_chunk() decides to delay until the end
863916d7576SAl Viro  * of syscall.  Runs synchronously.
864916d7576SAl Viro  */
865916d7576SAl Viro void audit_kill_trees(struct list_head *list)
866916d7576SAl Viro {
867916d7576SAl Viro 	mutex_lock(&audit_cmd_mutex);
868916d7576SAl Viro 	mutex_lock(&audit_filter_mutex);
869916d7576SAl Viro 
870916d7576SAl Viro 	while (!list_empty(list)) {
871916d7576SAl Viro 		struct audit_tree *victim;
872916d7576SAl Viro 
873916d7576SAl Viro 		victim = list_entry(list->next, struct audit_tree, list);
874916d7576SAl Viro 		kill_rules(victim);
875916d7576SAl Viro 		list_del_init(&victim->list);
876916d7576SAl Viro 
877916d7576SAl Viro 		mutex_unlock(&audit_filter_mutex);
878916d7576SAl Viro 
879916d7576SAl Viro 		prune_one(victim);
880916d7576SAl Viro 
881916d7576SAl Viro 		mutex_lock(&audit_filter_mutex);
882916d7576SAl Viro 	}
883916d7576SAl Viro 
884916d7576SAl Viro 	mutex_unlock(&audit_filter_mutex);
885916d7576SAl Viro 	mutex_unlock(&audit_cmd_mutex);
88674c3cbe3SAl Viro }
88774c3cbe3SAl Viro 
88874c3cbe3SAl Viro /*
88974c3cbe3SAl Viro  *  Here comes the stuff asynchronous to auditctl operations
89074c3cbe3SAl Viro  */
89174c3cbe3SAl Viro 
89274c3cbe3SAl Viro /* inode->inotify_mutex is locked */
89374c3cbe3SAl Viro static void evict_chunk(struct audit_chunk *chunk)
89474c3cbe3SAl Viro {
89574c3cbe3SAl Viro 	struct audit_tree *owner;
896916d7576SAl Viro 	struct list_head *postponed = audit_killed_trees();
897916d7576SAl Viro 	int need_prune = 0;
89874c3cbe3SAl Viro 	int n;
89974c3cbe3SAl Viro 
90074c3cbe3SAl Viro 	if (chunk->dead)
90174c3cbe3SAl Viro 		return;
90274c3cbe3SAl Viro 
90374c3cbe3SAl Viro 	chunk->dead = 1;
90474c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
90574c3cbe3SAl Viro 	spin_lock(&hash_lock);
90674c3cbe3SAl Viro 	while (!list_empty(&chunk->trees)) {
90774c3cbe3SAl Viro 		owner = list_entry(chunk->trees.next,
90874c3cbe3SAl Viro 				   struct audit_tree, same_root);
90974c3cbe3SAl Viro 		owner->goner = 1;
91074c3cbe3SAl Viro 		owner->root = NULL;
91174c3cbe3SAl Viro 		list_del_init(&owner->same_root);
91274c3cbe3SAl Viro 		spin_unlock(&hash_lock);
913916d7576SAl Viro 		if (!postponed) {
91474c3cbe3SAl Viro 			kill_rules(owner);
91574c3cbe3SAl Viro 			list_move(&owner->list, &prune_list);
916916d7576SAl Viro 			need_prune = 1;
917916d7576SAl Viro 		} else {
918916d7576SAl Viro 			list_move(&owner->list, postponed);
919916d7576SAl Viro 		}
92074c3cbe3SAl Viro 		spin_lock(&hash_lock);
92174c3cbe3SAl Viro 	}
92274c3cbe3SAl Viro 	list_del_rcu(&chunk->hash);
92374c3cbe3SAl Viro 	for (n = 0; n < chunk->count; n++)
92474c3cbe3SAl Viro 		list_del_init(&chunk->owners[n].list);
92574c3cbe3SAl Viro 	spin_unlock(&hash_lock);
926916d7576SAl Viro 	if (need_prune)
927916d7576SAl Viro 		audit_schedule_prune();
92874c3cbe3SAl Viro 	mutex_unlock(&audit_filter_mutex);
92974c3cbe3SAl Viro }
93074c3cbe3SAl Viro 
93174c3cbe3SAl Viro static void handle_event(struct inotify_watch *watch, u32 wd, u32 mask,
93274c3cbe3SAl Viro                          u32 cookie, const char *dname, struct inode *inode)
93374c3cbe3SAl Viro {
93474c3cbe3SAl Viro 	struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch);
93574c3cbe3SAl Viro 
93674c3cbe3SAl Viro 	if (mask & IN_IGNORED) {
93774c3cbe3SAl Viro 		evict_chunk(chunk);
93874c3cbe3SAl Viro 		put_inotify_watch(watch);
93974c3cbe3SAl Viro 	}
94074c3cbe3SAl Viro }
94174c3cbe3SAl Viro 
94274c3cbe3SAl Viro static void destroy_watch(struct inotify_watch *watch)
94374c3cbe3SAl Viro {
94474c3cbe3SAl Viro 	struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch);
9458f7b0ba1SAl Viro 	call_rcu(&chunk->head, __put_chunk);
94674c3cbe3SAl Viro }
94774c3cbe3SAl Viro 
94874c3cbe3SAl Viro static const struct inotify_operations rtree_inotify_ops = {
94974c3cbe3SAl Viro 	.handle_event	= handle_event,
95074c3cbe3SAl Viro 	.destroy_watch	= destroy_watch,
95174c3cbe3SAl Viro };
95274c3cbe3SAl Viro 
95374c3cbe3SAl Viro static int __init audit_tree_init(void)
95474c3cbe3SAl Viro {
95574c3cbe3SAl Viro 	int i;
95674c3cbe3SAl Viro 
95774c3cbe3SAl Viro 	rtree_ih = inotify_init(&rtree_inotify_ops);
95874c3cbe3SAl Viro 	if (IS_ERR(rtree_ih))
95974c3cbe3SAl Viro 		audit_panic("cannot initialize inotify handle for rectree watches");
96074c3cbe3SAl Viro 
96174c3cbe3SAl Viro 	for (i = 0; i < HASH_SIZE; i++)
96274c3cbe3SAl Viro 		INIT_LIST_HEAD(&chunk_hash_heads[i]);
96374c3cbe3SAl Viro 
96474c3cbe3SAl Viro 	return 0;
96574c3cbe3SAl Viro }
96674c3cbe3SAl Viro __initcall(audit_tree_init);
967