1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 274c3cbe3SAl Viro #include "audit.h" 328a3a7ebSEric Paris #include <linux/fsnotify_backend.h> 474c3cbe3SAl Viro #include <linux/namei.h> 574c3cbe3SAl Viro #include <linux/mount.h> 6916d7576SAl Viro #include <linux/kthread.h> 79d2378f8SElena Reshetova #include <linux/refcount.h> 85a0e3ad6STejun Heo #include <linux/slab.h> 974c3cbe3SAl Viro 1074c3cbe3SAl Viro struct audit_tree; 1174c3cbe3SAl Viro struct audit_chunk; 1274c3cbe3SAl Viro 1374c3cbe3SAl Viro struct audit_tree { 149d2378f8SElena Reshetova refcount_t count; 1574c3cbe3SAl Viro int goner; 1674c3cbe3SAl Viro struct audit_chunk *root; 1774c3cbe3SAl Viro struct list_head chunks; 1874c3cbe3SAl Viro struct list_head rules; 1974c3cbe3SAl Viro struct list_head list; 2074c3cbe3SAl Viro struct list_head same_root; 2174c3cbe3SAl Viro struct rcu_head head; 2274c3cbe3SAl Viro char pathname[]; 2374c3cbe3SAl Viro }; 2474c3cbe3SAl Viro 2574c3cbe3SAl Viro struct audit_chunk { 2674c3cbe3SAl Viro struct list_head hash; 278d20d6e9SJan Kara unsigned long key; 285f516130SJan Kara struct fsnotify_mark *mark; 2974c3cbe3SAl Viro struct list_head trees; /* with root here */ 3074c3cbe3SAl Viro int dead; 3174c3cbe3SAl Viro int count; 328f7b0ba1SAl Viro atomic_long_t refs; 3374c3cbe3SAl Viro struct rcu_head head; 3474c3cbe3SAl Viro struct node { 3574c3cbe3SAl Viro struct list_head list; 3674c3cbe3SAl Viro struct audit_tree *owner; 3774c3cbe3SAl Viro unsigned index; /* index; upper bit indicates 'will prune' */ 3874c3cbe3SAl Viro } owners[]; 3974c3cbe3SAl Viro }; 4074c3cbe3SAl Viro 415f516130SJan Kara struct audit_tree_mark { 425f516130SJan Kara struct fsnotify_mark mark; 435f516130SJan Kara struct audit_chunk *chunk; 445f516130SJan Kara }; 455f516130SJan Kara 4674c3cbe3SAl Viro static LIST_HEAD(tree_list); 4774c3cbe3SAl Viro static LIST_HEAD(prune_list); 48f1aaf262SImre Palik static struct task_struct *prune_thread; 4974c3cbe3SAl Viro 5074c3cbe3SAl Viro /* 5174c3cbe3SAl Viro * One struct chunk is attached to each inode of interest. 5274c3cbe3SAl Viro * We replace struct chunk on tagging/untagging. 5374c3cbe3SAl Viro * Rules have pointer to struct audit_tree. 5474c3cbe3SAl Viro * Rules have struct list_head rlist forming a list of rules over 5574c3cbe3SAl Viro * the same tree. 5674c3cbe3SAl Viro * References to struct chunk are collected at audit_inode{,_child}() 5774c3cbe3SAl Viro * time and used in AUDIT_TREE rule matching. 5874c3cbe3SAl Viro * These references are dropped at the same time we are calling 5974c3cbe3SAl Viro * audit_free_names(), etc. 6074c3cbe3SAl Viro * 6174c3cbe3SAl Viro * Cyclic lists galore: 6274c3cbe3SAl Viro * tree.chunks anchors chunk.owners[].list hash_lock 6374c3cbe3SAl Viro * tree.rules anchors rule.rlist audit_filter_mutex 6474c3cbe3SAl Viro * chunk.trees anchors tree.same_root hash_lock 6574c3cbe3SAl Viro * chunk.hash is a hash with middle bits of watch.inode as 6674c3cbe3SAl Viro * a hash function. RCU, hash_lock 6774c3cbe3SAl Viro * 6874c3cbe3SAl Viro * tree is refcounted; one reference for "some rules on rules_list refer to 6974c3cbe3SAl Viro * it", one for each chunk with pointer to it. 7074c3cbe3SAl Viro * 7128a3a7ebSEric Paris * chunk is refcounted by embedded fsnotify_mark + .refs (non-zero refcount 728f7b0ba1SAl Viro * of watch contributes 1 to .refs). 7374c3cbe3SAl Viro * 7474c3cbe3SAl Viro * node.index allows to get from node.list to containing chunk. 7574c3cbe3SAl Viro * MSB of that sucker is stolen to mark taggings that we might have to 7674c3cbe3SAl Viro * revert - several operations have very unpleasant cleanup logics and 7774c3cbe3SAl Viro * that makes a difference. Some. 7874c3cbe3SAl Viro */ 7974c3cbe3SAl Viro 8028a3a7ebSEric Paris static struct fsnotify_group *audit_tree_group; 815f516130SJan Kara static struct kmem_cache *audit_tree_mark_cachep __read_mostly; 8274c3cbe3SAl Viro 8374c3cbe3SAl Viro static struct audit_tree *alloc_tree(const char *s) 8474c3cbe3SAl Viro { 8574c3cbe3SAl Viro struct audit_tree *tree; 8674c3cbe3SAl Viro 8774c3cbe3SAl Viro tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL); 8874c3cbe3SAl Viro if (tree) { 899d2378f8SElena Reshetova refcount_set(&tree->count, 1); 9074c3cbe3SAl Viro tree->goner = 0; 9174c3cbe3SAl Viro INIT_LIST_HEAD(&tree->chunks); 9274c3cbe3SAl Viro INIT_LIST_HEAD(&tree->rules); 9374c3cbe3SAl Viro INIT_LIST_HEAD(&tree->list); 9474c3cbe3SAl Viro INIT_LIST_HEAD(&tree->same_root); 9574c3cbe3SAl Viro tree->root = NULL; 9674c3cbe3SAl Viro strcpy(tree->pathname, s); 9774c3cbe3SAl Viro } 9874c3cbe3SAl Viro return tree; 9974c3cbe3SAl Viro } 10074c3cbe3SAl Viro 10174c3cbe3SAl Viro static inline void get_tree(struct audit_tree *tree) 10274c3cbe3SAl Viro { 1039d2378f8SElena Reshetova refcount_inc(&tree->count); 10474c3cbe3SAl Viro } 10574c3cbe3SAl Viro 10674c3cbe3SAl Viro static inline void put_tree(struct audit_tree *tree) 10774c3cbe3SAl Viro { 1089d2378f8SElena Reshetova if (refcount_dec_and_test(&tree->count)) 1093b097c46SLai Jiangshan kfree_rcu(tree, head); 11074c3cbe3SAl Viro } 11174c3cbe3SAl Viro 11274c3cbe3SAl Viro /* to avoid bringing the entire thing in audit.h */ 11374c3cbe3SAl Viro const char *audit_tree_path(struct audit_tree *tree) 11474c3cbe3SAl Viro { 11574c3cbe3SAl Viro return tree->pathname; 11674c3cbe3SAl Viro } 11774c3cbe3SAl Viro 1188f7b0ba1SAl Viro static void free_chunk(struct audit_chunk *chunk) 11974c3cbe3SAl Viro { 12074c3cbe3SAl Viro int i; 12174c3cbe3SAl Viro 12274c3cbe3SAl Viro for (i = 0; i < chunk->count; i++) { 12374c3cbe3SAl Viro if (chunk->owners[i].owner) 12474c3cbe3SAl Viro put_tree(chunk->owners[i].owner); 12574c3cbe3SAl Viro } 12674c3cbe3SAl Viro kfree(chunk); 12774c3cbe3SAl Viro } 12874c3cbe3SAl Viro 12974c3cbe3SAl Viro void audit_put_chunk(struct audit_chunk *chunk) 13074c3cbe3SAl Viro { 1318f7b0ba1SAl Viro if (atomic_long_dec_and_test(&chunk->refs)) 1328f7b0ba1SAl Viro free_chunk(chunk); 1338f7b0ba1SAl Viro } 1348f7b0ba1SAl Viro 1358f7b0ba1SAl Viro static void __put_chunk(struct rcu_head *rcu) 1368f7b0ba1SAl Viro { 1378f7b0ba1SAl Viro struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head); 1388f7b0ba1SAl Viro audit_put_chunk(chunk); 13974c3cbe3SAl Viro } 14074c3cbe3SAl Viro 141a8375713SJan Kara /* 142a8375713SJan Kara * Drop reference to the chunk that was held by the mark. This is the reference 143a8375713SJan Kara * that gets dropped after we've removed the chunk from the hash table and we 144a8375713SJan Kara * use it to make sure chunk cannot be freed before RCU grace period expires. 145a8375713SJan Kara */ 146a8375713SJan Kara static void audit_mark_put_chunk(struct audit_chunk *chunk) 147a8375713SJan Kara { 148a8375713SJan Kara call_rcu(&chunk->head, __put_chunk); 149a8375713SJan Kara } 150a8375713SJan Kara 1515f516130SJan Kara static inline struct audit_tree_mark *audit_mark(struct fsnotify_mark *entry) 1525f516130SJan Kara { 1535f516130SJan Kara return container_of(entry, struct audit_tree_mark, mark); 1545f516130SJan Kara } 1555f516130SJan Kara 1565f516130SJan Kara static struct audit_chunk *mark_chunk(struct fsnotify_mark *mark) 1575f516130SJan Kara { 1585f516130SJan Kara return audit_mark(mark)->chunk; 1595f516130SJan Kara } 1605f516130SJan Kara 161e61ce867SEric Paris static void audit_tree_destroy_watch(struct fsnotify_mark *entry) 16228a3a7ebSEric Paris { 1635f516130SJan Kara struct audit_chunk *chunk = mark_chunk(entry); 164a8375713SJan Kara audit_mark_put_chunk(chunk); 1655f516130SJan Kara kmem_cache_free(audit_tree_mark_cachep, audit_mark(entry)); 1665f516130SJan Kara } 1675f516130SJan Kara 1685f516130SJan Kara static struct fsnotify_mark *alloc_mark(void) 1695f516130SJan Kara { 1705f516130SJan Kara struct audit_tree_mark *amark; 1715f516130SJan Kara 1725f516130SJan Kara amark = kmem_cache_zalloc(audit_tree_mark_cachep, GFP_KERNEL); 1735f516130SJan Kara if (!amark) 1745f516130SJan Kara return NULL; 1755f516130SJan Kara fsnotify_init_mark(&amark->mark, audit_tree_group); 1765f516130SJan Kara amark->mark.mask = FS_IN_IGNORED; 1775f516130SJan Kara return &amark->mark; 17828a3a7ebSEric Paris } 17928a3a7ebSEric Paris 18028a3a7ebSEric Paris static struct audit_chunk *alloc_chunk(int count) 18128a3a7ebSEric Paris { 18228a3a7ebSEric Paris struct audit_chunk *chunk; 18328a3a7ebSEric Paris size_t size; 18428a3a7ebSEric Paris int i; 18528a3a7ebSEric Paris 18628a3a7ebSEric Paris size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node); 18728a3a7ebSEric Paris chunk = kzalloc(size, GFP_KERNEL); 18828a3a7ebSEric Paris if (!chunk) 18928a3a7ebSEric Paris return NULL; 19028a3a7ebSEric Paris 1915f516130SJan Kara chunk->mark = alloc_mark(); 1925f516130SJan Kara if (!chunk->mark) { 1935f516130SJan Kara kfree(chunk); 1945f516130SJan Kara return NULL; 1955f516130SJan Kara } 1965f516130SJan Kara audit_mark(chunk->mark)->chunk = chunk; 1975f516130SJan Kara 19828a3a7ebSEric Paris INIT_LIST_HEAD(&chunk->hash); 19928a3a7ebSEric Paris INIT_LIST_HEAD(&chunk->trees); 20028a3a7ebSEric Paris chunk->count = count; 20128a3a7ebSEric Paris atomic_long_set(&chunk->refs, 1); 20228a3a7ebSEric Paris for (i = 0; i < count; i++) { 20328a3a7ebSEric Paris INIT_LIST_HEAD(&chunk->owners[i].list); 20428a3a7ebSEric Paris chunk->owners[i].index = i; 20528a3a7ebSEric Paris } 20628a3a7ebSEric Paris return chunk; 20728a3a7ebSEric Paris } 20828a3a7ebSEric Paris 20974c3cbe3SAl Viro enum {HASH_SIZE = 128}; 21074c3cbe3SAl Viro static struct list_head chunk_hash_heads[HASH_SIZE]; 21174c3cbe3SAl Viro static __cacheline_aligned_in_smp DEFINE_SPINLOCK(hash_lock); 21274c3cbe3SAl Viro 213f410ff65SJan Kara /* Function to return search key in our hash from inode. */ 214f410ff65SJan Kara static unsigned long inode_to_key(const struct inode *inode) 21574c3cbe3SAl Viro { 21636f10f55SAmir Goldstein /* Use address pointed to by connector->obj as the key */ 21736f10f55SAmir Goldstein return (unsigned long)&inode->i_fsnotify_marks; 218f410ff65SJan Kara } 219f410ff65SJan Kara 220f410ff65SJan Kara static inline struct list_head *chunk_hash(unsigned long key) 221f410ff65SJan Kara { 222f410ff65SJan Kara unsigned long n = key / L1_CACHE_BYTES; 22374c3cbe3SAl Viro return chunk_hash_heads + n % HASH_SIZE; 22474c3cbe3SAl Viro } 22574c3cbe3SAl Viro 2269f16d2e6SJan Kara /* hash_lock & entry->group->mark_mutex is held by caller */ 22774c3cbe3SAl Viro static void insert_hash(struct audit_chunk *chunk) 22874c3cbe3SAl Viro { 22928a3a7ebSEric Paris struct list_head *list; 23028a3a7ebSEric Paris 2311635e572SJan Kara /* 2321635e572SJan Kara * Make sure chunk is fully initialized before making it visible in the 2331635e572SJan Kara * hash. Pairs with a data dependency barrier in READ_ONCE() in 2341635e572SJan Kara * audit_tree_lookup(). 2351635e572SJan Kara */ 2361635e572SJan Kara smp_wmb(); 2378d20d6e9SJan Kara WARN_ON_ONCE(!chunk->key); 2388d20d6e9SJan Kara list = chunk_hash(chunk->key); 23974c3cbe3SAl Viro list_add_rcu(&chunk->hash, list); 24074c3cbe3SAl Viro } 24174c3cbe3SAl Viro 24274c3cbe3SAl Viro /* called under rcu_read_lock */ 24374c3cbe3SAl Viro struct audit_chunk *audit_tree_lookup(const struct inode *inode) 24474c3cbe3SAl Viro { 245f410ff65SJan Kara unsigned long key = inode_to_key(inode); 246f410ff65SJan Kara struct list_head *list = chunk_hash(key); 2476793a051SPaul E. McKenney struct audit_chunk *p; 24874c3cbe3SAl Viro 2496793a051SPaul E. McKenney list_for_each_entry_rcu(p, list, hash) { 2501635e572SJan Kara /* 2511635e572SJan Kara * We use a data dependency barrier in READ_ONCE() to make sure 2521635e572SJan Kara * the chunk we see is fully initialized. 2531635e572SJan Kara */ 2541635e572SJan Kara if (READ_ONCE(p->key) == key) { 2558f7b0ba1SAl Viro atomic_long_inc(&p->refs); 25674c3cbe3SAl Viro return p; 25774c3cbe3SAl Viro } 25874c3cbe3SAl Viro } 25974c3cbe3SAl Viro return NULL; 26074c3cbe3SAl Viro } 26174c3cbe3SAl Viro 2626f1b5d7aSYaowei Bai bool audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree) 26374c3cbe3SAl Viro { 26474c3cbe3SAl Viro int n; 26574c3cbe3SAl Viro for (n = 0; n < chunk->count; n++) 26674c3cbe3SAl Viro if (chunk->owners[n].owner == tree) 2676f1b5d7aSYaowei Bai return true; 2686f1b5d7aSYaowei Bai return false; 26974c3cbe3SAl Viro } 27074c3cbe3SAl Viro 27174c3cbe3SAl Viro /* tagging and untagging inodes with trees */ 27274c3cbe3SAl Viro 2738f7b0ba1SAl Viro static struct audit_chunk *find_chunk(struct node *p) 27474c3cbe3SAl Viro { 2758f7b0ba1SAl Viro int index = p->index & ~(1U<<31); 2768f7b0ba1SAl Viro p -= index; 2778f7b0ba1SAl Viro return container_of(p, struct audit_chunk, owners[0]); 2788f7b0ba1SAl Viro } 2798f7b0ba1SAl Viro 280c22fcde7SJan Kara static void replace_chunk(struct audit_chunk *new, struct audit_chunk *old) 281d31b326dSJan Kara { 282d31b326dSJan Kara struct audit_tree *owner; 283d31b326dSJan Kara int i, j; 284d31b326dSJan Kara 285d31b326dSJan Kara new->key = old->key; 286d31b326dSJan Kara list_splice_init(&old->trees, &new->trees); 287d31b326dSJan Kara list_for_each_entry(owner, &new->trees, same_root) 288d31b326dSJan Kara owner->root = new; 289d31b326dSJan Kara for (i = j = 0; j < old->count; i++, j++) { 290c22fcde7SJan Kara if (!old->owners[j].owner) { 291d31b326dSJan Kara i--; 292d31b326dSJan Kara continue; 293d31b326dSJan Kara } 294d31b326dSJan Kara owner = old->owners[j].owner; 295d31b326dSJan Kara new->owners[i].owner = owner; 296d31b326dSJan Kara new->owners[i].index = old->owners[j].index - j + i; 297d31b326dSJan Kara if (!owner) /* result of earlier fallback */ 298d31b326dSJan Kara continue; 299d31b326dSJan Kara get_tree(owner); 300d31b326dSJan Kara list_replace_init(&old->owners[j].list, &new->owners[i].list); 301d31b326dSJan Kara } 302d31b326dSJan Kara /* 303d31b326dSJan Kara * Make sure chunk is fully initialized before making it visible in the 304d31b326dSJan Kara * hash. Pairs with a data dependency barrier in READ_ONCE() in 305d31b326dSJan Kara * audit_tree_lookup(). 306d31b326dSJan Kara */ 307d31b326dSJan Kara smp_wmb(); 308d31b326dSJan Kara list_replace_rcu(&old->hash, &new->hash); 309d31b326dSJan Kara } 310d31b326dSJan Kara 31149a4ee7dSJan Kara static void remove_chunk_node(struct audit_chunk *chunk, struct node *p) 31249a4ee7dSJan Kara { 31349a4ee7dSJan Kara struct audit_tree *owner = p->owner; 31449a4ee7dSJan Kara 31549a4ee7dSJan Kara if (owner->root == chunk) { 31649a4ee7dSJan Kara list_del_init(&owner->same_root); 31749a4ee7dSJan Kara owner->root = NULL; 31849a4ee7dSJan Kara } 31949a4ee7dSJan Kara list_del_init(&p->list); 32049a4ee7dSJan Kara p->owner = NULL; 32149a4ee7dSJan Kara put_tree(owner); 32249a4ee7dSJan Kara } 32349a4ee7dSJan Kara 324c22fcde7SJan Kara static int chunk_count_trees(struct audit_chunk *chunk) 325c22fcde7SJan Kara { 326c22fcde7SJan Kara int i; 327c22fcde7SJan Kara int ret = 0; 328c22fcde7SJan Kara 329c22fcde7SJan Kara for (i = 0; i < chunk->count; i++) 330c22fcde7SJan Kara if (chunk->owners[i].owner) 331c22fcde7SJan Kara ret++; 332c22fcde7SJan Kara return ret; 333c22fcde7SJan Kara } 334c22fcde7SJan Kara 3358432c700SJan Kara static void untag_chunk(struct audit_chunk *chunk, struct fsnotify_mark *entry) 3368f7b0ba1SAl Viro { 3378432c700SJan Kara struct audit_chunk *new; 338c22fcde7SJan Kara int size; 33974c3cbe3SAl Viro 3408432c700SJan Kara mutex_lock(&audit_tree_group->mark_mutex); 3416b3f05d2SJan Kara /* 3426b3f05d2SJan Kara * mark_mutex protects mark from getting detached and thus also from 34336f10f55SAmir Goldstein * mark->connector->obj getting NULL. 3446b3f05d2SJan Kara */ 3458432c700SJan Kara if (chunk->dead || !(entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) 3468432c700SJan Kara goto out_mutex; 34774c3cbe3SAl Viro 348c22fcde7SJan Kara size = chunk_count_trees(chunk); 34974c3cbe3SAl Viro if (!size) { 35074c3cbe3SAl Viro chunk->dead = 1; 35174c3cbe3SAl Viro spin_lock(&hash_lock); 35274c3cbe3SAl Viro list_del_init(&chunk->trees); 35374c3cbe3SAl Viro list_del_rcu(&chunk->hash); 35474c3cbe3SAl Viro spin_unlock(&hash_lock); 355b1e4603bSJan Kara fsnotify_detach_mark(entry); 3568432c700SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 357b1e4603bSJan Kara fsnotify_free_mark(entry); 3588432c700SJan Kara return; 35974c3cbe3SAl Viro } 36074c3cbe3SAl Viro 361c22fcde7SJan Kara new = alloc_chunk(size); 36274c3cbe3SAl Viro if (!new) 36349a4ee7dSJan Kara goto out_mutex; 364f7a998a9SAl Viro 3655f516130SJan Kara if (fsnotify_add_mark_locked(new->mark, entry->connector->obj, 36636f10f55SAmir Goldstein FSNOTIFY_OBJ_TYPE_INODE, 1)) { 3675f516130SJan Kara fsnotify_put_mark(new->mark); 36849a4ee7dSJan Kara goto out_mutex; 36974c3cbe3SAl Viro } 37074c3cbe3SAl Viro 37174c3cbe3SAl Viro chunk->dead = 1; 37274c3cbe3SAl Viro spin_lock(&hash_lock); 3731635e572SJan Kara /* 374d31b326dSJan Kara * This has to go last when updating chunk as once replace_chunk() is 375d31b326dSJan Kara * called, new RCU readers can see the new chunk. 3761635e572SJan Kara */ 377c22fcde7SJan Kara replace_chunk(new, chunk); 37874c3cbe3SAl Viro spin_unlock(&hash_lock); 379b1e4603bSJan Kara fsnotify_detach_mark(entry); 3808432c700SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 381b1e4603bSJan Kara fsnotify_free_mark(entry); 3825f516130SJan Kara fsnotify_put_mark(new->mark); /* drop initial reference */ 3838432c700SJan Kara return; 38474c3cbe3SAl Viro 38549a4ee7dSJan Kara out_mutex: 3868432c700SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 38774c3cbe3SAl Viro } 38874c3cbe3SAl Viro 389a5789b07SJan Kara /* Call with group->mark_mutex held, releases it */ 39074c3cbe3SAl Viro static int create_chunk(struct inode *inode, struct audit_tree *tree) 39174c3cbe3SAl Viro { 392e61ce867SEric Paris struct fsnotify_mark *entry; 39374c3cbe3SAl Viro struct audit_chunk *chunk = alloc_chunk(1); 394a5789b07SJan Kara 395a5789b07SJan Kara if (!chunk) { 396a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 39774c3cbe3SAl Viro return -ENOMEM; 398a5789b07SJan Kara } 39974c3cbe3SAl Viro 4005f516130SJan Kara entry = chunk->mark; 401a5789b07SJan Kara if (fsnotify_add_inode_mark_locked(entry, inode, 0)) { 402a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 4030fe33aaeSMiklos Szeredi fsnotify_put_mark(entry); 40474c3cbe3SAl Viro return -ENOSPC; 40574c3cbe3SAl Viro } 40674c3cbe3SAl Viro 40774c3cbe3SAl Viro spin_lock(&hash_lock); 40874c3cbe3SAl Viro if (tree->goner) { 40974c3cbe3SAl Viro spin_unlock(&hash_lock); 41074c3cbe3SAl Viro chunk->dead = 1; 411b1e4603bSJan Kara fsnotify_detach_mark(entry); 412a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 413b1e4603bSJan Kara fsnotify_free_mark(entry); 41428a3a7ebSEric Paris fsnotify_put_mark(entry); 41574c3cbe3SAl Viro return 0; 41674c3cbe3SAl Viro } 41774c3cbe3SAl Viro chunk->owners[0].index = (1U << 31); 41874c3cbe3SAl Viro chunk->owners[0].owner = tree; 41974c3cbe3SAl Viro get_tree(tree); 42074c3cbe3SAl Viro list_add(&chunk->owners[0].list, &tree->chunks); 42174c3cbe3SAl Viro if (!tree->root) { 42274c3cbe3SAl Viro tree->root = chunk; 42374c3cbe3SAl Viro list_add(&tree->same_root, &chunk->trees); 42474c3cbe3SAl Viro } 4258d20d6e9SJan Kara chunk->key = inode_to_key(inode); 4261635e572SJan Kara /* 4271635e572SJan Kara * Inserting into the hash table has to go last as once we do that RCU 4281635e572SJan Kara * readers can see the chunk. 4291635e572SJan Kara */ 43074c3cbe3SAl Viro insert_hash(chunk); 43174c3cbe3SAl Viro spin_unlock(&hash_lock); 432a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 433b3e8692bSMiklos Szeredi fsnotify_put_mark(entry); /* drop initial reference */ 43474c3cbe3SAl Viro return 0; 43574c3cbe3SAl Viro } 43674c3cbe3SAl Viro 43774c3cbe3SAl Viro /* the first tagged inode becomes root of tree */ 43874c3cbe3SAl Viro static int tag_chunk(struct inode *inode, struct audit_tree *tree) 43974c3cbe3SAl Viro { 440e61ce867SEric Paris struct fsnotify_mark *old_entry, *chunk_entry; 44174c3cbe3SAl Viro struct audit_chunk *chunk, *old; 44274c3cbe3SAl Viro struct node *p; 44374c3cbe3SAl Viro int n; 44474c3cbe3SAl Viro 445a5789b07SJan Kara mutex_lock(&audit_tree_group->mark_mutex); 446b1362edfSJan Kara old_entry = fsnotify_find_mark(&inode->i_fsnotify_marks, 447b1362edfSJan Kara audit_tree_group); 44828a3a7ebSEric Paris if (!old_entry) 44974c3cbe3SAl Viro return create_chunk(inode, tree); 45074c3cbe3SAl Viro 4515f516130SJan Kara old = mark_chunk(old_entry); 45274c3cbe3SAl Viro 45374c3cbe3SAl Viro /* are we already there? */ 45474c3cbe3SAl Viro spin_lock(&hash_lock); 45574c3cbe3SAl Viro for (n = 0; n < old->count; n++) { 45674c3cbe3SAl Viro if (old->owners[n].owner == tree) { 45774c3cbe3SAl Viro spin_unlock(&hash_lock); 458a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 45928a3a7ebSEric Paris fsnotify_put_mark(old_entry); 46074c3cbe3SAl Viro return 0; 46174c3cbe3SAl Viro } 46274c3cbe3SAl Viro } 46374c3cbe3SAl Viro spin_unlock(&hash_lock); 46474c3cbe3SAl Viro 46574c3cbe3SAl Viro chunk = alloc_chunk(old->count + 1); 466b4c30aadSAl Viro if (!chunk) { 467a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 46828a3a7ebSEric Paris fsnotify_put_mark(old_entry); 46974c3cbe3SAl Viro return -ENOMEM; 470b4c30aadSAl Viro } 47174c3cbe3SAl Viro 4725f516130SJan Kara chunk_entry = chunk->mark; 47328a3a7ebSEric Paris 4746b3f05d2SJan Kara /* 4756b3f05d2SJan Kara * mark_mutex protects mark from getting detached and thus also from 47636f10f55SAmir Goldstein * mark->connector->obj getting NULL. 4776b3f05d2SJan Kara */ 47843471d15SJan Kara if (!(old_entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { 47928a3a7ebSEric Paris /* old_entry is being shot, lets just lie */ 480a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 48128a3a7ebSEric Paris fsnotify_put_mark(old_entry); 4825f516130SJan Kara fsnotify_put_mark(chunk->mark); 48328a3a7ebSEric Paris return -ENOENT; 48428a3a7ebSEric Paris } 48528a3a7ebSEric Paris 48636f10f55SAmir Goldstein if (fsnotify_add_mark_locked(chunk_entry, old_entry->connector->obj, 48736f10f55SAmir Goldstein FSNOTIFY_OBJ_TYPE_INODE, 1)) { 488a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 4890fe33aaeSMiklos Szeredi fsnotify_put_mark(chunk_entry); 49028a3a7ebSEric Paris fsnotify_put_mark(old_entry); 49174c3cbe3SAl Viro return -ENOSPC; 49274c3cbe3SAl Viro } 49328a3a7ebSEric Paris 49474c3cbe3SAl Viro spin_lock(&hash_lock); 49574c3cbe3SAl Viro if (tree->goner) { 49674c3cbe3SAl Viro spin_unlock(&hash_lock); 49774c3cbe3SAl Viro chunk->dead = 1; 498b1e4603bSJan Kara fsnotify_detach_mark(chunk_entry); 499a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 500b1e4603bSJan Kara fsnotify_free_mark(chunk_entry); 50128a3a7ebSEric Paris fsnotify_put_mark(chunk_entry); 50228a3a7ebSEric Paris fsnotify_put_mark(old_entry); 50374c3cbe3SAl Viro return 0; 50474c3cbe3SAl Viro } 505d31b326dSJan Kara p = &chunk->owners[chunk->count - 1]; 50674c3cbe3SAl Viro p->index = (chunk->count - 1) | (1U<<31); 50774c3cbe3SAl Viro p->owner = tree; 50874c3cbe3SAl Viro get_tree(tree); 50974c3cbe3SAl Viro list_add(&p->list, &tree->chunks); 51074c3cbe3SAl Viro old->dead = 1; 51174c3cbe3SAl Viro if (!tree->root) { 51274c3cbe3SAl Viro tree->root = chunk; 51374c3cbe3SAl Viro list_add(&tree->same_root, &chunk->trees); 51474c3cbe3SAl Viro } 5151635e572SJan Kara /* 516d31b326dSJan Kara * This has to go last when updating chunk as once replace_chunk() is 517d31b326dSJan Kara * called, new RCU readers can see the new chunk. 5181635e572SJan Kara */ 519c22fcde7SJan Kara replace_chunk(chunk, old); 52074c3cbe3SAl Viro spin_unlock(&hash_lock); 521b1e4603bSJan Kara fsnotify_detach_mark(old_entry); 522a5789b07SJan Kara mutex_unlock(&audit_tree_group->mark_mutex); 523b1e4603bSJan Kara fsnotify_free_mark(old_entry); 524b3e8692bSMiklos Szeredi fsnotify_put_mark(chunk_entry); /* drop initial reference */ 52528a3a7ebSEric Paris fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ 52674c3cbe3SAl Viro return 0; 52774c3cbe3SAl Viro } 52874c3cbe3SAl Viro 5292991dd2bSRichard Guy Briggs static void audit_tree_log_remove_rule(struct audit_krule *rule) 53074c3cbe3SAl Viro { 53174c3cbe3SAl Viro struct audit_buffer *ab; 53274c3cbe3SAl Viro 53365a8766fSRichard Guy Briggs if (!audit_enabled) 53465a8766fSRichard Guy Briggs return; 53574c3cbe3SAl Viro ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); 5360644ec0cSKees Cook if (unlikely(!ab)) 5370644ec0cSKees Cook return; 538c1e8f06dSSteve Grubb audit_log_format(ab, "op=remove_rule"); 5399d960985SEric Paris audit_log_format(ab, " dir="); 54074c3cbe3SAl Viro audit_log_untrustedstring(ab, rule->tree->pathname); 5419d960985SEric Paris audit_log_key(ab, rule->filterkey); 54274c3cbe3SAl Viro audit_log_format(ab, " list=%d res=1", rule->listnr); 54374c3cbe3SAl Viro audit_log_end(ab); 5440644ec0cSKees Cook } 5450644ec0cSKees Cook 5460644ec0cSKees Cook static void kill_rules(struct audit_tree *tree) 5470644ec0cSKees Cook { 5480644ec0cSKees Cook struct audit_krule *rule, *next; 5490644ec0cSKees Cook struct audit_entry *entry; 5500644ec0cSKees Cook 5510644ec0cSKees Cook list_for_each_entry_safe(rule, next, &tree->rules, rlist) { 5520644ec0cSKees Cook entry = container_of(rule, struct audit_entry, rule); 5530644ec0cSKees Cook 5540644ec0cSKees Cook list_del_init(&rule->rlist); 5550644ec0cSKees Cook if (rule->tree) { 5560644ec0cSKees Cook /* not a half-baked one */ 5572991dd2bSRichard Guy Briggs audit_tree_log_remove_rule(rule); 55834d99af5SRichard Guy Briggs if (entry->rule.exe) 55934d99af5SRichard Guy Briggs audit_remove_mark(entry->rule.exe); 56074c3cbe3SAl Viro rule->tree = NULL; 56174c3cbe3SAl Viro list_del_rcu(&entry->list); 562e45aa212SAl Viro list_del(&entry->rule.list); 56374c3cbe3SAl Viro call_rcu(&entry->rcu, audit_free_rule_rcu); 56474c3cbe3SAl Viro } 56574c3cbe3SAl Viro } 56674c3cbe3SAl Viro } 56774c3cbe3SAl Viro 56874c3cbe3SAl Viro /* 5698432c700SJan Kara * Remove tree from chunks. If 'tagged' is set, remove tree only from tagged 5708432c700SJan Kara * chunks. The function expects tagged chunks are all at the beginning of the 5718432c700SJan Kara * chunks list. 57274c3cbe3SAl Viro */ 5738432c700SJan Kara static void prune_tree_chunks(struct audit_tree *victim, bool tagged) 57474c3cbe3SAl Viro { 57574c3cbe3SAl Viro spin_lock(&hash_lock); 57674c3cbe3SAl Viro while (!list_empty(&victim->chunks)) { 57774c3cbe3SAl Viro struct node *p; 5788432c700SJan Kara struct audit_chunk *chunk; 5798432c700SJan Kara struct fsnotify_mark *mark; 58074c3cbe3SAl Viro 5818432c700SJan Kara p = list_first_entry(&victim->chunks, struct node, list); 5828432c700SJan Kara /* have we run out of marked? */ 5838432c700SJan Kara if (tagged && !(p->index & (1U<<31))) 5848432c700SJan Kara break; 5858432c700SJan Kara chunk = find_chunk(p); 5868432c700SJan Kara mark = chunk->mark; 5878432c700SJan Kara remove_chunk_node(chunk, p); 5888432c700SJan Kara fsnotify_get_mark(mark); 5898432c700SJan Kara spin_unlock(&hash_lock); 59074c3cbe3SAl Viro 5918432c700SJan Kara untag_chunk(chunk, mark); 5928432c700SJan Kara fsnotify_put_mark(mark); 5938432c700SJan Kara 5948432c700SJan Kara spin_lock(&hash_lock); 59574c3cbe3SAl Viro } 59674c3cbe3SAl Viro spin_unlock(&hash_lock); 59774c3cbe3SAl Viro put_tree(victim); 59874c3cbe3SAl Viro } 59974c3cbe3SAl Viro 6008432c700SJan Kara /* 6018432c700SJan Kara * finish killing struct audit_tree 6028432c700SJan Kara */ 6038432c700SJan Kara static void prune_one(struct audit_tree *victim) 6048432c700SJan Kara { 6058432c700SJan Kara prune_tree_chunks(victim, false); 6068432c700SJan Kara } 6078432c700SJan Kara 60874c3cbe3SAl Viro /* trim the uncommitted chunks from tree */ 60974c3cbe3SAl Viro 61074c3cbe3SAl Viro static void trim_marked(struct audit_tree *tree) 61174c3cbe3SAl Viro { 61274c3cbe3SAl Viro struct list_head *p, *q; 61374c3cbe3SAl Viro spin_lock(&hash_lock); 61474c3cbe3SAl Viro if (tree->goner) { 61574c3cbe3SAl Viro spin_unlock(&hash_lock); 61674c3cbe3SAl Viro return; 61774c3cbe3SAl Viro } 61874c3cbe3SAl Viro /* reorder */ 61974c3cbe3SAl Viro for (p = tree->chunks.next; p != &tree->chunks; p = q) { 62074c3cbe3SAl Viro struct node *node = list_entry(p, struct node, list); 62174c3cbe3SAl Viro q = p->next; 62274c3cbe3SAl Viro if (node->index & (1U<<31)) { 62374c3cbe3SAl Viro list_del_init(p); 62474c3cbe3SAl Viro list_add(p, &tree->chunks); 62574c3cbe3SAl Viro } 62674c3cbe3SAl Viro } 6278432c700SJan Kara spin_unlock(&hash_lock); 62874c3cbe3SAl Viro 6298432c700SJan Kara prune_tree_chunks(tree, true); 63074c3cbe3SAl Viro 6318432c700SJan Kara spin_lock(&hash_lock); 63274c3cbe3SAl Viro if (!tree->root && !tree->goner) { 63374c3cbe3SAl Viro tree->goner = 1; 63474c3cbe3SAl Viro spin_unlock(&hash_lock); 63574c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 63674c3cbe3SAl Viro kill_rules(tree); 63774c3cbe3SAl Viro list_del_init(&tree->list); 63874c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 63974c3cbe3SAl Viro prune_one(tree); 64074c3cbe3SAl Viro } else { 64174c3cbe3SAl Viro spin_unlock(&hash_lock); 64274c3cbe3SAl Viro } 64374c3cbe3SAl Viro } 64474c3cbe3SAl Viro 645916d7576SAl Viro static void audit_schedule_prune(void); 646916d7576SAl Viro 64774c3cbe3SAl Viro /* called with audit_filter_mutex */ 64874c3cbe3SAl Viro int audit_remove_tree_rule(struct audit_krule *rule) 64974c3cbe3SAl Viro { 65074c3cbe3SAl Viro struct audit_tree *tree; 65174c3cbe3SAl Viro tree = rule->tree; 65274c3cbe3SAl Viro if (tree) { 65374c3cbe3SAl Viro spin_lock(&hash_lock); 65474c3cbe3SAl Viro list_del_init(&rule->rlist); 65574c3cbe3SAl Viro if (list_empty(&tree->rules) && !tree->goner) { 65674c3cbe3SAl Viro tree->root = NULL; 65774c3cbe3SAl Viro list_del_init(&tree->same_root); 65874c3cbe3SAl Viro tree->goner = 1; 65974c3cbe3SAl Viro list_move(&tree->list, &prune_list); 66074c3cbe3SAl Viro rule->tree = NULL; 66174c3cbe3SAl Viro spin_unlock(&hash_lock); 66274c3cbe3SAl Viro audit_schedule_prune(); 66374c3cbe3SAl Viro return 1; 66474c3cbe3SAl Viro } 66574c3cbe3SAl Viro rule->tree = NULL; 66674c3cbe3SAl Viro spin_unlock(&hash_lock); 66774c3cbe3SAl Viro return 1; 66874c3cbe3SAl Viro } 66974c3cbe3SAl Viro return 0; 67074c3cbe3SAl Viro } 67174c3cbe3SAl Viro 6721f707137SAl Viro static int compare_root(struct vfsmount *mnt, void *arg) 6731f707137SAl Viro { 674f410ff65SJan Kara return inode_to_key(d_backing_inode(mnt->mnt_root)) == 675f410ff65SJan Kara (unsigned long)arg; 6761f707137SAl Viro } 6771f707137SAl Viro 67874c3cbe3SAl Viro void audit_trim_trees(void) 67974c3cbe3SAl Viro { 68074c3cbe3SAl Viro struct list_head cursor; 68174c3cbe3SAl Viro 68274c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 68374c3cbe3SAl Viro list_add(&cursor, &tree_list); 68474c3cbe3SAl Viro while (cursor.next != &tree_list) { 68574c3cbe3SAl Viro struct audit_tree *tree; 68698bc993fSAl Viro struct path path; 68774c3cbe3SAl Viro struct vfsmount *root_mnt; 68874c3cbe3SAl Viro struct node *node; 68974c3cbe3SAl Viro int err; 69074c3cbe3SAl Viro 69174c3cbe3SAl Viro tree = container_of(cursor.next, struct audit_tree, list); 69274c3cbe3SAl Viro get_tree(tree); 69374c3cbe3SAl Viro list_del(&cursor); 69474c3cbe3SAl Viro list_add(&cursor, &tree->list); 69574c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 69674c3cbe3SAl Viro 69798bc993fSAl Viro err = kern_path(tree->pathname, 0, &path); 69874c3cbe3SAl Viro if (err) 69974c3cbe3SAl Viro goto skip_it; 70074c3cbe3SAl Viro 701589ff870SAl Viro root_mnt = collect_mounts(&path); 70298bc993fSAl Viro path_put(&path); 703be34d1a3SDavid Howells if (IS_ERR(root_mnt)) 70474c3cbe3SAl Viro goto skip_it; 70574c3cbe3SAl Viro 70674c3cbe3SAl Viro spin_lock(&hash_lock); 70774c3cbe3SAl Viro list_for_each_entry(node, &tree->chunks, list) { 70828a3a7ebSEric Paris struct audit_chunk *chunk = find_chunk(node); 70925985edcSLucas De Marchi /* this could be NULL if the watch is dying else where... */ 71074c3cbe3SAl Viro node->index |= 1U<<31; 711f410ff65SJan Kara if (iterate_mounts(compare_root, 7128d20d6e9SJan Kara (void *)(chunk->key), 713f410ff65SJan Kara root_mnt)) 71474c3cbe3SAl Viro node->index &= ~(1U<<31); 71574c3cbe3SAl Viro } 71674c3cbe3SAl Viro spin_unlock(&hash_lock); 71774c3cbe3SAl Viro trim_marked(tree); 71874c3cbe3SAl Viro drop_collected_mounts(root_mnt); 71974c3cbe3SAl Viro skip_it: 72012b2f117SChen Gang put_tree(tree); 72174c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 72274c3cbe3SAl Viro } 72374c3cbe3SAl Viro list_del(&cursor); 72474c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 72574c3cbe3SAl Viro } 72674c3cbe3SAl Viro 72774c3cbe3SAl Viro int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) 72874c3cbe3SAl Viro { 72974c3cbe3SAl Viro 73074c3cbe3SAl Viro if (pathname[0] != '/' || 73174c3cbe3SAl Viro rule->listnr != AUDIT_FILTER_EXIT || 7325af75d8dSAl Viro op != Audit_equal || 73374c3cbe3SAl Viro rule->inode_f || rule->watch || rule->tree) 73474c3cbe3SAl Viro return -EINVAL; 73574c3cbe3SAl Viro rule->tree = alloc_tree(pathname); 73674c3cbe3SAl Viro if (!rule->tree) 73774c3cbe3SAl Viro return -ENOMEM; 73874c3cbe3SAl Viro return 0; 73974c3cbe3SAl Viro } 74074c3cbe3SAl Viro 74174c3cbe3SAl Viro void audit_put_tree(struct audit_tree *tree) 74274c3cbe3SAl Viro { 74374c3cbe3SAl Viro put_tree(tree); 74474c3cbe3SAl Viro } 74574c3cbe3SAl Viro 7461f707137SAl Viro static int tag_mount(struct vfsmount *mnt, void *arg) 7471f707137SAl Viro { 7483b362157SDavid Howells return tag_chunk(d_backing_inode(mnt->mnt_root), arg); 7491f707137SAl Viro } 7501f707137SAl Viro 751f1aaf262SImre Palik /* 752f1aaf262SImre Palik * That gets run when evict_chunk() ends up needing to kill audit_tree. 753f1aaf262SImre Palik * Runs from a separate thread. 754f1aaf262SImre Palik */ 755f1aaf262SImre Palik static int prune_tree_thread(void *unused) 756f1aaf262SImre Palik { 757f1aaf262SImre Palik for (;;) { 7580bf676d1SJiri Slaby if (list_empty(&prune_list)) { 759f1aaf262SImre Palik set_current_state(TASK_INTERRUPTIBLE); 760f1aaf262SImre Palik schedule(); 7610bf676d1SJiri Slaby } 762f1aaf262SImre Palik 763ce423631SPaul Moore audit_ctl_lock(); 764f1aaf262SImre Palik mutex_lock(&audit_filter_mutex); 765f1aaf262SImre Palik 766f1aaf262SImre Palik while (!list_empty(&prune_list)) { 767f1aaf262SImre Palik struct audit_tree *victim; 768f1aaf262SImre Palik 769f1aaf262SImre Palik victim = list_entry(prune_list.next, 770f1aaf262SImre Palik struct audit_tree, list); 771f1aaf262SImre Palik list_del_init(&victim->list); 772f1aaf262SImre Palik 773f1aaf262SImre Palik mutex_unlock(&audit_filter_mutex); 774f1aaf262SImre Palik 775f1aaf262SImre Palik prune_one(victim); 776f1aaf262SImre Palik 777f1aaf262SImre Palik mutex_lock(&audit_filter_mutex); 778f1aaf262SImre Palik } 779f1aaf262SImre Palik 780f1aaf262SImre Palik mutex_unlock(&audit_filter_mutex); 781ce423631SPaul Moore audit_ctl_unlock(); 782f1aaf262SImre Palik } 783f1aaf262SImre Palik return 0; 784f1aaf262SImre Palik } 785f1aaf262SImre Palik 786f1aaf262SImre Palik static int audit_launch_prune(void) 787f1aaf262SImre Palik { 788f1aaf262SImre Palik if (prune_thread) 789f1aaf262SImre Palik return 0; 7900bf676d1SJiri Slaby prune_thread = kthread_run(prune_tree_thread, NULL, 791f1aaf262SImre Palik "audit_prune_tree"); 792f1aaf262SImre Palik if (IS_ERR(prune_thread)) { 793f1aaf262SImre Palik pr_err("cannot start thread audit_prune_tree"); 794f1aaf262SImre Palik prune_thread = NULL; 795f1aaf262SImre Palik return -ENOMEM; 796f1aaf262SImre Palik } 7970bf676d1SJiri Slaby return 0; 798f1aaf262SImre Palik } 799f1aaf262SImre Palik 80074c3cbe3SAl Viro /* called with audit_filter_mutex */ 80174c3cbe3SAl Viro int audit_add_tree_rule(struct audit_krule *rule) 80274c3cbe3SAl Viro { 80374c3cbe3SAl Viro struct audit_tree *seed = rule->tree, *tree; 80498bc993fSAl Viro struct path path; 8051f707137SAl Viro struct vfsmount *mnt; 80674c3cbe3SAl Viro int err; 80774c3cbe3SAl Viro 808736f3203SChen Gang rule->tree = NULL; 80974c3cbe3SAl Viro list_for_each_entry(tree, &tree_list, list) { 81074c3cbe3SAl Viro if (!strcmp(seed->pathname, tree->pathname)) { 81174c3cbe3SAl Viro put_tree(seed); 81274c3cbe3SAl Viro rule->tree = tree; 81374c3cbe3SAl Viro list_add(&rule->rlist, &tree->rules); 81474c3cbe3SAl Viro return 0; 81574c3cbe3SAl Viro } 81674c3cbe3SAl Viro } 81774c3cbe3SAl Viro tree = seed; 81874c3cbe3SAl Viro list_add(&tree->list, &tree_list); 81974c3cbe3SAl Viro list_add(&rule->rlist, &tree->rules); 82074c3cbe3SAl Viro /* do not set rule->tree yet */ 82174c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 82274c3cbe3SAl Viro 823f1aaf262SImre Palik if (unlikely(!prune_thread)) { 824f1aaf262SImre Palik err = audit_launch_prune(); 825f1aaf262SImre Palik if (err) 826f1aaf262SImre Palik goto Err; 827f1aaf262SImre Palik } 828f1aaf262SImre Palik 82998bc993fSAl Viro err = kern_path(tree->pathname, 0, &path); 83074c3cbe3SAl Viro if (err) 83174c3cbe3SAl Viro goto Err; 832589ff870SAl Viro mnt = collect_mounts(&path); 83398bc993fSAl Viro path_put(&path); 834be34d1a3SDavid Howells if (IS_ERR(mnt)) { 835be34d1a3SDavid Howells err = PTR_ERR(mnt); 83674c3cbe3SAl Viro goto Err; 83774c3cbe3SAl Viro } 83874c3cbe3SAl Viro 83974c3cbe3SAl Viro get_tree(tree); 8401f707137SAl Viro err = iterate_mounts(tag_mount, tree, mnt); 84174c3cbe3SAl Viro drop_collected_mounts(mnt); 84274c3cbe3SAl Viro 84374c3cbe3SAl Viro if (!err) { 84474c3cbe3SAl Viro struct node *node; 84574c3cbe3SAl Viro spin_lock(&hash_lock); 84674c3cbe3SAl Viro list_for_each_entry(node, &tree->chunks, list) 84774c3cbe3SAl Viro node->index &= ~(1U<<31); 84874c3cbe3SAl Viro spin_unlock(&hash_lock); 84974c3cbe3SAl Viro } else { 85074c3cbe3SAl Viro trim_marked(tree); 85174c3cbe3SAl Viro goto Err; 85274c3cbe3SAl Viro } 85374c3cbe3SAl Viro 85474c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 85574c3cbe3SAl Viro if (list_empty(&rule->rlist)) { 85674c3cbe3SAl Viro put_tree(tree); 85774c3cbe3SAl Viro return -ENOENT; 85874c3cbe3SAl Viro } 85974c3cbe3SAl Viro rule->tree = tree; 86074c3cbe3SAl Viro put_tree(tree); 86174c3cbe3SAl Viro 86274c3cbe3SAl Viro return 0; 86374c3cbe3SAl Viro Err: 86474c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 86574c3cbe3SAl Viro list_del_init(&tree->list); 86674c3cbe3SAl Viro list_del_init(&tree->rules); 86774c3cbe3SAl Viro put_tree(tree); 86874c3cbe3SAl Viro return err; 86974c3cbe3SAl Viro } 87074c3cbe3SAl Viro 87174c3cbe3SAl Viro int audit_tag_tree(char *old, char *new) 87274c3cbe3SAl Viro { 87374c3cbe3SAl Viro struct list_head cursor, barrier; 87474c3cbe3SAl Viro int failed = 0; 8752096f759SAl Viro struct path path1, path2; 87674c3cbe3SAl Viro struct vfsmount *tagged; 87774c3cbe3SAl Viro int err; 87874c3cbe3SAl Viro 8792096f759SAl Viro err = kern_path(new, 0, &path2); 88074c3cbe3SAl Viro if (err) 88174c3cbe3SAl Viro return err; 8822096f759SAl Viro tagged = collect_mounts(&path2); 8832096f759SAl Viro path_put(&path2); 884be34d1a3SDavid Howells if (IS_ERR(tagged)) 885be34d1a3SDavid Howells return PTR_ERR(tagged); 88674c3cbe3SAl Viro 8872096f759SAl Viro err = kern_path(old, 0, &path1); 88874c3cbe3SAl Viro if (err) { 88974c3cbe3SAl Viro drop_collected_mounts(tagged); 89074c3cbe3SAl Viro return err; 89174c3cbe3SAl Viro } 89274c3cbe3SAl Viro 89374c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 89474c3cbe3SAl Viro list_add(&barrier, &tree_list); 89574c3cbe3SAl Viro list_add(&cursor, &barrier); 89674c3cbe3SAl Viro 89774c3cbe3SAl Viro while (cursor.next != &tree_list) { 89874c3cbe3SAl Viro struct audit_tree *tree; 8992096f759SAl Viro int good_one = 0; 90074c3cbe3SAl Viro 90174c3cbe3SAl Viro tree = container_of(cursor.next, struct audit_tree, list); 90274c3cbe3SAl Viro get_tree(tree); 90374c3cbe3SAl Viro list_del(&cursor); 90474c3cbe3SAl Viro list_add(&cursor, &tree->list); 90574c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 90674c3cbe3SAl Viro 9072096f759SAl Viro err = kern_path(tree->pathname, 0, &path2); 9082096f759SAl Viro if (!err) { 9092096f759SAl Viro good_one = path_is_under(&path1, &path2); 9102096f759SAl Viro path_put(&path2); 91174c3cbe3SAl Viro } 91274c3cbe3SAl Viro 9132096f759SAl Viro if (!good_one) { 91474c3cbe3SAl Viro put_tree(tree); 91574c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 91674c3cbe3SAl Viro continue; 91774c3cbe3SAl Viro } 91874c3cbe3SAl Viro 9191f707137SAl Viro failed = iterate_mounts(tag_mount, tree, tagged); 92074c3cbe3SAl Viro if (failed) { 92174c3cbe3SAl Viro put_tree(tree); 92274c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 92374c3cbe3SAl Viro break; 92474c3cbe3SAl Viro } 92574c3cbe3SAl Viro 92674c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 92774c3cbe3SAl Viro spin_lock(&hash_lock); 92874c3cbe3SAl Viro if (!tree->goner) { 92974c3cbe3SAl Viro list_del(&tree->list); 93074c3cbe3SAl Viro list_add(&tree->list, &tree_list); 93174c3cbe3SAl Viro } 93274c3cbe3SAl Viro spin_unlock(&hash_lock); 93374c3cbe3SAl Viro put_tree(tree); 93474c3cbe3SAl Viro } 93574c3cbe3SAl Viro 93674c3cbe3SAl Viro while (barrier.prev != &tree_list) { 93774c3cbe3SAl Viro struct audit_tree *tree; 93874c3cbe3SAl Viro 93974c3cbe3SAl Viro tree = container_of(barrier.prev, struct audit_tree, list); 94074c3cbe3SAl Viro get_tree(tree); 94174c3cbe3SAl Viro list_del(&tree->list); 94274c3cbe3SAl Viro list_add(&tree->list, &barrier); 94374c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 94474c3cbe3SAl Viro 94574c3cbe3SAl Viro if (!failed) { 94674c3cbe3SAl Viro struct node *node; 94774c3cbe3SAl Viro spin_lock(&hash_lock); 94874c3cbe3SAl Viro list_for_each_entry(node, &tree->chunks, list) 94974c3cbe3SAl Viro node->index &= ~(1U<<31); 95074c3cbe3SAl Viro spin_unlock(&hash_lock); 95174c3cbe3SAl Viro } else { 95274c3cbe3SAl Viro trim_marked(tree); 95374c3cbe3SAl Viro } 95474c3cbe3SAl Viro 95574c3cbe3SAl Viro put_tree(tree); 95674c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 95774c3cbe3SAl Viro } 95874c3cbe3SAl Viro list_del(&barrier); 95974c3cbe3SAl Viro list_del(&cursor); 96074c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 9612096f759SAl Viro path_put(&path1); 96274c3cbe3SAl Viro drop_collected_mounts(tagged); 96374c3cbe3SAl Viro return failed; 96474c3cbe3SAl Viro } 96574c3cbe3SAl Viro 966916d7576SAl Viro 967916d7576SAl Viro static void audit_schedule_prune(void) 968916d7576SAl Viro { 969f1aaf262SImre Palik wake_up_process(prune_thread); 970916d7576SAl Viro } 971916d7576SAl Viro 972916d7576SAl Viro /* 973916d7576SAl Viro * ... and that one is done if evict_chunk() decides to delay until the end 974916d7576SAl Viro * of syscall. Runs synchronously. 975916d7576SAl Viro */ 976916d7576SAl Viro void audit_kill_trees(struct list_head *list) 977916d7576SAl Viro { 978ce423631SPaul Moore audit_ctl_lock(); 979916d7576SAl Viro mutex_lock(&audit_filter_mutex); 980916d7576SAl Viro 981916d7576SAl Viro while (!list_empty(list)) { 982916d7576SAl Viro struct audit_tree *victim; 983916d7576SAl Viro 984916d7576SAl Viro victim = list_entry(list->next, struct audit_tree, list); 985916d7576SAl Viro kill_rules(victim); 986916d7576SAl Viro list_del_init(&victim->list); 987916d7576SAl Viro 988916d7576SAl Viro mutex_unlock(&audit_filter_mutex); 989916d7576SAl Viro 990916d7576SAl Viro prune_one(victim); 991916d7576SAl Viro 992916d7576SAl Viro mutex_lock(&audit_filter_mutex); 993916d7576SAl Viro } 994916d7576SAl Viro 995916d7576SAl Viro mutex_unlock(&audit_filter_mutex); 996ce423631SPaul Moore audit_ctl_unlock(); 99774c3cbe3SAl Viro } 99874c3cbe3SAl Viro 99974c3cbe3SAl Viro /* 100074c3cbe3SAl Viro * Here comes the stuff asynchronous to auditctl operations 100174c3cbe3SAl Viro */ 100274c3cbe3SAl Viro 100374c3cbe3SAl Viro static void evict_chunk(struct audit_chunk *chunk) 100474c3cbe3SAl Viro { 100574c3cbe3SAl Viro struct audit_tree *owner; 1006916d7576SAl Viro struct list_head *postponed = audit_killed_trees(); 1007916d7576SAl Viro int need_prune = 0; 100874c3cbe3SAl Viro int n; 100974c3cbe3SAl Viro 101074c3cbe3SAl Viro if (chunk->dead) 101174c3cbe3SAl Viro return; 101274c3cbe3SAl Viro 101374c3cbe3SAl Viro chunk->dead = 1; 101474c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 101574c3cbe3SAl Viro spin_lock(&hash_lock); 101674c3cbe3SAl Viro while (!list_empty(&chunk->trees)) { 101774c3cbe3SAl Viro owner = list_entry(chunk->trees.next, 101874c3cbe3SAl Viro struct audit_tree, same_root); 101974c3cbe3SAl Viro owner->goner = 1; 102074c3cbe3SAl Viro owner->root = NULL; 102174c3cbe3SAl Viro list_del_init(&owner->same_root); 102274c3cbe3SAl Viro spin_unlock(&hash_lock); 1023916d7576SAl Viro if (!postponed) { 102474c3cbe3SAl Viro kill_rules(owner); 102574c3cbe3SAl Viro list_move(&owner->list, &prune_list); 1026916d7576SAl Viro need_prune = 1; 1027916d7576SAl Viro } else { 1028916d7576SAl Viro list_move(&owner->list, postponed); 1029916d7576SAl Viro } 103074c3cbe3SAl Viro spin_lock(&hash_lock); 103174c3cbe3SAl Viro } 103274c3cbe3SAl Viro list_del_rcu(&chunk->hash); 103374c3cbe3SAl Viro for (n = 0; n < chunk->count; n++) 103474c3cbe3SAl Viro list_del_init(&chunk->owners[n].list); 103574c3cbe3SAl Viro spin_unlock(&hash_lock); 1036f1aaf262SImre Palik mutex_unlock(&audit_filter_mutex); 1037916d7576SAl Viro if (need_prune) 1038916d7576SAl Viro audit_schedule_prune(); 103974c3cbe3SAl Viro } 104074c3cbe3SAl Viro 10413a9b16b4SEric Paris static int audit_tree_handle_event(struct fsnotify_group *group, 10427053aee2SJan Kara struct inode *to_tell, 10433cd5eca8SAl Viro u32 mask, const void *data, int data_type, 10449385a84dSJan Kara const unsigned char *file_name, u32 cookie, 10459385a84dSJan Kara struct fsnotify_iter_info *iter_info) 104674c3cbe3SAl Viro { 104783c4c4b0SJan Kara return 0; 104828a3a7ebSEric Paris } 104974c3cbe3SAl Viro 1050e61ce867SEric Paris static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify_group *group) 105128a3a7ebSEric Paris { 10525f516130SJan Kara struct audit_chunk *chunk = mark_chunk(entry); 105328a3a7ebSEric Paris 105474c3cbe3SAl Viro evict_chunk(chunk); 1055b3e8692bSMiklos Szeredi 1056b3e8692bSMiklos Szeredi /* 1057b3e8692bSMiklos Szeredi * We are guaranteed to have at least one reference to the mark from 1058b3e8692bSMiklos Szeredi * either the inode or the caller of fsnotify_destroy_mark(). 1059b3e8692bSMiklos Szeredi */ 1060ab97f873SElena Reshetova BUG_ON(refcount_read(&entry->refcnt) < 1); 106174c3cbe3SAl Viro } 106274c3cbe3SAl Viro 106328a3a7ebSEric Paris static const struct fsnotify_ops audit_tree_ops = { 106428a3a7ebSEric Paris .handle_event = audit_tree_handle_event, 106528a3a7ebSEric Paris .freeing_mark = audit_tree_freeing_mark, 1066054c636eSJan Kara .free_mark = audit_tree_destroy_watch, 106774c3cbe3SAl Viro }; 106874c3cbe3SAl Viro 106974c3cbe3SAl Viro static int __init audit_tree_init(void) 107074c3cbe3SAl Viro { 107174c3cbe3SAl Viro int i; 107274c3cbe3SAl Viro 10735f516130SJan Kara audit_tree_mark_cachep = KMEM_CACHE(audit_tree_mark, SLAB_PANIC); 10745f516130SJan Kara 10750d2e2a1dSEric Paris audit_tree_group = fsnotify_alloc_group(&audit_tree_ops); 107628a3a7ebSEric Paris if (IS_ERR(audit_tree_group)) 107728a3a7ebSEric Paris audit_panic("cannot initialize fsnotify group for rectree watches"); 107874c3cbe3SAl Viro 107974c3cbe3SAl Viro for (i = 0; i < HASH_SIZE; i++) 108074c3cbe3SAl Viro INIT_LIST_HEAD(&chunk_hash_heads[i]); 108174c3cbe3SAl Viro 108274c3cbe3SAl Viro return 0; 108374c3cbe3SAl Viro } 108474c3cbe3SAl Viro __initcall(audit_tree_init); 1085