xref: /openbmc/linux/kernel/audit_tree.c (revision ab97f873)
174c3cbe3SAl Viro #include "audit.h"
228a3a7ebSEric Paris #include <linux/fsnotify_backend.h>
374c3cbe3SAl Viro #include <linux/namei.h>
474c3cbe3SAl Viro #include <linux/mount.h>
5916d7576SAl Viro #include <linux/kthread.h>
69d2378f8SElena Reshetova #include <linux/refcount.h>
75a0e3ad6STejun Heo #include <linux/slab.h>
874c3cbe3SAl Viro 
974c3cbe3SAl Viro struct audit_tree;
1074c3cbe3SAl Viro struct audit_chunk;
1174c3cbe3SAl Viro 
1274c3cbe3SAl Viro struct audit_tree {
139d2378f8SElena Reshetova 	refcount_t count;
1474c3cbe3SAl Viro 	int goner;
1574c3cbe3SAl Viro 	struct audit_chunk *root;
1674c3cbe3SAl Viro 	struct list_head chunks;
1774c3cbe3SAl Viro 	struct list_head rules;
1874c3cbe3SAl Viro 	struct list_head list;
1974c3cbe3SAl Viro 	struct list_head same_root;
2074c3cbe3SAl Viro 	struct rcu_head head;
2174c3cbe3SAl Viro 	char pathname[];
2274c3cbe3SAl Viro };
2374c3cbe3SAl Viro 
2474c3cbe3SAl Viro struct audit_chunk {
2574c3cbe3SAl Viro 	struct list_head hash;
26e61ce867SEric Paris 	struct fsnotify_mark mark;
2774c3cbe3SAl Viro 	struct list_head trees;		/* with root here */
2874c3cbe3SAl Viro 	int dead;
2974c3cbe3SAl Viro 	int count;
308f7b0ba1SAl Viro 	atomic_long_t refs;
3174c3cbe3SAl Viro 	struct rcu_head head;
3274c3cbe3SAl Viro 	struct node {
3374c3cbe3SAl Viro 		struct list_head list;
3474c3cbe3SAl Viro 		struct audit_tree *owner;
3574c3cbe3SAl Viro 		unsigned index;		/* index; upper bit indicates 'will prune' */
3674c3cbe3SAl Viro 	} owners[];
3774c3cbe3SAl Viro };
3874c3cbe3SAl Viro 
3974c3cbe3SAl Viro static LIST_HEAD(tree_list);
4074c3cbe3SAl Viro static LIST_HEAD(prune_list);
41f1aaf262SImre Palik static struct task_struct *prune_thread;
4274c3cbe3SAl Viro 
4374c3cbe3SAl Viro /*
4474c3cbe3SAl Viro  * One struct chunk is attached to each inode of interest.
4574c3cbe3SAl Viro  * We replace struct chunk on tagging/untagging.
4674c3cbe3SAl Viro  * Rules have pointer to struct audit_tree.
4774c3cbe3SAl Viro  * Rules have struct list_head rlist forming a list of rules over
4874c3cbe3SAl Viro  * the same tree.
4974c3cbe3SAl Viro  * References to struct chunk are collected at audit_inode{,_child}()
5074c3cbe3SAl Viro  * time and used in AUDIT_TREE rule matching.
5174c3cbe3SAl Viro  * These references are dropped at the same time we are calling
5274c3cbe3SAl Viro  * audit_free_names(), etc.
5374c3cbe3SAl Viro  *
5474c3cbe3SAl Viro  * Cyclic lists galore:
5574c3cbe3SAl Viro  * tree.chunks anchors chunk.owners[].list			hash_lock
5674c3cbe3SAl Viro  * tree.rules anchors rule.rlist				audit_filter_mutex
5774c3cbe3SAl Viro  * chunk.trees anchors tree.same_root				hash_lock
5874c3cbe3SAl Viro  * chunk.hash is a hash with middle bits of watch.inode as
5974c3cbe3SAl Viro  * a hash function.						RCU, hash_lock
6074c3cbe3SAl Viro  *
6174c3cbe3SAl Viro  * tree is refcounted; one reference for "some rules on rules_list refer to
6274c3cbe3SAl Viro  * it", one for each chunk with pointer to it.
6374c3cbe3SAl Viro  *
6428a3a7ebSEric Paris  * chunk is refcounted by embedded fsnotify_mark + .refs (non-zero refcount
658f7b0ba1SAl Viro  * of watch contributes 1 to .refs).
6674c3cbe3SAl Viro  *
6774c3cbe3SAl Viro  * node.index allows to get from node.list to containing chunk.
6874c3cbe3SAl Viro  * MSB of that sucker is stolen to mark taggings that we might have to
6974c3cbe3SAl Viro  * revert - several operations have very unpleasant cleanup logics and
7074c3cbe3SAl Viro  * that makes a difference.  Some.
7174c3cbe3SAl Viro  */
7274c3cbe3SAl Viro 
7328a3a7ebSEric Paris static struct fsnotify_group *audit_tree_group;
7474c3cbe3SAl Viro 
7574c3cbe3SAl Viro static struct audit_tree *alloc_tree(const char *s)
7674c3cbe3SAl Viro {
7774c3cbe3SAl Viro 	struct audit_tree *tree;
7874c3cbe3SAl Viro 
7974c3cbe3SAl Viro 	tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL);
8074c3cbe3SAl Viro 	if (tree) {
819d2378f8SElena Reshetova 		refcount_set(&tree->count, 1);
8274c3cbe3SAl Viro 		tree->goner = 0;
8374c3cbe3SAl Viro 		INIT_LIST_HEAD(&tree->chunks);
8474c3cbe3SAl Viro 		INIT_LIST_HEAD(&tree->rules);
8574c3cbe3SAl Viro 		INIT_LIST_HEAD(&tree->list);
8674c3cbe3SAl Viro 		INIT_LIST_HEAD(&tree->same_root);
8774c3cbe3SAl Viro 		tree->root = NULL;
8874c3cbe3SAl Viro 		strcpy(tree->pathname, s);
8974c3cbe3SAl Viro 	}
9074c3cbe3SAl Viro 	return tree;
9174c3cbe3SAl Viro }
9274c3cbe3SAl Viro 
9374c3cbe3SAl Viro static inline void get_tree(struct audit_tree *tree)
9474c3cbe3SAl Viro {
959d2378f8SElena Reshetova 	refcount_inc(&tree->count);
9674c3cbe3SAl Viro }
9774c3cbe3SAl Viro 
9874c3cbe3SAl Viro static inline void put_tree(struct audit_tree *tree)
9974c3cbe3SAl Viro {
1009d2378f8SElena Reshetova 	if (refcount_dec_and_test(&tree->count))
1013b097c46SLai Jiangshan 		kfree_rcu(tree, head);
10274c3cbe3SAl Viro }
10374c3cbe3SAl Viro 
10474c3cbe3SAl Viro /* to avoid bringing the entire thing in audit.h */
10574c3cbe3SAl Viro const char *audit_tree_path(struct audit_tree *tree)
10674c3cbe3SAl Viro {
10774c3cbe3SAl Viro 	return tree->pathname;
10874c3cbe3SAl Viro }
10974c3cbe3SAl Viro 
1108f7b0ba1SAl Viro static void free_chunk(struct audit_chunk *chunk)
11174c3cbe3SAl Viro {
11274c3cbe3SAl Viro 	int i;
11374c3cbe3SAl Viro 
11474c3cbe3SAl Viro 	for (i = 0; i < chunk->count; i++) {
11574c3cbe3SAl Viro 		if (chunk->owners[i].owner)
11674c3cbe3SAl Viro 			put_tree(chunk->owners[i].owner);
11774c3cbe3SAl Viro 	}
11874c3cbe3SAl Viro 	kfree(chunk);
11974c3cbe3SAl Viro }
12074c3cbe3SAl Viro 
12174c3cbe3SAl Viro void audit_put_chunk(struct audit_chunk *chunk)
12274c3cbe3SAl Viro {
1238f7b0ba1SAl Viro 	if (atomic_long_dec_and_test(&chunk->refs))
1248f7b0ba1SAl Viro 		free_chunk(chunk);
1258f7b0ba1SAl Viro }
1268f7b0ba1SAl Viro 
1278f7b0ba1SAl Viro static void __put_chunk(struct rcu_head *rcu)
1288f7b0ba1SAl Viro {
1298f7b0ba1SAl Viro 	struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
1308f7b0ba1SAl Viro 	audit_put_chunk(chunk);
13174c3cbe3SAl Viro }
13274c3cbe3SAl Viro 
133e61ce867SEric Paris static void audit_tree_destroy_watch(struct fsnotify_mark *entry)
13428a3a7ebSEric Paris {
13528a3a7ebSEric Paris 	struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark);
13628a3a7ebSEric Paris 	call_rcu(&chunk->head, __put_chunk);
13728a3a7ebSEric Paris }
13828a3a7ebSEric Paris 
13928a3a7ebSEric Paris static struct audit_chunk *alloc_chunk(int count)
14028a3a7ebSEric Paris {
14128a3a7ebSEric Paris 	struct audit_chunk *chunk;
14228a3a7ebSEric Paris 	size_t size;
14328a3a7ebSEric Paris 	int i;
14428a3a7ebSEric Paris 
14528a3a7ebSEric Paris 	size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node);
14628a3a7ebSEric Paris 	chunk = kzalloc(size, GFP_KERNEL);
14728a3a7ebSEric Paris 	if (!chunk)
14828a3a7ebSEric Paris 		return NULL;
14928a3a7ebSEric Paris 
15028a3a7ebSEric Paris 	INIT_LIST_HEAD(&chunk->hash);
15128a3a7ebSEric Paris 	INIT_LIST_HEAD(&chunk->trees);
15228a3a7ebSEric Paris 	chunk->count = count;
15328a3a7ebSEric Paris 	atomic_long_set(&chunk->refs, 1);
15428a3a7ebSEric Paris 	for (i = 0; i < count; i++) {
15528a3a7ebSEric Paris 		INIT_LIST_HEAD(&chunk->owners[i].list);
15628a3a7ebSEric Paris 		chunk->owners[i].index = i;
15728a3a7ebSEric Paris 	}
158054c636eSJan Kara 	fsnotify_init_mark(&chunk->mark, audit_tree_group);
159799b6014SMiklos Szeredi 	chunk->mark.mask = FS_IN_IGNORED;
16028a3a7ebSEric Paris 	return chunk;
16128a3a7ebSEric Paris }
16228a3a7ebSEric Paris 
16374c3cbe3SAl Viro enum {HASH_SIZE = 128};
16474c3cbe3SAl Viro static struct list_head chunk_hash_heads[HASH_SIZE];
16574c3cbe3SAl Viro static __cacheline_aligned_in_smp DEFINE_SPINLOCK(hash_lock);
16674c3cbe3SAl Viro 
167f410ff65SJan Kara /* Function to return search key in our hash from inode. */
168f410ff65SJan Kara static unsigned long inode_to_key(const struct inode *inode)
16974c3cbe3SAl Viro {
170f410ff65SJan Kara 	return (unsigned long)inode;
171f410ff65SJan Kara }
172f410ff65SJan Kara 
173f410ff65SJan Kara /*
174f410ff65SJan Kara  * Function to return search key in our hash from chunk. Key 0 is special and
175f410ff65SJan Kara  * should never be present in the hash.
176f410ff65SJan Kara  */
177f410ff65SJan Kara static unsigned long chunk_to_key(struct audit_chunk *chunk)
178f410ff65SJan Kara {
1796b3f05d2SJan Kara 	/*
1806b3f05d2SJan Kara 	 * We have a reference to the mark so it should be attached to a
1816b3f05d2SJan Kara 	 * connector.
1826b3f05d2SJan Kara 	 */
1836b3f05d2SJan Kara 	if (WARN_ON_ONCE(!chunk->mark.connector))
1846b3f05d2SJan Kara 		return 0;
1856b3f05d2SJan Kara 	return (unsigned long)chunk->mark.connector->inode;
186f410ff65SJan Kara }
187f410ff65SJan Kara 
188f410ff65SJan Kara static inline struct list_head *chunk_hash(unsigned long key)
189f410ff65SJan Kara {
190f410ff65SJan Kara 	unsigned long n = key / L1_CACHE_BYTES;
19174c3cbe3SAl Viro 	return chunk_hash_heads + n % HASH_SIZE;
19274c3cbe3SAl Viro }
19374c3cbe3SAl Viro 
19428a3a7ebSEric Paris /* hash_lock & entry->lock is held by caller */
19574c3cbe3SAl Viro static void insert_hash(struct audit_chunk *chunk)
19674c3cbe3SAl Viro {
1976b3f05d2SJan Kara 	unsigned long key = chunk_to_key(chunk);
19828a3a7ebSEric Paris 	struct list_head *list;
19928a3a7ebSEric Paris 
20043471d15SJan Kara 	if (!(chunk->mark.flags & FSNOTIFY_MARK_FLAG_ATTACHED))
20128a3a7ebSEric Paris 		return;
202f410ff65SJan Kara 	list = chunk_hash(key);
20374c3cbe3SAl Viro 	list_add_rcu(&chunk->hash, list);
20474c3cbe3SAl Viro }
20574c3cbe3SAl Viro 
20674c3cbe3SAl Viro /* called under rcu_read_lock */
20774c3cbe3SAl Viro struct audit_chunk *audit_tree_lookup(const struct inode *inode)
20874c3cbe3SAl Viro {
209f410ff65SJan Kara 	unsigned long key = inode_to_key(inode);
210f410ff65SJan Kara 	struct list_head *list = chunk_hash(key);
2116793a051SPaul E. McKenney 	struct audit_chunk *p;
21274c3cbe3SAl Viro 
2136793a051SPaul E. McKenney 	list_for_each_entry_rcu(p, list, hash) {
214f410ff65SJan Kara 		if (chunk_to_key(p) == key) {
2158f7b0ba1SAl Viro 			atomic_long_inc(&p->refs);
21674c3cbe3SAl Viro 			return p;
21774c3cbe3SAl Viro 		}
21874c3cbe3SAl Viro 	}
21974c3cbe3SAl Viro 	return NULL;
22074c3cbe3SAl Viro }
22174c3cbe3SAl Viro 
2226f1b5d7aSYaowei Bai bool audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree)
22374c3cbe3SAl Viro {
22474c3cbe3SAl Viro 	int n;
22574c3cbe3SAl Viro 	for (n = 0; n < chunk->count; n++)
22674c3cbe3SAl Viro 		if (chunk->owners[n].owner == tree)
2276f1b5d7aSYaowei Bai 			return true;
2286f1b5d7aSYaowei Bai 	return false;
22974c3cbe3SAl Viro }
23074c3cbe3SAl Viro 
23174c3cbe3SAl Viro /* tagging and untagging inodes with trees */
23274c3cbe3SAl Viro 
2338f7b0ba1SAl Viro static struct audit_chunk *find_chunk(struct node *p)
23474c3cbe3SAl Viro {
2358f7b0ba1SAl Viro 	int index = p->index & ~(1U<<31);
2368f7b0ba1SAl Viro 	p -= index;
2378f7b0ba1SAl Viro 	return container_of(p, struct audit_chunk, owners[0]);
2388f7b0ba1SAl Viro }
2398f7b0ba1SAl Viro 
2408f7b0ba1SAl Viro static void untag_chunk(struct node *p)
2418f7b0ba1SAl Viro {
2428f7b0ba1SAl Viro 	struct audit_chunk *chunk = find_chunk(p);
243e61ce867SEric Paris 	struct fsnotify_mark *entry = &chunk->mark;
244f7a998a9SAl Viro 	struct audit_chunk *new = NULL;
24574c3cbe3SAl Viro 	struct audit_tree *owner;
24674c3cbe3SAl Viro 	int size = chunk->count - 1;
24774c3cbe3SAl Viro 	int i, j;
24874c3cbe3SAl Viro 
24928a3a7ebSEric Paris 	fsnotify_get_mark(entry);
2508f7b0ba1SAl Viro 
2518f7b0ba1SAl Viro 	spin_unlock(&hash_lock);
2528f7b0ba1SAl Viro 
253f7a998a9SAl Viro 	if (size)
254f7a998a9SAl Viro 		new = alloc_chunk(size);
255f7a998a9SAl Viro 
256be29d20fSJan Kara 	mutex_lock(&entry->group->mark_mutex);
25728a3a7ebSEric Paris 	spin_lock(&entry->lock);
2586b3f05d2SJan Kara 	/*
2596b3f05d2SJan Kara 	 * mark_mutex protects mark from getting detached and thus also from
2606b3f05d2SJan Kara 	 * mark->connector->inode getting NULL.
2616b3f05d2SJan Kara 	 */
26243471d15SJan Kara 	if (chunk->dead || !(entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) {
26328a3a7ebSEric Paris 		spin_unlock(&entry->lock);
264be29d20fSJan Kara 		mutex_unlock(&entry->group->mark_mutex);
265f7a998a9SAl Viro 		if (new)
2667b129323SJan Kara 			fsnotify_put_mark(&new->mark);
2678f7b0ba1SAl Viro 		goto out;
26874c3cbe3SAl Viro 	}
26974c3cbe3SAl Viro 
27074c3cbe3SAl Viro 	owner = p->owner;
27174c3cbe3SAl Viro 
27274c3cbe3SAl Viro 	if (!size) {
27374c3cbe3SAl Viro 		chunk->dead = 1;
27474c3cbe3SAl Viro 		spin_lock(&hash_lock);
27574c3cbe3SAl Viro 		list_del_init(&chunk->trees);
27674c3cbe3SAl Viro 		if (owner->root == chunk)
27774c3cbe3SAl Viro 			owner->root = NULL;
27874c3cbe3SAl Viro 		list_del_init(&p->list);
27974c3cbe3SAl Viro 		list_del_rcu(&chunk->hash);
28074c3cbe3SAl Viro 		spin_unlock(&hash_lock);
28128a3a7ebSEric Paris 		spin_unlock(&entry->lock);
282be29d20fSJan Kara 		mutex_unlock(&entry->group->mark_mutex);
283e2a29943SLino Sanfilippo 		fsnotify_destroy_mark(entry, audit_tree_group);
2848f7b0ba1SAl Viro 		goto out;
28574c3cbe3SAl Viro 	}
28674c3cbe3SAl Viro 
28774c3cbe3SAl Viro 	if (!new)
28874c3cbe3SAl Viro 		goto Fallback;
289f7a998a9SAl Viro 
2907b129323SJan Kara 	if (fsnotify_add_mark_locked(&new->mark, entry->connector->inode,
291be29d20fSJan Kara 				     NULL, 1)) {
2920fe33aaeSMiklos Szeredi 		fsnotify_put_mark(&new->mark);
29374c3cbe3SAl Viro 		goto Fallback;
29474c3cbe3SAl Viro 	}
29574c3cbe3SAl Viro 
29674c3cbe3SAl Viro 	chunk->dead = 1;
29774c3cbe3SAl Viro 	spin_lock(&hash_lock);
29874c3cbe3SAl Viro 	list_replace_init(&chunk->trees, &new->trees);
29974c3cbe3SAl Viro 	if (owner->root == chunk) {
30074c3cbe3SAl Viro 		list_del_init(&owner->same_root);
30174c3cbe3SAl Viro 		owner->root = NULL;
30274c3cbe3SAl Viro 	}
30374c3cbe3SAl Viro 
3046f5d5114SAl Viro 	for (i = j = 0; j <= size; i++, j++) {
30574c3cbe3SAl Viro 		struct audit_tree *s;
30674c3cbe3SAl Viro 		if (&chunk->owners[j] == p) {
30774c3cbe3SAl Viro 			list_del_init(&p->list);
30874c3cbe3SAl Viro 			i--;
30974c3cbe3SAl Viro 			continue;
31074c3cbe3SAl Viro 		}
31174c3cbe3SAl Viro 		s = chunk->owners[j].owner;
31274c3cbe3SAl Viro 		new->owners[i].owner = s;
31374c3cbe3SAl Viro 		new->owners[i].index = chunk->owners[j].index - j + i;
31474c3cbe3SAl Viro 		if (!s) /* result of earlier fallback */
31574c3cbe3SAl Viro 			continue;
31674c3cbe3SAl Viro 		get_tree(s);
3176f5d5114SAl Viro 		list_replace_init(&chunk->owners[j].list, &new->owners[i].list);
31874c3cbe3SAl Viro 	}
31974c3cbe3SAl Viro 
32074c3cbe3SAl Viro 	list_replace_rcu(&chunk->hash, &new->hash);
32174c3cbe3SAl Viro 	list_for_each_entry(owner, &new->trees, same_root)
32274c3cbe3SAl Viro 		owner->root = new;
32374c3cbe3SAl Viro 	spin_unlock(&hash_lock);
32428a3a7ebSEric Paris 	spin_unlock(&entry->lock);
325be29d20fSJan Kara 	mutex_unlock(&entry->group->mark_mutex);
326e2a29943SLino Sanfilippo 	fsnotify_destroy_mark(entry, audit_tree_group);
327b3e8692bSMiklos Szeredi 	fsnotify_put_mark(&new->mark);	/* drop initial reference */
3288f7b0ba1SAl Viro 	goto out;
32974c3cbe3SAl Viro 
33074c3cbe3SAl Viro Fallback:
33174c3cbe3SAl Viro 	// do the best we can
33274c3cbe3SAl Viro 	spin_lock(&hash_lock);
33374c3cbe3SAl Viro 	if (owner->root == chunk) {
33474c3cbe3SAl Viro 		list_del_init(&owner->same_root);
33574c3cbe3SAl Viro 		owner->root = NULL;
33674c3cbe3SAl Viro 	}
33774c3cbe3SAl Viro 	list_del_init(&p->list);
33874c3cbe3SAl Viro 	p->owner = NULL;
33974c3cbe3SAl Viro 	put_tree(owner);
34074c3cbe3SAl Viro 	spin_unlock(&hash_lock);
34128a3a7ebSEric Paris 	spin_unlock(&entry->lock);
342be29d20fSJan Kara 	mutex_unlock(&entry->group->mark_mutex);
3438f7b0ba1SAl Viro out:
34428a3a7ebSEric Paris 	fsnotify_put_mark(entry);
3458f7b0ba1SAl Viro 	spin_lock(&hash_lock);
34674c3cbe3SAl Viro }
34774c3cbe3SAl Viro 
34874c3cbe3SAl Viro static int create_chunk(struct inode *inode, struct audit_tree *tree)
34974c3cbe3SAl Viro {
350e61ce867SEric Paris 	struct fsnotify_mark *entry;
35174c3cbe3SAl Viro 	struct audit_chunk *chunk = alloc_chunk(1);
35274c3cbe3SAl Viro 	if (!chunk)
35374c3cbe3SAl Viro 		return -ENOMEM;
35474c3cbe3SAl Viro 
35528a3a7ebSEric Paris 	entry = &chunk->mark;
3567b129323SJan Kara 	if (fsnotify_add_mark(entry, inode, NULL, 0)) {
3570fe33aaeSMiklos Szeredi 		fsnotify_put_mark(entry);
35874c3cbe3SAl Viro 		return -ENOSPC;
35974c3cbe3SAl Viro 	}
36074c3cbe3SAl Viro 
36128a3a7ebSEric Paris 	spin_lock(&entry->lock);
36274c3cbe3SAl Viro 	spin_lock(&hash_lock);
36374c3cbe3SAl Viro 	if (tree->goner) {
36474c3cbe3SAl Viro 		spin_unlock(&hash_lock);
36574c3cbe3SAl Viro 		chunk->dead = 1;
36628a3a7ebSEric Paris 		spin_unlock(&entry->lock);
367e2a29943SLino Sanfilippo 		fsnotify_destroy_mark(entry, audit_tree_group);
36828a3a7ebSEric Paris 		fsnotify_put_mark(entry);
36974c3cbe3SAl Viro 		return 0;
37074c3cbe3SAl Viro 	}
37174c3cbe3SAl Viro 	chunk->owners[0].index = (1U << 31);
37274c3cbe3SAl Viro 	chunk->owners[0].owner = tree;
37374c3cbe3SAl Viro 	get_tree(tree);
37474c3cbe3SAl Viro 	list_add(&chunk->owners[0].list, &tree->chunks);
37574c3cbe3SAl Viro 	if (!tree->root) {
37674c3cbe3SAl Viro 		tree->root = chunk;
37774c3cbe3SAl Viro 		list_add(&tree->same_root, &chunk->trees);
37874c3cbe3SAl Viro 	}
37974c3cbe3SAl Viro 	insert_hash(chunk);
38074c3cbe3SAl Viro 	spin_unlock(&hash_lock);
38128a3a7ebSEric Paris 	spin_unlock(&entry->lock);
382b3e8692bSMiklos Szeredi 	fsnotify_put_mark(entry);	/* drop initial reference */
38374c3cbe3SAl Viro 	return 0;
38474c3cbe3SAl Viro }
38574c3cbe3SAl Viro 
38674c3cbe3SAl Viro /* the first tagged inode becomes root of tree */
38774c3cbe3SAl Viro static int tag_chunk(struct inode *inode, struct audit_tree *tree)
38874c3cbe3SAl Viro {
389e61ce867SEric Paris 	struct fsnotify_mark *old_entry, *chunk_entry;
39074c3cbe3SAl Viro 	struct audit_tree *owner;
39174c3cbe3SAl Viro 	struct audit_chunk *chunk, *old;
39274c3cbe3SAl Viro 	struct node *p;
39374c3cbe3SAl Viro 	int n;
39474c3cbe3SAl Viro 
395b1362edfSJan Kara 	old_entry = fsnotify_find_mark(&inode->i_fsnotify_marks,
396b1362edfSJan Kara 				       audit_tree_group);
39728a3a7ebSEric Paris 	if (!old_entry)
39874c3cbe3SAl Viro 		return create_chunk(inode, tree);
39974c3cbe3SAl Viro 
40028a3a7ebSEric Paris 	old = container_of(old_entry, struct audit_chunk, mark);
40174c3cbe3SAl Viro 
40274c3cbe3SAl Viro 	/* are we already there? */
40374c3cbe3SAl Viro 	spin_lock(&hash_lock);
40474c3cbe3SAl Viro 	for (n = 0; n < old->count; n++) {
40574c3cbe3SAl Viro 		if (old->owners[n].owner == tree) {
40674c3cbe3SAl Viro 			spin_unlock(&hash_lock);
40728a3a7ebSEric Paris 			fsnotify_put_mark(old_entry);
40874c3cbe3SAl Viro 			return 0;
40974c3cbe3SAl Viro 		}
41074c3cbe3SAl Viro 	}
41174c3cbe3SAl Viro 	spin_unlock(&hash_lock);
41274c3cbe3SAl Viro 
41374c3cbe3SAl Viro 	chunk = alloc_chunk(old->count + 1);
414b4c30aadSAl Viro 	if (!chunk) {
41528a3a7ebSEric Paris 		fsnotify_put_mark(old_entry);
41674c3cbe3SAl Viro 		return -ENOMEM;
417b4c30aadSAl Viro 	}
41874c3cbe3SAl Viro 
41928a3a7ebSEric Paris 	chunk_entry = &chunk->mark;
42028a3a7ebSEric Paris 
421be29d20fSJan Kara 	mutex_lock(&old_entry->group->mark_mutex);
42228a3a7ebSEric Paris 	spin_lock(&old_entry->lock);
4236b3f05d2SJan Kara 	/*
4246b3f05d2SJan Kara 	 * mark_mutex protects mark from getting detached and thus also from
4256b3f05d2SJan Kara 	 * mark->connector->inode getting NULL.
4266b3f05d2SJan Kara 	 */
42743471d15SJan Kara 	if (!(old_entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) {
42828a3a7ebSEric Paris 		/* old_entry is being shot, lets just lie */
42928a3a7ebSEric Paris 		spin_unlock(&old_entry->lock);
430be29d20fSJan Kara 		mutex_unlock(&old_entry->group->mark_mutex);
43128a3a7ebSEric Paris 		fsnotify_put_mark(old_entry);
4327b129323SJan Kara 		fsnotify_put_mark(&chunk->mark);
43328a3a7ebSEric Paris 		return -ENOENT;
43428a3a7ebSEric Paris 	}
43528a3a7ebSEric Paris 
4367b129323SJan Kara 	if (fsnotify_add_mark_locked(chunk_entry,
43786ffe245SJan Kara 			     old_entry->connector->inode, NULL, 1)) {
43828a3a7ebSEric Paris 		spin_unlock(&old_entry->lock);
439be29d20fSJan Kara 		mutex_unlock(&old_entry->group->mark_mutex);
4400fe33aaeSMiklos Szeredi 		fsnotify_put_mark(chunk_entry);
44128a3a7ebSEric Paris 		fsnotify_put_mark(old_entry);
44274c3cbe3SAl Viro 		return -ENOSPC;
44374c3cbe3SAl Viro 	}
44428a3a7ebSEric Paris 
44528a3a7ebSEric Paris 	/* even though we hold old_entry->lock, this is safe since chunk_entry->lock could NEVER have been grabbed before */
44628a3a7ebSEric Paris 	spin_lock(&chunk_entry->lock);
44774c3cbe3SAl Viro 	spin_lock(&hash_lock);
44828a3a7ebSEric Paris 
44928a3a7ebSEric Paris 	/* we now hold old_entry->lock, chunk_entry->lock, and hash_lock */
45074c3cbe3SAl Viro 	if (tree->goner) {
45174c3cbe3SAl Viro 		spin_unlock(&hash_lock);
45274c3cbe3SAl Viro 		chunk->dead = 1;
45328a3a7ebSEric Paris 		spin_unlock(&chunk_entry->lock);
45428a3a7ebSEric Paris 		spin_unlock(&old_entry->lock);
455be29d20fSJan Kara 		mutex_unlock(&old_entry->group->mark_mutex);
45628a3a7ebSEric Paris 
457e2a29943SLino Sanfilippo 		fsnotify_destroy_mark(chunk_entry, audit_tree_group);
45828a3a7ebSEric Paris 
45928a3a7ebSEric Paris 		fsnotify_put_mark(chunk_entry);
46028a3a7ebSEric Paris 		fsnotify_put_mark(old_entry);
46174c3cbe3SAl Viro 		return 0;
46274c3cbe3SAl Viro 	}
46374c3cbe3SAl Viro 	list_replace_init(&old->trees, &chunk->trees);
46474c3cbe3SAl Viro 	for (n = 0, p = chunk->owners; n < old->count; n++, p++) {
46574c3cbe3SAl Viro 		struct audit_tree *s = old->owners[n].owner;
46674c3cbe3SAl Viro 		p->owner = s;
46774c3cbe3SAl Viro 		p->index = old->owners[n].index;
46874c3cbe3SAl Viro 		if (!s) /* result of fallback in untag */
46974c3cbe3SAl Viro 			continue;
47074c3cbe3SAl Viro 		get_tree(s);
47174c3cbe3SAl Viro 		list_replace_init(&old->owners[n].list, &p->list);
47274c3cbe3SAl Viro 	}
47374c3cbe3SAl Viro 	p->index = (chunk->count - 1) | (1U<<31);
47474c3cbe3SAl Viro 	p->owner = tree;
47574c3cbe3SAl Viro 	get_tree(tree);
47674c3cbe3SAl Viro 	list_add(&p->list, &tree->chunks);
47774c3cbe3SAl Viro 	list_replace_rcu(&old->hash, &chunk->hash);
47874c3cbe3SAl Viro 	list_for_each_entry(owner, &chunk->trees, same_root)
47974c3cbe3SAl Viro 		owner->root = chunk;
48074c3cbe3SAl Viro 	old->dead = 1;
48174c3cbe3SAl Viro 	if (!tree->root) {
48274c3cbe3SAl Viro 		tree->root = chunk;
48374c3cbe3SAl Viro 		list_add(&tree->same_root, &chunk->trees);
48474c3cbe3SAl Viro 	}
48574c3cbe3SAl Viro 	spin_unlock(&hash_lock);
48628a3a7ebSEric Paris 	spin_unlock(&chunk_entry->lock);
48728a3a7ebSEric Paris 	spin_unlock(&old_entry->lock);
488be29d20fSJan Kara 	mutex_unlock(&old_entry->group->mark_mutex);
489e2a29943SLino Sanfilippo 	fsnotify_destroy_mark(old_entry, audit_tree_group);
490b3e8692bSMiklos Szeredi 	fsnotify_put_mark(chunk_entry);	/* drop initial reference */
49128a3a7ebSEric Paris 	fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */
49274c3cbe3SAl Viro 	return 0;
49374c3cbe3SAl Viro }
49474c3cbe3SAl Viro 
4952991dd2bSRichard Guy Briggs static void audit_tree_log_remove_rule(struct audit_krule *rule)
49674c3cbe3SAl Viro {
49774c3cbe3SAl Viro 	struct audit_buffer *ab;
49874c3cbe3SAl Viro 
49974c3cbe3SAl Viro 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
5000644ec0cSKees Cook 	if (unlikely(!ab))
5010644ec0cSKees Cook 		return;
502c1e8f06dSSteve Grubb 	audit_log_format(ab, "op=remove_rule");
5039d960985SEric Paris 	audit_log_format(ab, " dir=");
50474c3cbe3SAl Viro 	audit_log_untrustedstring(ab, rule->tree->pathname);
5059d960985SEric Paris 	audit_log_key(ab, rule->filterkey);
50674c3cbe3SAl Viro 	audit_log_format(ab, " list=%d res=1", rule->listnr);
50774c3cbe3SAl Viro 	audit_log_end(ab);
5080644ec0cSKees Cook }
5090644ec0cSKees Cook 
5100644ec0cSKees Cook static void kill_rules(struct audit_tree *tree)
5110644ec0cSKees Cook {
5120644ec0cSKees Cook 	struct audit_krule *rule, *next;
5130644ec0cSKees Cook 	struct audit_entry *entry;
5140644ec0cSKees Cook 
5150644ec0cSKees Cook 	list_for_each_entry_safe(rule, next, &tree->rules, rlist) {
5160644ec0cSKees Cook 		entry = container_of(rule, struct audit_entry, rule);
5170644ec0cSKees Cook 
5180644ec0cSKees Cook 		list_del_init(&rule->rlist);
5190644ec0cSKees Cook 		if (rule->tree) {
5200644ec0cSKees Cook 			/* not a half-baked one */
5212991dd2bSRichard Guy Briggs 			audit_tree_log_remove_rule(rule);
52234d99af5SRichard Guy Briggs 			if (entry->rule.exe)
52334d99af5SRichard Guy Briggs 				audit_remove_mark(entry->rule.exe);
52474c3cbe3SAl Viro 			rule->tree = NULL;
52574c3cbe3SAl Viro 			list_del_rcu(&entry->list);
526e45aa212SAl Viro 			list_del(&entry->rule.list);
52774c3cbe3SAl Viro 			call_rcu(&entry->rcu, audit_free_rule_rcu);
52874c3cbe3SAl Viro 		}
52974c3cbe3SAl Viro 	}
53074c3cbe3SAl Viro }
53174c3cbe3SAl Viro 
53274c3cbe3SAl Viro /*
53374c3cbe3SAl Viro  * finish killing struct audit_tree
53474c3cbe3SAl Viro  */
53574c3cbe3SAl Viro static void prune_one(struct audit_tree *victim)
53674c3cbe3SAl Viro {
53774c3cbe3SAl Viro 	spin_lock(&hash_lock);
53874c3cbe3SAl Viro 	while (!list_empty(&victim->chunks)) {
53974c3cbe3SAl Viro 		struct node *p;
54074c3cbe3SAl Viro 
54174c3cbe3SAl Viro 		p = list_entry(victim->chunks.next, struct node, list);
54274c3cbe3SAl Viro 
5438f7b0ba1SAl Viro 		untag_chunk(p);
54474c3cbe3SAl Viro 	}
54574c3cbe3SAl Viro 	spin_unlock(&hash_lock);
54674c3cbe3SAl Viro 	put_tree(victim);
54774c3cbe3SAl Viro }
54874c3cbe3SAl Viro 
54974c3cbe3SAl Viro /* trim the uncommitted chunks from tree */
55074c3cbe3SAl Viro 
55174c3cbe3SAl Viro static void trim_marked(struct audit_tree *tree)
55274c3cbe3SAl Viro {
55374c3cbe3SAl Viro 	struct list_head *p, *q;
55474c3cbe3SAl Viro 	spin_lock(&hash_lock);
55574c3cbe3SAl Viro 	if (tree->goner) {
55674c3cbe3SAl Viro 		spin_unlock(&hash_lock);
55774c3cbe3SAl Viro 		return;
55874c3cbe3SAl Viro 	}
55974c3cbe3SAl Viro 	/* reorder */
56074c3cbe3SAl Viro 	for (p = tree->chunks.next; p != &tree->chunks; p = q) {
56174c3cbe3SAl Viro 		struct node *node = list_entry(p, struct node, list);
56274c3cbe3SAl Viro 		q = p->next;
56374c3cbe3SAl Viro 		if (node->index & (1U<<31)) {
56474c3cbe3SAl Viro 			list_del_init(p);
56574c3cbe3SAl Viro 			list_add(p, &tree->chunks);
56674c3cbe3SAl Viro 		}
56774c3cbe3SAl Viro 	}
56874c3cbe3SAl Viro 
56974c3cbe3SAl Viro 	while (!list_empty(&tree->chunks)) {
57074c3cbe3SAl Viro 		struct node *node;
57174c3cbe3SAl Viro 
57274c3cbe3SAl Viro 		node = list_entry(tree->chunks.next, struct node, list);
57374c3cbe3SAl Viro 
57474c3cbe3SAl Viro 		/* have we run out of marked? */
57574c3cbe3SAl Viro 		if (!(node->index & (1U<<31)))
57674c3cbe3SAl Viro 			break;
57774c3cbe3SAl Viro 
5788f7b0ba1SAl Viro 		untag_chunk(node);
57974c3cbe3SAl Viro 	}
58074c3cbe3SAl Viro 	if (!tree->root && !tree->goner) {
58174c3cbe3SAl Viro 		tree->goner = 1;
58274c3cbe3SAl Viro 		spin_unlock(&hash_lock);
58374c3cbe3SAl Viro 		mutex_lock(&audit_filter_mutex);
58474c3cbe3SAl Viro 		kill_rules(tree);
58574c3cbe3SAl Viro 		list_del_init(&tree->list);
58674c3cbe3SAl Viro 		mutex_unlock(&audit_filter_mutex);
58774c3cbe3SAl Viro 		prune_one(tree);
58874c3cbe3SAl Viro 	} else {
58974c3cbe3SAl Viro 		spin_unlock(&hash_lock);
59074c3cbe3SAl Viro 	}
59174c3cbe3SAl Viro }
59274c3cbe3SAl Viro 
593916d7576SAl Viro static void audit_schedule_prune(void);
594916d7576SAl Viro 
59574c3cbe3SAl Viro /* called with audit_filter_mutex */
59674c3cbe3SAl Viro int audit_remove_tree_rule(struct audit_krule *rule)
59774c3cbe3SAl Viro {
59874c3cbe3SAl Viro 	struct audit_tree *tree;
59974c3cbe3SAl Viro 	tree = rule->tree;
60074c3cbe3SAl Viro 	if (tree) {
60174c3cbe3SAl Viro 		spin_lock(&hash_lock);
60274c3cbe3SAl Viro 		list_del_init(&rule->rlist);
60374c3cbe3SAl Viro 		if (list_empty(&tree->rules) && !tree->goner) {
60474c3cbe3SAl Viro 			tree->root = NULL;
60574c3cbe3SAl Viro 			list_del_init(&tree->same_root);
60674c3cbe3SAl Viro 			tree->goner = 1;
60774c3cbe3SAl Viro 			list_move(&tree->list, &prune_list);
60874c3cbe3SAl Viro 			rule->tree = NULL;
60974c3cbe3SAl Viro 			spin_unlock(&hash_lock);
61074c3cbe3SAl Viro 			audit_schedule_prune();
61174c3cbe3SAl Viro 			return 1;
61274c3cbe3SAl Viro 		}
61374c3cbe3SAl Viro 		rule->tree = NULL;
61474c3cbe3SAl Viro 		spin_unlock(&hash_lock);
61574c3cbe3SAl Viro 		return 1;
61674c3cbe3SAl Viro 	}
61774c3cbe3SAl Viro 	return 0;
61874c3cbe3SAl Viro }
61974c3cbe3SAl Viro 
6201f707137SAl Viro static int compare_root(struct vfsmount *mnt, void *arg)
6211f707137SAl Viro {
622f410ff65SJan Kara 	return inode_to_key(d_backing_inode(mnt->mnt_root)) ==
623f410ff65SJan Kara 	       (unsigned long)arg;
6241f707137SAl Viro }
6251f707137SAl Viro 
62674c3cbe3SAl Viro void audit_trim_trees(void)
62774c3cbe3SAl Viro {
62874c3cbe3SAl Viro 	struct list_head cursor;
62974c3cbe3SAl Viro 
63074c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
63174c3cbe3SAl Viro 	list_add(&cursor, &tree_list);
63274c3cbe3SAl Viro 	while (cursor.next != &tree_list) {
63374c3cbe3SAl Viro 		struct audit_tree *tree;
63498bc993fSAl Viro 		struct path path;
63574c3cbe3SAl Viro 		struct vfsmount *root_mnt;
63674c3cbe3SAl Viro 		struct node *node;
63774c3cbe3SAl Viro 		int err;
63874c3cbe3SAl Viro 
63974c3cbe3SAl Viro 		tree = container_of(cursor.next, struct audit_tree, list);
64074c3cbe3SAl Viro 		get_tree(tree);
64174c3cbe3SAl Viro 		list_del(&cursor);
64274c3cbe3SAl Viro 		list_add(&cursor, &tree->list);
64374c3cbe3SAl Viro 		mutex_unlock(&audit_filter_mutex);
64474c3cbe3SAl Viro 
64598bc993fSAl Viro 		err = kern_path(tree->pathname, 0, &path);
64674c3cbe3SAl Viro 		if (err)
64774c3cbe3SAl Viro 			goto skip_it;
64874c3cbe3SAl Viro 
649589ff870SAl Viro 		root_mnt = collect_mounts(&path);
65098bc993fSAl Viro 		path_put(&path);
651be34d1a3SDavid Howells 		if (IS_ERR(root_mnt))
65274c3cbe3SAl Viro 			goto skip_it;
65374c3cbe3SAl Viro 
65474c3cbe3SAl Viro 		spin_lock(&hash_lock);
65574c3cbe3SAl Viro 		list_for_each_entry(node, &tree->chunks, list) {
65628a3a7ebSEric Paris 			struct audit_chunk *chunk = find_chunk(node);
65725985edcSLucas De Marchi 			/* this could be NULL if the watch is dying else where... */
65874c3cbe3SAl Viro 			node->index |= 1U<<31;
659f410ff65SJan Kara 			if (iterate_mounts(compare_root,
660f410ff65SJan Kara 					   (void *)chunk_to_key(chunk),
661f410ff65SJan Kara 					   root_mnt))
66274c3cbe3SAl Viro 				node->index &= ~(1U<<31);
66374c3cbe3SAl Viro 		}
66474c3cbe3SAl Viro 		spin_unlock(&hash_lock);
66574c3cbe3SAl Viro 		trim_marked(tree);
66674c3cbe3SAl Viro 		drop_collected_mounts(root_mnt);
66774c3cbe3SAl Viro skip_it:
66812b2f117SChen Gang 		put_tree(tree);
66974c3cbe3SAl Viro 		mutex_lock(&audit_filter_mutex);
67074c3cbe3SAl Viro 	}
67174c3cbe3SAl Viro 	list_del(&cursor);
67274c3cbe3SAl Viro 	mutex_unlock(&audit_filter_mutex);
67374c3cbe3SAl Viro }
67474c3cbe3SAl Viro 
67574c3cbe3SAl Viro int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
67674c3cbe3SAl Viro {
67774c3cbe3SAl Viro 
67874c3cbe3SAl Viro 	if (pathname[0] != '/' ||
67974c3cbe3SAl Viro 	    rule->listnr != AUDIT_FILTER_EXIT ||
6805af75d8dSAl Viro 	    op != Audit_equal ||
68174c3cbe3SAl Viro 	    rule->inode_f || rule->watch || rule->tree)
68274c3cbe3SAl Viro 		return -EINVAL;
68374c3cbe3SAl Viro 	rule->tree = alloc_tree(pathname);
68474c3cbe3SAl Viro 	if (!rule->tree)
68574c3cbe3SAl Viro 		return -ENOMEM;
68674c3cbe3SAl Viro 	return 0;
68774c3cbe3SAl Viro }
68874c3cbe3SAl Viro 
68974c3cbe3SAl Viro void audit_put_tree(struct audit_tree *tree)
69074c3cbe3SAl Viro {
69174c3cbe3SAl Viro 	put_tree(tree);
69274c3cbe3SAl Viro }
69374c3cbe3SAl Viro 
6941f707137SAl Viro static int tag_mount(struct vfsmount *mnt, void *arg)
6951f707137SAl Viro {
6963b362157SDavid Howells 	return tag_chunk(d_backing_inode(mnt->mnt_root), arg);
6971f707137SAl Viro }
6981f707137SAl Viro 
699f1aaf262SImre Palik /*
700f1aaf262SImre Palik  * That gets run when evict_chunk() ends up needing to kill audit_tree.
701f1aaf262SImre Palik  * Runs from a separate thread.
702f1aaf262SImre Palik  */
703f1aaf262SImre Palik static int prune_tree_thread(void *unused)
704f1aaf262SImre Palik {
705f1aaf262SImre Palik 	for (;;) {
7060bf676d1SJiri Slaby 		if (list_empty(&prune_list)) {
707f1aaf262SImre Palik 			set_current_state(TASK_INTERRUPTIBLE);
708f1aaf262SImre Palik 			schedule();
7090bf676d1SJiri Slaby 		}
710f1aaf262SImre Palik 
711f1aaf262SImre Palik 		mutex_lock(&audit_cmd_mutex);
712f1aaf262SImre Palik 		mutex_lock(&audit_filter_mutex);
713f1aaf262SImre Palik 
714f1aaf262SImre Palik 		while (!list_empty(&prune_list)) {
715f1aaf262SImre Palik 			struct audit_tree *victim;
716f1aaf262SImre Palik 
717f1aaf262SImre Palik 			victim = list_entry(prune_list.next,
718f1aaf262SImre Palik 					struct audit_tree, list);
719f1aaf262SImre Palik 			list_del_init(&victim->list);
720f1aaf262SImre Palik 
721f1aaf262SImre Palik 			mutex_unlock(&audit_filter_mutex);
722f1aaf262SImre Palik 
723f1aaf262SImre Palik 			prune_one(victim);
724f1aaf262SImre Palik 
725f1aaf262SImre Palik 			mutex_lock(&audit_filter_mutex);
726f1aaf262SImre Palik 		}
727f1aaf262SImre Palik 
728f1aaf262SImre Palik 		mutex_unlock(&audit_filter_mutex);
729f1aaf262SImre Palik 		mutex_unlock(&audit_cmd_mutex);
730f1aaf262SImre Palik 	}
731f1aaf262SImre Palik 	return 0;
732f1aaf262SImre Palik }
733f1aaf262SImre Palik 
734f1aaf262SImre Palik static int audit_launch_prune(void)
735f1aaf262SImre Palik {
736f1aaf262SImre Palik 	if (prune_thread)
737f1aaf262SImre Palik 		return 0;
7380bf676d1SJiri Slaby 	prune_thread = kthread_run(prune_tree_thread, NULL,
739f1aaf262SImre Palik 				"audit_prune_tree");
740f1aaf262SImre Palik 	if (IS_ERR(prune_thread)) {
741f1aaf262SImre Palik 		pr_err("cannot start thread audit_prune_tree");
742f1aaf262SImre Palik 		prune_thread = NULL;
743f1aaf262SImre Palik 		return -ENOMEM;
744f1aaf262SImre Palik 	}
7450bf676d1SJiri Slaby 	return 0;
746f1aaf262SImre Palik }
747f1aaf262SImre Palik 
74874c3cbe3SAl Viro /* called with audit_filter_mutex */
74974c3cbe3SAl Viro int audit_add_tree_rule(struct audit_krule *rule)
75074c3cbe3SAl Viro {
75174c3cbe3SAl Viro 	struct audit_tree *seed = rule->tree, *tree;
75298bc993fSAl Viro 	struct path path;
7531f707137SAl Viro 	struct vfsmount *mnt;
75474c3cbe3SAl Viro 	int err;
75574c3cbe3SAl Viro 
756736f3203SChen Gang 	rule->tree = NULL;
75774c3cbe3SAl Viro 	list_for_each_entry(tree, &tree_list, list) {
75874c3cbe3SAl Viro 		if (!strcmp(seed->pathname, tree->pathname)) {
75974c3cbe3SAl Viro 			put_tree(seed);
76074c3cbe3SAl Viro 			rule->tree = tree;
76174c3cbe3SAl Viro 			list_add(&rule->rlist, &tree->rules);
76274c3cbe3SAl Viro 			return 0;
76374c3cbe3SAl Viro 		}
76474c3cbe3SAl Viro 	}
76574c3cbe3SAl Viro 	tree = seed;
76674c3cbe3SAl Viro 	list_add(&tree->list, &tree_list);
76774c3cbe3SAl Viro 	list_add(&rule->rlist, &tree->rules);
76874c3cbe3SAl Viro 	/* do not set rule->tree yet */
76974c3cbe3SAl Viro 	mutex_unlock(&audit_filter_mutex);
77074c3cbe3SAl Viro 
771f1aaf262SImre Palik 	if (unlikely(!prune_thread)) {
772f1aaf262SImre Palik 		err = audit_launch_prune();
773f1aaf262SImre Palik 		if (err)
774f1aaf262SImre Palik 			goto Err;
775f1aaf262SImre Palik 	}
776f1aaf262SImre Palik 
77798bc993fSAl Viro 	err = kern_path(tree->pathname, 0, &path);
77874c3cbe3SAl Viro 	if (err)
77974c3cbe3SAl Viro 		goto Err;
780589ff870SAl Viro 	mnt = collect_mounts(&path);
78198bc993fSAl Viro 	path_put(&path);
782be34d1a3SDavid Howells 	if (IS_ERR(mnt)) {
783be34d1a3SDavid Howells 		err = PTR_ERR(mnt);
78474c3cbe3SAl Viro 		goto Err;
78574c3cbe3SAl Viro 	}
78674c3cbe3SAl Viro 
78774c3cbe3SAl Viro 	get_tree(tree);
7881f707137SAl Viro 	err = iterate_mounts(tag_mount, tree, mnt);
78974c3cbe3SAl Viro 	drop_collected_mounts(mnt);
79074c3cbe3SAl Viro 
79174c3cbe3SAl Viro 	if (!err) {
79274c3cbe3SAl Viro 		struct node *node;
79374c3cbe3SAl Viro 		spin_lock(&hash_lock);
79474c3cbe3SAl Viro 		list_for_each_entry(node, &tree->chunks, list)
79574c3cbe3SAl Viro 			node->index &= ~(1U<<31);
79674c3cbe3SAl Viro 		spin_unlock(&hash_lock);
79774c3cbe3SAl Viro 	} else {
79874c3cbe3SAl Viro 		trim_marked(tree);
79974c3cbe3SAl Viro 		goto Err;
80074c3cbe3SAl Viro 	}
80174c3cbe3SAl Viro 
80274c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
80374c3cbe3SAl Viro 	if (list_empty(&rule->rlist)) {
80474c3cbe3SAl Viro 		put_tree(tree);
80574c3cbe3SAl Viro 		return -ENOENT;
80674c3cbe3SAl Viro 	}
80774c3cbe3SAl Viro 	rule->tree = tree;
80874c3cbe3SAl Viro 	put_tree(tree);
80974c3cbe3SAl Viro 
81074c3cbe3SAl Viro 	return 0;
81174c3cbe3SAl Viro Err:
81274c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
81374c3cbe3SAl Viro 	list_del_init(&tree->list);
81474c3cbe3SAl Viro 	list_del_init(&tree->rules);
81574c3cbe3SAl Viro 	put_tree(tree);
81674c3cbe3SAl Viro 	return err;
81774c3cbe3SAl Viro }
81874c3cbe3SAl Viro 
81974c3cbe3SAl Viro int audit_tag_tree(char *old, char *new)
82074c3cbe3SAl Viro {
82174c3cbe3SAl Viro 	struct list_head cursor, barrier;
82274c3cbe3SAl Viro 	int failed = 0;
8232096f759SAl Viro 	struct path path1, path2;
82474c3cbe3SAl Viro 	struct vfsmount *tagged;
82574c3cbe3SAl Viro 	int err;
82674c3cbe3SAl Viro 
8272096f759SAl Viro 	err = kern_path(new, 0, &path2);
82874c3cbe3SAl Viro 	if (err)
82974c3cbe3SAl Viro 		return err;
8302096f759SAl Viro 	tagged = collect_mounts(&path2);
8312096f759SAl Viro 	path_put(&path2);
832be34d1a3SDavid Howells 	if (IS_ERR(tagged))
833be34d1a3SDavid Howells 		return PTR_ERR(tagged);
83474c3cbe3SAl Viro 
8352096f759SAl Viro 	err = kern_path(old, 0, &path1);
83674c3cbe3SAl Viro 	if (err) {
83774c3cbe3SAl Viro 		drop_collected_mounts(tagged);
83874c3cbe3SAl Viro 		return err;
83974c3cbe3SAl Viro 	}
84074c3cbe3SAl Viro 
84174c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
84274c3cbe3SAl Viro 	list_add(&barrier, &tree_list);
84374c3cbe3SAl Viro 	list_add(&cursor, &barrier);
84474c3cbe3SAl Viro 
84574c3cbe3SAl Viro 	while (cursor.next != &tree_list) {
84674c3cbe3SAl Viro 		struct audit_tree *tree;
8472096f759SAl Viro 		int good_one = 0;
84874c3cbe3SAl Viro 
84974c3cbe3SAl Viro 		tree = container_of(cursor.next, struct audit_tree, list);
85074c3cbe3SAl Viro 		get_tree(tree);
85174c3cbe3SAl Viro 		list_del(&cursor);
85274c3cbe3SAl Viro 		list_add(&cursor, &tree->list);
85374c3cbe3SAl Viro 		mutex_unlock(&audit_filter_mutex);
85474c3cbe3SAl Viro 
8552096f759SAl Viro 		err = kern_path(tree->pathname, 0, &path2);
8562096f759SAl Viro 		if (!err) {
8572096f759SAl Viro 			good_one = path_is_under(&path1, &path2);
8582096f759SAl Viro 			path_put(&path2);
85974c3cbe3SAl Viro 		}
86074c3cbe3SAl Viro 
8612096f759SAl Viro 		if (!good_one) {
86274c3cbe3SAl Viro 			put_tree(tree);
86374c3cbe3SAl Viro 			mutex_lock(&audit_filter_mutex);
86474c3cbe3SAl Viro 			continue;
86574c3cbe3SAl Viro 		}
86674c3cbe3SAl Viro 
8671f707137SAl Viro 		failed = iterate_mounts(tag_mount, tree, tagged);
86874c3cbe3SAl Viro 		if (failed) {
86974c3cbe3SAl Viro 			put_tree(tree);
87074c3cbe3SAl Viro 			mutex_lock(&audit_filter_mutex);
87174c3cbe3SAl Viro 			break;
87274c3cbe3SAl Viro 		}
87374c3cbe3SAl Viro 
87474c3cbe3SAl Viro 		mutex_lock(&audit_filter_mutex);
87574c3cbe3SAl Viro 		spin_lock(&hash_lock);
87674c3cbe3SAl Viro 		if (!tree->goner) {
87774c3cbe3SAl Viro 			list_del(&tree->list);
87874c3cbe3SAl Viro 			list_add(&tree->list, &tree_list);
87974c3cbe3SAl Viro 		}
88074c3cbe3SAl Viro 		spin_unlock(&hash_lock);
88174c3cbe3SAl Viro 		put_tree(tree);
88274c3cbe3SAl Viro 	}
88374c3cbe3SAl Viro 
88474c3cbe3SAl Viro 	while (barrier.prev != &tree_list) {
88574c3cbe3SAl Viro 		struct audit_tree *tree;
88674c3cbe3SAl Viro 
88774c3cbe3SAl Viro 		tree = container_of(barrier.prev, struct audit_tree, list);
88874c3cbe3SAl Viro 		get_tree(tree);
88974c3cbe3SAl Viro 		list_del(&tree->list);
89074c3cbe3SAl Viro 		list_add(&tree->list, &barrier);
89174c3cbe3SAl Viro 		mutex_unlock(&audit_filter_mutex);
89274c3cbe3SAl Viro 
89374c3cbe3SAl Viro 		if (!failed) {
89474c3cbe3SAl Viro 			struct node *node;
89574c3cbe3SAl Viro 			spin_lock(&hash_lock);
89674c3cbe3SAl Viro 			list_for_each_entry(node, &tree->chunks, list)
89774c3cbe3SAl Viro 				node->index &= ~(1U<<31);
89874c3cbe3SAl Viro 			spin_unlock(&hash_lock);
89974c3cbe3SAl Viro 		} else {
90074c3cbe3SAl Viro 			trim_marked(tree);
90174c3cbe3SAl Viro 		}
90274c3cbe3SAl Viro 
90374c3cbe3SAl Viro 		put_tree(tree);
90474c3cbe3SAl Viro 		mutex_lock(&audit_filter_mutex);
90574c3cbe3SAl Viro 	}
90674c3cbe3SAl Viro 	list_del(&barrier);
90774c3cbe3SAl Viro 	list_del(&cursor);
90874c3cbe3SAl Viro 	mutex_unlock(&audit_filter_mutex);
9092096f759SAl Viro 	path_put(&path1);
91074c3cbe3SAl Viro 	drop_collected_mounts(tagged);
91174c3cbe3SAl Viro 	return failed;
91274c3cbe3SAl Viro }
91374c3cbe3SAl Viro 
914916d7576SAl Viro 
915916d7576SAl Viro static void audit_schedule_prune(void)
916916d7576SAl Viro {
917f1aaf262SImre Palik 	wake_up_process(prune_thread);
918916d7576SAl Viro }
919916d7576SAl Viro 
920916d7576SAl Viro /*
921916d7576SAl Viro  * ... and that one is done if evict_chunk() decides to delay until the end
922916d7576SAl Viro  * of syscall.  Runs synchronously.
923916d7576SAl Viro  */
924916d7576SAl Viro void audit_kill_trees(struct list_head *list)
925916d7576SAl Viro {
926916d7576SAl Viro 	mutex_lock(&audit_cmd_mutex);
927916d7576SAl Viro 	mutex_lock(&audit_filter_mutex);
928916d7576SAl Viro 
929916d7576SAl Viro 	while (!list_empty(list)) {
930916d7576SAl Viro 		struct audit_tree *victim;
931916d7576SAl Viro 
932916d7576SAl Viro 		victim = list_entry(list->next, struct audit_tree, list);
933916d7576SAl Viro 		kill_rules(victim);
934916d7576SAl Viro 		list_del_init(&victim->list);
935916d7576SAl Viro 
936916d7576SAl Viro 		mutex_unlock(&audit_filter_mutex);
937916d7576SAl Viro 
938916d7576SAl Viro 		prune_one(victim);
939916d7576SAl Viro 
940916d7576SAl Viro 		mutex_lock(&audit_filter_mutex);
941916d7576SAl Viro 	}
942916d7576SAl Viro 
943916d7576SAl Viro 	mutex_unlock(&audit_filter_mutex);
944916d7576SAl Viro 	mutex_unlock(&audit_cmd_mutex);
94574c3cbe3SAl Viro }
94674c3cbe3SAl Viro 
94774c3cbe3SAl Viro /*
94874c3cbe3SAl Viro  *  Here comes the stuff asynchronous to auditctl operations
94974c3cbe3SAl Viro  */
95074c3cbe3SAl Viro 
95174c3cbe3SAl Viro static void evict_chunk(struct audit_chunk *chunk)
95274c3cbe3SAl Viro {
95374c3cbe3SAl Viro 	struct audit_tree *owner;
954916d7576SAl Viro 	struct list_head *postponed = audit_killed_trees();
955916d7576SAl Viro 	int need_prune = 0;
95674c3cbe3SAl Viro 	int n;
95774c3cbe3SAl Viro 
95874c3cbe3SAl Viro 	if (chunk->dead)
95974c3cbe3SAl Viro 		return;
96074c3cbe3SAl Viro 
96174c3cbe3SAl Viro 	chunk->dead = 1;
96274c3cbe3SAl Viro 	mutex_lock(&audit_filter_mutex);
96374c3cbe3SAl Viro 	spin_lock(&hash_lock);
96474c3cbe3SAl Viro 	while (!list_empty(&chunk->trees)) {
96574c3cbe3SAl Viro 		owner = list_entry(chunk->trees.next,
96674c3cbe3SAl Viro 				   struct audit_tree, same_root);
96774c3cbe3SAl Viro 		owner->goner = 1;
96874c3cbe3SAl Viro 		owner->root = NULL;
96974c3cbe3SAl Viro 		list_del_init(&owner->same_root);
97074c3cbe3SAl Viro 		spin_unlock(&hash_lock);
971916d7576SAl Viro 		if (!postponed) {
97274c3cbe3SAl Viro 			kill_rules(owner);
97374c3cbe3SAl Viro 			list_move(&owner->list, &prune_list);
974916d7576SAl Viro 			need_prune = 1;
975916d7576SAl Viro 		} else {
976916d7576SAl Viro 			list_move(&owner->list, postponed);
977916d7576SAl Viro 		}
97874c3cbe3SAl Viro 		spin_lock(&hash_lock);
97974c3cbe3SAl Viro 	}
98074c3cbe3SAl Viro 	list_del_rcu(&chunk->hash);
98174c3cbe3SAl Viro 	for (n = 0; n < chunk->count; n++)
98274c3cbe3SAl Viro 		list_del_init(&chunk->owners[n].list);
98374c3cbe3SAl Viro 	spin_unlock(&hash_lock);
984f1aaf262SImre Palik 	mutex_unlock(&audit_filter_mutex);
985916d7576SAl Viro 	if (need_prune)
986916d7576SAl Viro 		audit_schedule_prune();
98774c3cbe3SAl Viro }
98874c3cbe3SAl Viro 
9893a9b16b4SEric Paris static int audit_tree_handle_event(struct fsnotify_group *group,
9907053aee2SJan Kara 				   struct inode *to_tell,
991ce8f76fbSEric Paris 				   struct fsnotify_mark *inode_mark,
9927053aee2SJan Kara 				   struct fsnotify_mark *vfsmount_mark,
9933cd5eca8SAl Viro 				   u32 mask, const void *data, int data_type,
9949385a84dSJan Kara 				   const unsigned char *file_name, u32 cookie,
9959385a84dSJan Kara 				   struct fsnotify_iter_info *iter_info)
99674c3cbe3SAl Viro {
99783c4c4b0SJan Kara 	return 0;
99828a3a7ebSEric Paris }
99974c3cbe3SAl Viro 
1000e61ce867SEric Paris static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify_group *group)
100128a3a7ebSEric Paris {
100228a3a7ebSEric Paris 	struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark);
100328a3a7ebSEric Paris 
100474c3cbe3SAl Viro 	evict_chunk(chunk);
1005b3e8692bSMiklos Szeredi 
1006b3e8692bSMiklos Szeredi 	/*
1007b3e8692bSMiklos Szeredi 	 * We are guaranteed to have at least one reference to the mark from
1008b3e8692bSMiklos Szeredi 	 * either the inode or the caller of fsnotify_destroy_mark().
1009b3e8692bSMiklos Szeredi 	 */
1010ab97f873SElena Reshetova 	BUG_ON(refcount_read(&entry->refcnt) < 1);
101174c3cbe3SAl Viro }
101274c3cbe3SAl Viro 
101328a3a7ebSEric Paris static const struct fsnotify_ops audit_tree_ops = {
101428a3a7ebSEric Paris 	.handle_event = audit_tree_handle_event,
101528a3a7ebSEric Paris 	.freeing_mark = audit_tree_freeing_mark,
1016054c636eSJan Kara 	.free_mark = audit_tree_destroy_watch,
101774c3cbe3SAl Viro };
101874c3cbe3SAl Viro 
101974c3cbe3SAl Viro static int __init audit_tree_init(void)
102074c3cbe3SAl Viro {
102174c3cbe3SAl Viro 	int i;
102274c3cbe3SAl Viro 
10230d2e2a1dSEric Paris 	audit_tree_group = fsnotify_alloc_group(&audit_tree_ops);
102428a3a7ebSEric Paris 	if (IS_ERR(audit_tree_group))
102528a3a7ebSEric Paris 		audit_panic("cannot initialize fsnotify group for rectree watches");
102674c3cbe3SAl Viro 
102774c3cbe3SAl Viro 	for (i = 0; i < HASH_SIZE; i++)
102874c3cbe3SAl Viro 		INIT_LIST_HEAD(&chunk_hash_heads[i]);
102974c3cbe3SAl Viro 
103074c3cbe3SAl Viro 	return 0;
103174c3cbe3SAl Viro }
103274c3cbe3SAl Viro __initcall(audit_tree_init);
1033