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> 65a0e3ad6STejun Heo #include <linux/slab.h> 774c3cbe3SAl Viro 874c3cbe3SAl Viro struct audit_tree; 974c3cbe3SAl Viro struct audit_chunk; 1074c3cbe3SAl Viro 1174c3cbe3SAl Viro struct audit_tree { 1274c3cbe3SAl Viro atomic_t count; 1374c3cbe3SAl Viro int goner; 1474c3cbe3SAl Viro struct audit_chunk *root; 1574c3cbe3SAl Viro struct list_head chunks; 1674c3cbe3SAl Viro struct list_head rules; 1774c3cbe3SAl Viro struct list_head list; 1874c3cbe3SAl Viro struct list_head same_root; 1974c3cbe3SAl Viro struct rcu_head head; 2074c3cbe3SAl Viro char pathname[]; 2174c3cbe3SAl Viro }; 2274c3cbe3SAl Viro 2374c3cbe3SAl Viro struct audit_chunk { 2474c3cbe3SAl Viro struct list_head hash; 25e61ce867SEric Paris struct fsnotify_mark mark; 2674c3cbe3SAl Viro struct list_head trees; /* with root here */ 2774c3cbe3SAl Viro int dead; 2874c3cbe3SAl Viro int count; 298f7b0ba1SAl Viro atomic_long_t refs; 3074c3cbe3SAl Viro struct rcu_head head; 3174c3cbe3SAl Viro struct node { 3274c3cbe3SAl Viro struct list_head list; 3374c3cbe3SAl Viro struct audit_tree *owner; 3474c3cbe3SAl Viro unsigned index; /* index; upper bit indicates 'will prune' */ 3574c3cbe3SAl Viro } owners[]; 3674c3cbe3SAl Viro }; 3774c3cbe3SAl Viro 3874c3cbe3SAl Viro static LIST_HEAD(tree_list); 3974c3cbe3SAl Viro static LIST_HEAD(prune_list); 40f1aaf262SImre Palik static struct task_struct *prune_thread; 4174c3cbe3SAl Viro 4274c3cbe3SAl Viro /* 4374c3cbe3SAl Viro * One struct chunk is attached to each inode of interest. 4474c3cbe3SAl Viro * We replace struct chunk on tagging/untagging. 4574c3cbe3SAl Viro * Rules have pointer to struct audit_tree. 4674c3cbe3SAl Viro * Rules have struct list_head rlist forming a list of rules over 4774c3cbe3SAl Viro * the same tree. 4874c3cbe3SAl Viro * References to struct chunk are collected at audit_inode{,_child}() 4974c3cbe3SAl Viro * time and used in AUDIT_TREE rule matching. 5074c3cbe3SAl Viro * These references are dropped at the same time we are calling 5174c3cbe3SAl Viro * audit_free_names(), etc. 5274c3cbe3SAl Viro * 5374c3cbe3SAl Viro * Cyclic lists galore: 5474c3cbe3SAl Viro * tree.chunks anchors chunk.owners[].list hash_lock 5574c3cbe3SAl Viro * tree.rules anchors rule.rlist audit_filter_mutex 5674c3cbe3SAl Viro * chunk.trees anchors tree.same_root hash_lock 5774c3cbe3SAl Viro * chunk.hash is a hash with middle bits of watch.inode as 5874c3cbe3SAl Viro * a hash function. RCU, hash_lock 5974c3cbe3SAl Viro * 6074c3cbe3SAl Viro * tree is refcounted; one reference for "some rules on rules_list refer to 6174c3cbe3SAl Viro * it", one for each chunk with pointer to it. 6274c3cbe3SAl Viro * 6328a3a7ebSEric Paris * chunk is refcounted by embedded fsnotify_mark + .refs (non-zero refcount 648f7b0ba1SAl Viro * of watch contributes 1 to .refs). 6574c3cbe3SAl Viro * 6674c3cbe3SAl Viro * node.index allows to get from node.list to containing chunk. 6774c3cbe3SAl Viro * MSB of that sucker is stolen to mark taggings that we might have to 6874c3cbe3SAl Viro * revert - several operations have very unpleasant cleanup logics and 6974c3cbe3SAl Viro * that makes a difference. Some. 7074c3cbe3SAl Viro */ 7174c3cbe3SAl Viro 7228a3a7ebSEric Paris static struct fsnotify_group *audit_tree_group; 7374c3cbe3SAl Viro 7474c3cbe3SAl Viro static struct audit_tree *alloc_tree(const char *s) 7574c3cbe3SAl Viro { 7674c3cbe3SAl Viro struct audit_tree *tree; 7774c3cbe3SAl Viro 7874c3cbe3SAl Viro tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL); 7974c3cbe3SAl Viro if (tree) { 8074c3cbe3SAl Viro atomic_set(&tree->count, 1); 8174c3cbe3SAl Viro tree->goner = 0; 8274c3cbe3SAl Viro INIT_LIST_HEAD(&tree->chunks); 8374c3cbe3SAl Viro INIT_LIST_HEAD(&tree->rules); 8474c3cbe3SAl Viro INIT_LIST_HEAD(&tree->list); 8574c3cbe3SAl Viro INIT_LIST_HEAD(&tree->same_root); 8674c3cbe3SAl Viro tree->root = NULL; 8774c3cbe3SAl Viro strcpy(tree->pathname, s); 8874c3cbe3SAl Viro } 8974c3cbe3SAl Viro return tree; 9074c3cbe3SAl Viro } 9174c3cbe3SAl Viro 9274c3cbe3SAl Viro static inline void get_tree(struct audit_tree *tree) 9374c3cbe3SAl Viro { 9474c3cbe3SAl Viro atomic_inc(&tree->count); 9574c3cbe3SAl Viro } 9674c3cbe3SAl Viro 9774c3cbe3SAl Viro static inline void put_tree(struct audit_tree *tree) 9874c3cbe3SAl Viro { 9974c3cbe3SAl Viro if (atomic_dec_and_test(&tree->count)) 1003b097c46SLai Jiangshan kfree_rcu(tree, head); 10174c3cbe3SAl Viro } 10274c3cbe3SAl Viro 10374c3cbe3SAl Viro /* to avoid bringing the entire thing in audit.h */ 10474c3cbe3SAl Viro const char *audit_tree_path(struct audit_tree *tree) 10574c3cbe3SAl Viro { 10674c3cbe3SAl Viro return tree->pathname; 10774c3cbe3SAl Viro } 10874c3cbe3SAl Viro 1098f7b0ba1SAl Viro static void free_chunk(struct audit_chunk *chunk) 11074c3cbe3SAl Viro { 11174c3cbe3SAl Viro int i; 11274c3cbe3SAl Viro 11374c3cbe3SAl Viro for (i = 0; i < chunk->count; i++) { 11474c3cbe3SAl Viro if (chunk->owners[i].owner) 11574c3cbe3SAl Viro put_tree(chunk->owners[i].owner); 11674c3cbe3SAl Viro } 11774c3cbe3SAl Viro kfree(chunk); 11874c3cbe3SAl Viro } 11974c3cbe3SAl Viro 12074c3cbe3SAl Viro void audit_put_chunk(struct audit_chunk *chunk) 12174c3cbe3SAl Viro { 1228f7b0ba1SAl Viro if (atomic_long_dec_and_test(&chunk->refs)) 1238f7b0ba1SAl Viro free_chunk(chunk); 1248f7b0ba1SAl Viro } 1258f7b0ba1SAl Viro 1268f7b0ba1SAl Viro static void __put_chunk(struct rcu_head *rcu) 1278f7b0ba1SAl Viro { 1288f7b0ba1SAl Viro struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head); 1298f7b0ba1SAl Viro audit_put_chunk(chunk); 13074c3cbe3SAl Viro } 13174c3cbe3SAl Viro 132e61ce867SEric Paris static void audit_tree_destroy_watch(struct fsnotify_mark *entry) 13328a3a7ebSEric Paris { 13428a3a7ebSEric Paris struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark); 13528a3a7ebSEric Paris call_rcu(&chunk->head, __put_chunk); 13628a3a7ebSEric Paris } 13728a3a7ebSEric Paris 13828a3a7ebSEric Paris static struct audit_chunk *alloc_chunk(int count) 13928a3a7ebSEric Paris { 14028a3a7ebSEric Paris struct audit_chunk *chunk; 14128a3a7ebSEric Paris size_t size; 14228a3a7ebSEric Paris int i; 14328a3a7ebSEric Paris 14428a3a7ebSEric Paris size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node); 14528a3a7ebSEric Paris chunk = kzalloc(size, GFP_KERNEL); 14628a3a7ebSEric Paris if (!chunk) 14728a3a7ebSEric Paris return NULL; 14828a3a7ebSEric Paris 14928a3a7ebSEric Paris INIT_LIST_HEAD(&chunk->hash); 15028a3a7ebSEric Paris INIT_LIST_HEAD(&chunk->trees); 15128a3a7ebSEric Paris chunk->count = count; 15228a3a7ebSEric Paris atomic_long_set(&chunk->refs, 1); 15328a3a7ebSEric Paris for (i = 0; i < count; i++) { 15428a3a7ebSEric Paris INIT_LIST_HEAD(&chunk->owners[i].list); 15528a3a7ebSEric Paris chunk->owners[i].index = i; 15628a3a7ebSEric Paris } 15728a3a7ebSEric Paris fsnotify_init_mark(&chunk->mark, audit_tree_destroy_watch); 158799b6014SMiklos Szeredi chunk->mark.mask = FS_IN_IGNORED; 15928a3a7ebSEric Paris return chunk; 16028a3a7ebSEric Paris } 16128a3a7ebSEric Paris 16274c3cbe3SAl Viro enum {HASH_SIZE = 128}; 16374c3cbe3SAl Viro static struct list_head chunk_hash_heads[HASH_SIZE]; 16474c3cbe3SAl Viro static __cacheline_aligned_in_smp DEFINE_SPINLOCK(hash_lock); 16574c3cbe3SAl Viro 166f410ff65SJan Kara /* Function to return search key in our hash from inode. */ 167f410ff65SJan Kara static unsigned long inode_to_key(const struct inode *inode) 16874c3cbe3SAl Viro { 169f410ff65SJan Kara return (unsigned long)inode; 170f410ff65SJan Kara } 171f410ff65SJan Kara 172f410ff65SJan Kara /* 173f410ff65SJan Kara * Function to return search key in our hash from chunk. Key 0 is special and 174f410ff65SJan Kara * should never be present in the hash. 17586ffe245SJan Kara * 17686ffe245SJan Kara * Must be called with chunk->mark.lock held to protect from connector 17786ffe245SJan Kara * becoming NULL. 178f410ff65SJan Kara */ 17986ffe245SJan Kara static unsigned long __chunk_to_key(struct audit_chunk *chunk) 18086ffe245SJan Kara { 18186ffe245SJan Kara if (!chunk->mark.connector) 18286ffe245SJan Kara return 0; 18386ffe245SJan Kara return (unsigned long)chunk->mark.connector->inode; 18486ffe245SJan Kara } 18586ffe245SJan Kara 186f410ff65SJan Kara static unsigned long chunk_to_key(struct audit_chunk *chunk) 187f410ff65SJan Kara { 18886ffe245SJan Kara unsigned long key; 18986ffe245SJan Kara 19086ffe245SJan Kara spin_lock(&chunk->mark.lock); 19186ffe245SJan Kara key = __chunk_to_key(chunk); 19286ffe245SJan Kara spin_unlock(&chunk->mark.lock); 19386ffe245SJan Kara return key; 194f410ff65SJan Kara } 195f410ff65SJan Kara 196f410ff65SJan Kara static inline struct list_head *chunk_hash(unsigned long key) 197f410ff65SJan Kara { 198f410ff65SJan Kara unsigned long n = key / L1_CACHE_BYTES; 19974c3cbe3SAl Viro return chunk_hash_heads + n % HASH_SIZE; 20074c3cbe3SAl Viro } 20174c3cbe3SAl Viro 20228a3a7ebSEric Paris /* hash_lock & entry->lock is held by caller */ 20374c3cbe3SAl Viro static void insert_hash(struct audit_chunk *chunk) 20474c3cbe3SAl Viro { 20586ffe245SJan Kara unsigned long key = __chunk_to_key(chunk); 20628a3a7ebSEric Paris struct list_head *list; 20728a3a7ebSEric Paris 20843471d15SJan Kara if (!(chunk->mark.flags & FSNOTIFY_MARK_FLAG_ATTACHED)) 20928a3a7ebSEric Paris return; 210f410ff65SJan Kara list = chunk_hash(key); 21174c3cbe3SAl Viro list_add_rcu(&chunk->hash, list); 21274c3cbe3SAl Viro } 21374c3cbe3SAl Viro 21474c3cbe3SAl Viro /* called under rcu_read_lock */ 21574c3cbe3SAl Viro struct audit_chunk *audit_tree_lookup(const struct inode *inode) 21674c3cbe3SAl Viro { 217f410ff65SJan Kara unsigned long key = inode_to_key(inode); 218f410ff65SJan Kara struct list_head *list = chunk_hash(key); 2196793a051SPaul E. McKenney struct audit_chunk *p; 22074c3cbe3SAl Viro 2216793a051SPaul E. McKenney list_for_each_entry_rcu(p, list, hash) { 222f410ff65SJan Kara if (chunk_to_key(p) == key) { 2238f7b0ba1SAl Viro atomic_long_inc(&p->refs); 22474c3cbe3SAl Viro return p; 22574c3cbe3SAl Viro } 22674c3cbe3SAl Viro } 22774c3cbe3SAl Viro return NULL; 22874c3cbe3SAl Viro } 22974c3cbe3SAl Viro 2306f1b5d7aSYaowei Bai bool audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree) 23174c3cbe3SAl Viro { 23274c3cbe3SAl Viro int n; 23374c3cbe3SAl Viro for (n = 0; n < chunk->count; n++) 23474c3cbe3SAl Viro if (chunk->owners[n].owner == tree) 2356f1b5d7aSYaowei Bai return true; 2366f1b5d7aSYaowei Bai return false; 23774c3cbe3SAl Viro } 23874c3cbe3SAl Viro 23974c3cbe3SAl Viro /* tagging and untagging inodes with trees */ 24074c3cbe3SAl Viro 2418f7b0ba1SAl Viro static struct audit_chunk *find_chunk(struct node *p) 24274c3cbe3SAl Viro { 2438f7b0ba1SAl Viro int index = p->index & ~(1U<<31); 2448f7b0ba1SAl Viro p -= index; 2458f7b0ba1SAl Viro return container_of(p, struct audit_chunk, owners[0]); 2468f7b0ba1SAl Viro } 2478f7b0ba1SAl Viro 2488f7b0ba1SAl Viro static void untag_chunk(struct node *p) 2498f7b0ba1SAl Viro { 2508f7b0ba1SAl Viro struct audit_chunk *chunk = find_chunk(p); 251e61ce867SEric Paris struct fsnotify_mark *entry = &chunk->mark; 252f7a998a9SAl Viro struct audit_chunk *new = NULL; 25374c3cbe3SAl Viro struct audit_tree *owner; 25474c3cbe3SAl Viro int size = chunk->count - 1; 25574c3cbe3SAl Viro int i, j; 25674c3cbe3SAl Viro 25728a3a7ebSEric Paris fsnotify_get_mark(entry); 2588f7b0ba1SAl Viro 2598f7b0ba1SAl Viro spin_unlock(&hash_lock); 2608f7b0ba1SAl Viro 261f7a998a9SAl Viro if (size) 262f7a998a9SAl Viro new = alloc_chunk(size); 263f7a998a9SAl Viro 264be29d20fSJan Kara mutex_lock(&entry->group->mark_mutex); 26528a3a7ebSEric Paris spin_lock(&entry->lock); 26643471d15SJan Kara if (chunk->dead || !(entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { 26728a3a7ebSEric Paris spin_unlock(&entry->lock); 268be29d20fSJan Kara mutex_unlock(&entry->group->mark_mutex); 269f7a998a9SAl Viro if (new) 270f7a998a9SAl Viro free_chunk(new); 2718f7b0ba1SAl Viro goto out; 27274c3cbe3SAl Viro } 27374c3cbe3SAl Viro 27474c3cbe3SAl Viro owner = p->owner; 27574c3cbe3SAl Viro 27674c3cbe3SAl Viro if (!size) { 27774c3cbe3SAl Viro chunk->dead = 1; 27874c3cbe3SAl Viro spin_lock(&hash_lock); 27974c3cbe3SAl Viro list_del_init(&chunk->trees); 28074c3cbe3SAl Viro if (owner->root == chunk) 28174c3cbe3SAl Viro owner->root = NULL; 28274c3cbe3SAl Viro list_del_init(&p->list); 28374c3cbe3SAl Viro list_del_rcu(&chunk->hash); 28474c3cbe3SAl Viro spin_unlock(&hash_lock); 28528a3a7ebSEric Paris spin_unlock(&entry->lock); 286be29d20fSJan Kara mutex_unlock(&entry->group->mark_mutex); 287e2a29943SLino Sanfilippo fsnotify_destroy_mark(entry, audit_tree_group); 2888f7b0ba1SAl Viro goto out; 28974c3cbe3SAl Viro } 29074c3cbe3SAl Viro 29174c3cbe3SAl Viro if (!new) 29274c3cbe3SAl Viro goto Fallback; 293f7a998a9SAl Viro 29486ffe245SJan Kara if (fsnotify_add_mark_locked(&new->mark, entry->group, 29586ffe245SJan Kara entry->connector->inode, NULL, 1)) { 2960fe33aaeSMiklos Szeredi fsnotify_put_mark(&new->mark); 29774c3cbe3SAl Viro goto Fallback; 29874c3cbe3SAl Viro } 29974c3cbe3SAl Viro 30074c3cbe3SAl Viro chunk->dead = 1; 30174c3cbe3SAl Viro spin_lock(&hash_lock); 30274c3cbe3SAl Viro list_replace_init(&chunk->trees, &new->trees); 30374c3cbe3SAl Viro if (owner->root == chunk) { 30474c3cbe3SAl Viro list_del_init(&owner->same_root); 30574c3cbe3SAl Viro owner->root = NULL; 30674c3cbe3SAl Viro } 30774c3cbe3SAl Viro 3086f5d5114SAl Viro for (i = j = 0; j <= size; i++, j++) { 30974c3cbe3SAl Viro struct audit_tree *s; 31074c3cbe3SAl Viro if (&chunk->owners[j] == p) { 31174c3cbe3SAl Viro list_del_init(&p->list); 31274c3cbe3SAl Viro i--; 31374c3cbe3SAl Viro continue; 31474c3cbe3SAl Viro } 31574c3cbe3SAl Viro s = chunk->owners[j].owner; 31674c3cbe3SAl Viro new->owners[i].owner = s; 31774c3cbe3SAl Viro new->owners[i].index = chunk->owners[j].index - j + i; 31874c3cbe3SAl Viro if (!s) /* result of earlier fallback */ 31974c3cbe3SAl Viro continue; 32074c3cbe3SAl Viro get_tree(s); 3216f5d5114SAl Viro list_replace_init(&chunk->owners[j].list, &new->owners[i].list); 32274c3cbe3SAl Viro } 32374c3cbe3SAl Viro 32474c3cbe3SAl Viro list_replace_rcu(&chunk->hash, &new->hash); 32574c3cbe3SAl Viro list_for_each_entry(owner, &new->trees, same_root) 32674c3cbe3SAl Viro owner->root = new; 32774c3cbe3SAl Viro spin_unlock(&hash_lock); 32828a3a7ebSEric Paris spin_unlock(&entry->lock); 329be29d20fSJan Kara mutex_unlock(&entry->group->mark_mutex); 330e2a29943SLino Sanfilippo fsnotify_destroy_mark(entry, audit_tree_group); 331b3e8692bSMiklos Szeredi fsnotify_put_mark(&new->mark); /* drop initial reference */ 3328f7b0ba1SAl Viro goto out; 33374c3cbe3SAl Viro 33474c3cbe3SAl Viro Fallback: 33574c3cbe3SAl Viro // do the best we can 33674c3cbe3SAl Viro spin_lock(&hash_lock); 33774c3cbe3SAl Viro if (owner->root == chunk) { 33874c3cbe3SAl Viro list_del_init(&owner->same_root); 33974c3cbe3SAl Viro owner->root = NULL; 34074c3cbe3SAl Viro } 34174c3cbe3SAl Viro list_del_init(&p->list); 34274c3cbe3SAl Viro p->owner = NULL; 34374c3cbe3SAl Viro put_tree(owner); 34474c3cbe3SAl Viro spin_unlock(&hash_lock); 34528a3a7ebSEric Paris spin_unlock(&entry->lock); 346be29d20fSJan Kara mutex_unlock(&entry->group->mark_mutex); 3478f7b0ba1SAl Viro out: 34828a3a7ebSEric Paris fsnotify_put_mark(entry); 3498f7b0ba1SAl Viro spin_lock(&hash_lock); 35074c3cbe3SAl Viro } 35174c3cbe3SAl Viro 35274c3cbe3SAl Viro static int create_chunk(struct inode *inode, struct audit_tree *tree) 35374c3cbe3SAl Viro { 354e61ce867SEric Paris struct fsnotify_mark *entry; 35574c3cbe3SAl Viro struct audit_chunk *chunk = alloc_chunk(1); 35674c3cbe3SAl Viro if (!chunk) 35774c3cbe3SAl Viro return -ENOMEM; 35874c3cbe3SAl Viro 35928a3a7ebSEric Paris entry = &chunk->mark; 3605444e298SEric Paris if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) { 3610fe33aaeSMiklos Szeredi fsnotify_put_mark(entry); 36274c3cbe3SAl Viro return -ENOSPC; 36374c3cbe3SAl Viro } 36474c3cbe3SAl Viro 36528a3a7ebSEric Paris spin_lock(&entry->lock); 36674c3cbe3SAl Viro spin_lock(&hash_lock); 36774c3cbe3SAl Viro if (tree->goner) { 36874c3cbe3SAl Viro spin_unlock(&hash_lock); 36974c3cbe3SAl Viro chunk->dead = 1; 37028a3a7ebSEric Paris spin_unlock(&entry->lock); 371e2a29943SLino Sanfilippo fsnotify_destroy_mark(entry, audit_tree_group); 37228a3a7ebSEric Paris fsnotify_put_mark(entry); 37374c3cbe3SAl Viro return 0; 37474c3cbe3SAl Viro } 37574c3cbe3SAl Viro chunk->owners[0].index = (1U << 31); 37674c3cbe3SAl Viro chunk->owners[0].owner = tree; 37774c3cbe3SAl Viro get_tree(tree); 37874c3cbe3SAl Viro list_add(&chunk->owners[0].list, &tree->chunks); 37974c3cbe3SAl Viro if (!tree->root) { 38074c3cbe3SAl Viro tree->root = chunk; 38174c3cbe3SAl Viro list_add(&tree->same_root, &chunk->trees); 38274c3cbe3SAl Viro } 38374c3cbe3SAl Viro insert_hash(chunk); 38474c3cbe3SAl Viro spin_unlock(&hash_lock); 38528a3a7ebSEric Paris spin_unlock(&entry->lock); 386b3e8692bSMiklos Szeredi fsnotify_put_mark(entry); /* drop initial reference */ 38774c3cbe3SAl Viro return 0; 38874c3cbe3SAl Viro } 38974c3cbe3SAl Viro 39074c3cbe3SAl Viro /* the first tagged inode becomes root of tree */ 39174c3cbe3SAl Viro static int tag_chunk(struct inode *inode, struct audit_tree *tree) 39274c3cbe3SAl Viro { 393e61ce867SEric Paris struct fsnotify_mark *old_entry, *chunk_entry; 39474c3cbe3SAl Viro struct audit_tree *owner; 39574c3cbe3SAl Viro struct audit_chunk *chunk, *old; 39674c3cbe3SAl Viro struct node *p; 39774c3cbe3SAl Viro int n; 39874c3cbe3SAl Viro 3995444e298SEric Paris old_entry = fsnotify_find_inode_mark(audit_tree_group, inode); 40028a3a7ebSEric Paris if (!old_entry) 40174c3cbe3SAl Viro return create_chunk(inode, tree); 40274c3cbe3SAl Viro 40328a3a7ebSEric Paris old = container_of(old_entry, struct audit_chunk, mark); 40474c3cbe3SAl Viro 40574c3cbe3SAl Viro /* are we already there? */ 40674c3cbe3SAl Viro spin_lock(&hash_lock); 40774c3cbe3SAl Viro for (n = 0; n < old->count; n++) { 40874c3cbe3SAl Viro if (old->owners[n].owner == tree) { 40974c3cbe3SAl Viro spin_unlock(&hash_lock); 41028a3a7ebSEric Paris fsnotify_put_mark(old_entry); 41174c3cbe3SAl Viro return 0; 41274c3cbe3SAl Viro } 41374c3cbe3SAl Viro } 41474c3cbe3SAl Viro spin_unlock(&hash_lock); 41574c3cbe3SAl Viro 41674c3cbe3SAl Viro chunk = alloc_chunk(old->count + 1); 417b4c30aadSAl Viro if (!chunk) { 41828a3a7ebSEric Paris fsnotify_put_mark(old_entry); 41974c3cbe3SAl Viro return -ENOMEM; 420b4c30aadSAl Viro } 42174c3cbe3SAl Viro 42228a3a7ebSEric Paris chunk_entry = &chunk->mark; 42328a3a7ebSEric Paris 424be29d20fSJan Kara mutex_lock(&old_entry->group->mark_mutex); 42528a3a7ebSEric Paris spin_lock(&old_entry->lock); 42643471d15SJan Kara if (!(old_entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { 42728a3a7ebSEric Paris /* old_entry is being shot, lets just lie */ 42828a3a7ebSEric Paris spin_unlock(&old_entry->lock); 429be29d20fSJan Kara mutex_unlock(&old_entry->group->mark_mutex); 43028a3a7ebSEric Paris fsnotify_put_mark(old_entry); 43174c3cbe3SAl Viro free_chunk(chunk); 43228a3a7ebSEric Paris return -ENOENT; 43328a3a7ebSEric Paris } 43428a3a7ebSEric Paris 435be29d20fSJan Kara if (fsnotify_add_mark_locked(chunk_entry, old_entry->group, 43686ffe245SJan Kara old_entry->connector->inode, NULL, 1)) { 43728a3a7ebSEric Paris spin_unlock(&old_entry->lock); 438be29d20fSJan Kara mutex_unlock(&old_entry->group->mark_mutex); 4390fe33aaeSMiklos Szeredi fsnotify_put_mark(chunk_entry); 44028a3a7ebSEric Paris fsnotify_put_mark(old_entry); 44174c3cbe3SAl Viro return -ENOSPC; 44274c3cbe3SAl Viro } 44328a3a7ebSEric Paris 44428a3a7ebSEric Paris /* even though we hold old_entry->lock, this is safe since chunk_entry->lock could NEVER have been grabbed before */ 44528a3a7ebSEric Paris spin_lock(&chunk_entry->lock); 44674c3cbe3SAl Viro spin_lock(&hash_lock); 44728a3a7ebSEric Paris 44828a3a7ebSEric Paris /* we now hold old_entry->lock, chunk_entry->lock, and hash_lock */ 44974c3cbe3SAl Viro if (tree->goner) { 45074c3cbe3SAl Viro spin_unlock(&hash_lock); 45174c3cbe3SAl Viro chunk->dead = 1; 45228a3a7ebSEric Paris spin_unlock(&chunk_entry->lock); 45328a3a7ebSEric Paris spin_unlock(&old_entry->lock); 454be29d20fSJan Kara mutex_unlock(&old_entry->group->mark_mutex); 45528a3a7ebSEric Paris 456e2a29943SLino Sanfilippo fsnotify_destroy_mark(chunk_entry, audit_tree_group); 45728a3a7ebSEric Paris 45828a3a7ebSEric Paris fsnotify_put_mark(chunk_entry); 45928a3a7ebSEric Paris fsnotify_put_mark(old_entry); 46074c3cbe3SAl Viro return 0; 46174c3cbe3SAl Viro } 46274c3cbe3SAl Viro list_replace_init(&old->trees, &chunk->trees); 46374c3cbe3SAl Viro for (n = 0, p = chunk->owners; n < old->count; n++, p++) { 46474c3cbe3SAl Viro struct audit_tree *s = old->owners[n].owner; 46574c3cbe3SAl Viro p->owner = s; 46674c3cbe3SAl Viro p->index = old->owners[n].index; 46774c3cbe3SAl Viro if (!s) /* result of fallback in untag */ 46874c3cbe3SAl Viro continue; 46974c3cbe3SAl Viro get_tree(s); 47074c3cbe3SAl Viro list_replace_init(&old->owners[n].list, &p->list); 47174c3cbe3SAl Viro } 47274c3cbe3SAl Viro p->index = (chunk->count - 1) | (1U<<31); 47374c3cbe3SAl Viro p->owner = tree; 47474c3cbe3SAl Viro get_tree(tree); 47574c3cbe3SAl Viro list_add(&p->list, &tree->chunks); 47674c3cbe3SAl Viro list_replace_rcu(&old->hash, &chunk->hash); 47774c3cbe3SAl Viro list_for_each_entry(owner, &chunk->trees, same_root) 47874c3cbe3SAl Viro owner->root = chunk; 47974c3cbe3SAl Viro old->dead = 1; 48074c3cbe3SAl Viro if (!tree->root) { 48174c3cbe3SAl Viro tree->root = chunk; 48274c3cbe3SAl Viro list_add(&tree->same_root, &chunk->trees); 48374c3cbe3SAl Viro } 48474c3cbe3SAl Viro spin_unlock(&hash_lock); 48528a3a7ebSEric Paris spin_unlock(&chunk_entry->lock); 48628a3a7ebSEric Paris spin_unlock(&old_entry->lock); 487be29d20fSJan Kara mutex_unlock(&old_entry->group->mark_mutex); 488e2a29943SLino Sanfilippo fsnotify_destroy_mark(old_entry, audit_tree_group); 489b3e8692bSMiklos Szeredi fsnotify_put_mark(chunk_entry); /* drop initial reference */ 49028a3a7ebSEric Paris fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ 49174c3cbe3SAl Viro return 0; 49274c3cbe3SAl Viro } 49374c3cbe3SAl Viro 4942991dd2bSRichard Guy Briggs static void audit_tree_log_remove_rule(struct audit_krule *rule) 49574c3cbe3SAl Viro { 49674c3cbe3SAl Viro struct audit_buffer *ab; 49774c3cbe3SAl Viro 49874c3cbe3SAl Viro ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); 4990644ec0cSKees Cook if (unlikely(!ab)) 5000644ec0cSKees Cook return; 501c1e8f06dSSteve Grubb audit_log_format(ab, "op=remove_rule"); 5029d960985SEric Paris audit_log_format(ab, " dir="); 50374c3cbe3SAl Viro audit_log_untrustedstring(ab, rule->tree->pathname); 5049d960985SEric Paris audit_log_key(ab, rule->filterkey); 50574c3cbe3SAl Viro audit_log_format(ab, " list=%d res=1", rule->listnr); 50674c3cbe3SAl Viro audit_log_end(ab); 5070644ec0cSKees Cook } 5080644ec0cSKees Cook 5090644ec0cSKees Cook static void kill_rules(struct audit_tree *tree) 5100644ec0cSKees Cook { 5110644ec0cSKees Cook struct audit_krule *rule, *next; 5120644ec0cSKees Cook struct audit_entry *entry; 5130644ec0cSKees Cook 5140644ec0cSKees Cook list_for_each_entry_safe(rule, next, &tree->rules, rlist) { 5150644ec0cSKees Cook entry = container_of(rule, struct audit_entry, rule); 5160644ec0cSKees Cook 5170644ec0cSKees Cook list_del_init(&rule->rlist); 5180644ec0cSKees Cook if (rule->tree) { 5190644ec0cSKees Cook /* not a half-baked one */ 5202991dd2bSRichard Guy Briggs audit_tree_log_remove_rule(rule); 52134d99af5SRichard Guy Briggs if (entry->rule.exe) 52234d99af5SRichard Guy Briggs audit_remove_mark(entry->rule.exe); 52374c3cbe3SAl Viro rule->tree = NULL; 52474c3cbe3SAl Viro list_del_rcu(&entry->list); 525e45aa212SAl Viro list_del(&entry->rule.list); 52674c3cbe3SAl Viro call_rcu(&entry->rcu, audit_free_rule_rcu); 52774c3cbe3SAl Viro } 52874c3cbe3SAl Viro } 52974c3cbe3SAl Viro } 53074c3cbe3SAl Viro 53174c3cbe3SAl Viro /* 53274c3cbe3SAl Viro * finish killing struct audit_tree 53374c3cbe3SAl Viro */ 53474c3cbe3SAl Viro static void prune_one(struct audit_tree *victim) 53574c3cbe3SAl Viro { 53674c3cbe3SAl Viro spin_lock(&hash_lock); 53774c3cbe3SAl Viro while (!list_empty(&victim->chunks)) { 53874c3cbe3SAl Viro struct node *p; 53974c3cbe3SAl Viro 54074c3cbe3SAl Viro p = list_entry(victim->chunks.next, struct node, list); 54174c3cbe3SAl Viro 5428f7b0ba1SAl Viro untag_chunk(p); 54374c3cbe3SAl Viro } 54474c3cbe3SAl Viro spin_unlock(&hash_lock); 54574c3cbe3SAl Viro put_tree(victim); 54674c3cbe3SAl Viro } 54774c3cbe3SAl Viro 54874c3cbe3SAl Viro /* trim the uncommitted chunks from tree */ 54974c3cbe3SAl Viro 55074c3cbe3SAl Viro static void trim_marked(struct audit_tree *tree) 55174c3cbe3SAl Viro { 55274c3cbe3SAl Viro struct list_head *p, *q; 55374c3cbe3SAl Viro spin_lock(&hash_lock); 55474c3cbe3SAl Viro if (tree->goner) { 55574c3cbe3SAl Viro spin_unlock(&hash_lock); 55674c3cbe3SAl Viro return; 55774c3cbe3SAl Viro } 55874c3cbe3SAl Viro /* reorder */ 55974c3cbe3SAl Viro for (p = tree->chunks.next; p != &tree->chunks; p = q) { 56074c3cbe3SAl Viro struct node *node = list_entry(p, struct node, list); 56174c3cbe3SAl Viro q = p->next; 56274c3cbe3SAl Viro if (node->index & (1U<<31)) { 56374c3cbe3SAl Viro list_del_init(p); 56474c3cbe3SAl Viro list_add(p, &tree->chunks); 56574c3cbe3SAl Viro } 56674c3cbe3SAl Viro } 56774c3cbe3SAl Viro 56874c3cbe3SAl Viro while (!list_empty(&tree->chunks)) { 56974c3cbe3SAl Viro struct node *node; 57074c3cbe3SAl Viro 57174c3cbe3SAl Viro node = list_entry(tree->chunks.next, struct node, list); 57274c3cbe3SAl Viro 57374c3cbe3SAl Viro /* have we run out of marked? */ 57474c3cbe3SAl Viro if (!(node->index & (1U<<31))) 57574c3cbe3SAl Viro break; 57674c3cbe3SAl Viro 5778f7b0ba1SAl Viro untag_chunk(node); 57874c3cbe3SAl Viro } 57974c3cbe3SAl Viro if (!tree->root && !tree->goner) { 58074c3cbe3SAl Viro tree->goner = 1; 58174c3cbe3SAl Viro spin_unlock(&hash_lock); 58274c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 58374c3cbe3SAl Viro kill_rules(tree); 58474c3cbe3SAl Viro list_del_init(&tree->list); 58574c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 58674c3cbe3SAl Viro prune_one(tree); 58774c3cbe3SAl Viro } else { 58874c3cbe3SAl Viro spin_unlock(&hash_lock); 58974c3cbe3SAl Viro } 59074c3cbe3SAl Viro } 59174c3cbe3SAl Viro 592916d7576SAl Viro static void audit_schedule_prune(void); 593916d7576SAl Viro 59474c3cbe3SAl Viro /* called with audit_filter_mutex */ 59574c3cbe3SAl Viro int audit_remove_tree_rule(struct audit_krule *rule) 59674c3cbe3SAl Viro { 59774c3cbe3SAl Viro struct audit_tree *tree; 59874c3cbe3SAl Viro tree = rule->tree; 59974c3cbe3SAl Viro if (tree) { 60074c3cbe3SAl Viro spin_lock(&hash_lock); 60174c3cbe3SAl Viro list_del_init(&rule->rlist); 60274c3cbe3SAl Viro if (list_empty(&tree->rules) && !tree->goner) { 60374c3cbe3SAl Viro tree->root = NULL; 60474c3cbe3SAl Viro list_del_init(&tree->same_root); 60574c3cbe3SAl Viro tree->goner = 1; 60674c3cbe3SAl Viro list_move(&tree->list, &prune_list); 60774c3cbe3SAl Viro rule->tree = NULL; 60874c3cbe3SAl Viro spin_unlock(&hash_lock); 60974c3cbe3SAl Viro audit_schedule_prune(); 61074c3cbe3SAl Viro return 1; 61174c3cbe3SAl Viro } 61274c3cbe3SAl Viro rule->tree = NULL; 61374c3cbe3SAl Viro spin_unlock(&hash_lock); 61474c3cbe3SAl Viro return 1; 61574c3cbe3SAl Viro } 61674c3cbe3SAl Viro return 0; 61774c3cbe3SAl Viro } 61874c3cbe3SAl Viro 6191f707137SAl Viro static int compare_root(struct vfsmount *mnt, void *arg) 6201f707137SAl Viro { 621f410ff65SJan Kara return inode_to_key(d_backing_inode(mnt->mnt_root)) == 622f410ff65SJan Kara (unsigned long)arg; 6231f707137SAl Viro } 6241f707137SAl Viro 62574c3cbe3SAl Viro void audit_trim_trees(void) 62674c3cbe3SAl Viro { 62774c3cbe3SAl Viro struct list_head cursor; 62874c3cbe3SAl Viro 62974c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 63074c3cbe3SAl Viro list_add(&cursor, &tree_list); 63174c3cbe3SAl Viro while (cursor.next != &tree_list) { 63274c3cbe3SAl Viro struct audit_tree *tree; 63398bc993fSAl Viro struct path path; 63474c3cbe3SAl Viro struct vfsmount *root_mnt; 63574c3cbe3SAl Viro struct node *node; 63674c3cbe3SAl Viro int err; 63774c3cbe3SAl Viro 63874c3cbe3SAl Viro tree = container_of(cursor.next, struct audit_tree, list); 63974c3cbe3SAl Viro get_tree(tree); 64074c3cbe3SAl Viro list_del(&cursor); 64174c3cbe3SAl Viro list_add(&cursor, &tree->list); 64274c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 64374c3cbe3SAl Viro 64498bc993fSAl Viro err = kern_path(tree->pathname, 0, &path); 64574c3cbe3SAl Viro if (err) 64674c3cbe3SAl Viro goto skip_it; 64774c3cbe3SAl Viro 648589ff870SAl Viro root_mnt = collect_mounts(&path); 64998bc993fSAl Viro path_put(&path); 650be34d1a3SDavid Howells if (IS_ERR(root_mnt)) 65174c3cbe3SAl Viro goto skip_it; 65274c3cbe3SAl Viro 65374c3cbe3SAl Viro spin_lock(&hash_lock); 65474c3cbe3SAl Viro list_for_each_entry(node, &tree->chunks, list) { 65528a3a7ebSEric Paris struct audit_chunk *chunk = find_chunk(node); 65625985edcSLucas De Marchi /* this could be NULL if the watch is dying else where... */ 65774c3cbe3SAl Viro node->index |= 1U<<31; 658f410ff65SJan Kara if (iterate_mounts(compare_root, 659f410ff65SJan Kara (void *)chunk_to_key(chunk), 660f410ff65SJan Kara root_mnt)) 66174c3cbe3SAl Viro node->index &= ~(1U<<31); 66274c3cbe3SAl Viro } 66374c3cbe3SAl Viro spin_unlock(&hash_lock); 66474c3cbe3SAl Viro trim_marked(tree); 66574c3cbe3SAl Viro drop_collected_mounts(root_mnt); 66674c3cbe3SAl Viro skip_it: 66712b2f117SChen Gang put_tree(tree); 66874c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 66974c3cbe3SAl Viro } 67074c3cbe3SAl Viro list_del(&cursor); 67174c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 67274c3cbe3SAl Viro } 67374c3cbe3SAl Viro 67474c3cbe3SAl Viro int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) 67574c3cbe3SAl Viro { 67674c3cbe3SAl Viro 67774c3cbe3SAl Viro if (pathname[0] != '/' || 67874c3cbe3SAl Viro rule->listnr != AUDIT_FILTER_EXIT || 6795af75d8dSAl Viro op != Audit_equal || 68074c3cbe3SAl Viro rule->inode_f || rule->watch || rule->tree) 68174c3cbe3SAl Viro return -EINVAL; 68274c3cbe3SAl Viro rule->tree = alloc_tree(pathname); 68374c3cbe3SAl Viro if (!rule->tree) 68474c3cbe3SAl Viro return -ENOMEM; 68574c3cbe3SAl Viro return 0; 68674c3cbe3SAl Viro } 68774c3cbe3SAl Viro 68874c3cbe3SAl Viro void audit_put_tree(struct audit_tree *tree) 68974c3cbe3SAl Viro { 69074c3cbe3SAl Viro put_tree(tree); 69174c3cbe3SAl Viro } 69274c3cbe3SAl Viro 6931f707137SAl Viro static int tag_mount(struct vfsmount *mnt, void *arg) 6941f707137SAl Viro { 6953b362157SDavid Howells return tag_chunk(d_backing_inode(mnt->mnt_root), arg); 6961f707137SAl Viro } 6971f707137SAl Viro 698f1aaf262SImre Palik /* 699f1aaf262SImre Palik * That gets run when evict_chunk() ends up needing to kill audit_tree. 700f1aaf262SImre Palik * Runs from a separate thread. 701f1aaf262SImre Palik */ 702f1aaf262SImre Palik static int prune_tree_thread(void *unused) 703f1aaf262SImre Palik { 704f1aaf262SImre Palik for (;;) { 7050bf676d1SJiri Slaby if (list_empty(&prune_list)) { 706f1aaf262SImre Palik set_current_state(TASK_INTERRUPTIBLE); 707f1aaf262SImre Palik schedule(); 7080bf676d1SJiri Slaby } 709f1aaf262SImre Palik 710f1aaf262SImre Palik mutex_lock(&audit_cmd_mutex); 711f1aaf262SImre Palik mutex_lock(&audit_filter_mutex); 712f1aaf262SImre Palik 713f1aaf262SImre Palik while (!list_empty(&prune_list)) { 714f1aaf262SImre Palik struct audit_tree *victim; 715f1aaf262SImre Palik 716f1aaf262SImre Palik victim = list_entry(prune_list.next, 717f1aaf262SImre Palik struct audit_tree, list); 718f1aaf262SImre Palik list_del_init(&victim->list); 719f1aaf262SImre Palik 720f1aaf262SImre Palik mutex_unlock(&audit_filter_mutex); 721f1aaf262SImre Palik 722f1aaf262SImre Palik prune_one(victim); 723f1aaf262SImre Palik 724f1aaf262SImre Palik mutex_lock(&audit_filter_mutex); 725f1aaf262SImre Palik } 726f1aaf262SImre Palik 727f1aaf262SImre Palik mutex_unlock(&audit_filter_mutex); 728f1aaf262SImre Palik mutex_unlock(&audit_cmd_mutex); 729f1aaf262SImre Palik } 730f1aaf262SImre Palik return 0; 731f1aaf262SImre Palik } 732f1aaf262SImre Palik 733f1aaf262SImre Palik static int audit_launch_prune(void) 734f1aaf262SImre Palik { 735f1aaf262SImre Palik if (prune_thread) 736f1aaf262SImre Palik return 0; 7370bf676d1SJiri Slaby prune_thread = kthread_run(prune_tree_thread, NULL, 738f1aaf262SImre Palik "audit_prune_tree"); 739f1aaf262SImre Palik if (IS_ERR(prune_thread)) { 740f1aaf262SImre Palik pr_err("cannot start thread audit_prune_tree"); 741f1aaf262SImre Palik prune_thread = NULL; 742f1aaf262SImre Palik return -ENOMEM; 743f1aaf262SImre Palik } 7440bf676d1SJiri Slaby return 0; 745f1aaf262SImre Palik } 746f1aaf262SImre Palik 74774c3cbe3SAl Viro /* called with audit_filter_mutex */ 74874c3cbe3SAl Viro int audit_add_tree_rule(struct audit_krule *rule) 74974c3cbe3SAl Viro { 75074c3cbe3SAl Viro struct audit_tree *seed = rule->tree, *tree; 75198bc993fSAl Viro struct path path; 7521f707137SAl Viro struct vfsmount *mnt; 75374c3cbe3SAl Viro int err; 75474c3cbe3SAl Viro 755736f3203SChen Gang rule->tree = NULL; 75674c3cbe3SAl Viro list_for_each_entry(tree, &tree_list, list) { 75774c3cbe3SAl Viro if (!strcmp(seed->pathname, tree->pathname)) { 75874c3cbe3SAl Viro put_tree(seed); 75974c3cbe3SAl Viro rule->tree = tree; 76074c3cbe3SAl Viro list_add(&rule->rlist, &tree->rules); 76174c3cbe3SAl Viro return 0; 76274c3cbe3SAl Viro } 76374c3cbe3SAl Viro } 76474c3cbe3SAl Viro tree = seed; 76574c3cbe3SAl Viro list_add(&tree->list, &tree_list); 76674c3cbe3SAl Viro list_add(&rule->rlist, &tree->rules); 76774c3cbe3SAl Viro /* do not set rule->tree yet */ 76874c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 76974c3cbe3SAl Viro 770f1aaf262SImre Palik if (unlikely(!prune_thread)) { 771f1aaf262SImre Palik err = audit_launch_prune(); 772f1aaf262SImre Palik if (err) 773f1aaf262SImre Palik goto Err; 774f1aaf262SImre Palik } 775f1aaf262SImre Palik 77698bc993fSAl Viro err = kern_path(tree->pathname, 0, &path); 77774c3cbe3SAl Viro if (err) 77874c3cbe3SAl Viro goto Err; 779589ff870SAl Viro mnt = collect_mounts(&path); 78098bc993fSAl Viro path_put(&path); 781be34d1a3SDavid Howells if (IS_ERR(mnt)) { 782be34d1a3SDavid Howells err = PTR_ERR(mnt); 78374c3cbe3SAl Viro goto Err; 78474c3cbe3SAl Viro } 78574c3cbe3SAl Viro 78674c3cbe3SAl Viro get_tree(tree); 7871f707137SAl Viro err = iterate_mounts(tag_mount, tree, mnt); 78874c3cbe3SAl Viro drop_collected_mounts(mnt); 78974c3cbe3SAl Viro 79074c3cbe3SAl Viro if (!err) { 79174c3cbe3SAl Viro struct node *node; 79274c3cbe3SAl Viro spin_lock(&hash_lock); 79374c3cbe3SAl Viro list_for_each_entry(node, &tree->chunks, list) 79474c3cbe3SAl Viro node->index &= ~(1U<<31); 79574c3cbe3SAl Viro spin_unlock(&hash_lock); 79674c3cbe3SAl Viro } else { 79774c3cbe3SAl Viro trim_marked(tree); 79874c3cbe3SAl Viro goto Err; 79974c3cbe3SAl Viro } 80074c3cbe3SAl Viro 80174c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 80274c3cbe3SAl Viro if (list_empty(&rule->rlist)) { 80374c3cbe3SAl Viro put_tree(tree); 80474c3cbe3SAl Viro return -ENOENT; 80574c3cbe3SAl Viro } 80674c3cbe3SAl Viro rule->tree = tree; 80774c3cbe3SAl Viro put_tree(tree); 80874c3cbe3SAl Viro 80974c3cbe3SAl Viro return 0; 81074c3cbe3SAl Viro Err: 81174c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 81274c3cbe3SAl Viro list_del_init(&tree->list); 81374c3cbe3SAl Viro list_del_init(&tree->rules); 81474c3cbe3SAl Viro put_tree(tree); 81574c3cbe3SAl Viro return err; 81674c3cbe3SAl Viro } 81774c3cbe3SAl Viro 81874c3cbe3SAl Viro int audit_tag_tree(char *old, char *new) 81974c3cbe3SAl Viro { 82074c3cbe3SAl Viro struct list_head cursor, barrier; 82174c3cbe3SAl Viro int failed = 0; 8222096f759SAl Viro struct path path1, path2; 82374c3cbe3SAl Viro struct vfsmount *tagged; 82474c3cbe3SAl Viro int err; 82574c3cbe3SAl Viro 8262096f759SAl Viro err = kern_path(new, 0, &path2); 82774c3cbe3SAl Viro if (err) 82874c3cbe3SAl Viro return err; 8292096f759SAl Viro tagged = collect_mounts(&path2); 8302096f759SAl Viro path_put(&path2); 831be34d1a3SDavid Howells if (IS_ERR(tagged)) 832be34d1a3SDavid Howells return PTR_ERR(tagged); 83374c3cbe3SAl Viro 8342096f759SAl Viro err = kern_path(old, 0, &path1); 83574c3cbe3SAl Viro if (err) { 83674c3cbe3SAl Viro drop_collected_mounts(tagged); 83774c3cbe3SAl Viro return err; 83874c3cbe3SAl Viro } 83974c3cbe3SAl Viro 84074c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 84174c3cbe3SAl Viro list_add(&barrier, &tree_list); 84274c3cbe3SAl Viro list_add(&cursor, &barrier); 84374c3cbe3SAl Viro 84474c3cbe3SAl Viro while (cursor.next != &tree_list) { 84574c3cbe3SAl Viro struct audit_tree *tree; 8462096f759SAl Viro int good_one = 0; 84774c3cbe3SAl Viro 84874c3cbe3SAl Viro tree = container_of(cursor.next, struct audit_tree, list); 84974c3cbe3SAl Viro get_tree(tree); 85074c3cbe3SAl Viro list_del(&cursor); 85174c3cbe3SAl Viro list_add(&cursor, &tree->list); 85274c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 85374c3cbe3SAl Viro 8542096f759SAl Viro err = kern_path(tree->pathname, 0, &path2); 8552096f759SAl Viro if (!err) { 8562096f759SAl Viro good_one = path_is_under(&path1, &path2); 8572096f759SAl Viro path_put(&path2); 85874c3cbe3SAl Viro } 85974c3cbe3SAl Viro 8602096f759SAl Viro if (!good_one) { 86174c3cbe3SAl Viro put_tree(tree); 86274c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 86374c3cbe3SAl Viro continue; 86474c3cbe3SAl Viro } 86574c3cbe3SAl Viro 8661f707137SAl Viro failed = iterate_mounts(tag_mount, tree, tagged); 86774c3cbe3SAl Viro if (failed) { 86874c3cbe3SAl Viro put_tree(tree); 86974c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 87074c3cbe3SAl Viro break; 87174c3cbe3SAl Viro } 87274c3cbe3SAl Viro 87374c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 87474c3cbe3SAl Viro spin_lock(&hash_lock); 87574c3cbe3SAl Viro if (!tree->goner) { 87674c3cbe3SAl Viro list_del(&tree->list); 87774c3cbe3SAl Viro list_add(&tree->list, &tree_list); 87874c3cbe3SAl Viro } 87974c3cbe3SAl Viro spin_unlock(&hash_lock); 88074c3cbe3SAl Viro put_tree(tree); 88174c3cbe3SAl Viro } 88274c3cbe3SAl Viro 88374c3cbe3SAl Viro while (barrier.prev != &tree_list) { 88474c3cbe3SAl Viro struct audit_tree *tree; 88574c3cbe3SAl Viro 88674c3cbe3SAl Viro tree = container_of(barrier.prev, struct audit_tree, list); 88774c3cbe3SAl Viro get_tree(tree); 88874c3cbe3SAl Viro list_del(&tree->list); 88974c3cbe3SAl Viro list_add(&tree->list, &barrier); 89074c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 89174c3cbe3SAl Viro 89274c3cbe3SAl Viro if (!failed) { 89374c3cbe3SAl Viro struct node *node; 89474c3cbe3SAl Viro spin_lock(&hash_lock); 89574c3cbe3SAl Viro list_for_each_entry(node, &tree->chunks, list) 89674c3cbe3SAl Viro node->index &= ~(1U<<31); 89774c3cbe3SAl Viro spin_unlock(&hash_lock); 89874c3cbe3SAl Viro } else { 89974c3cbe3SAl Viro trim_marked(tree); 90074c3cbe3SAl Viro } 90174c3cbe3SAl Viro 90274c3cbe3SAl Viro put_tree(tree); 90374c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 90474c3cbe3SAl Viro } 90574c3cbe3SAl Viro list_del(&barrier); 90674c3cbe3SAl Viro list_del(&cursor); 90774c3cbe3SAl Viro mutex_unlock(&audit_filter_mutex); 9082096f759SAl Viro path_put(&path1); 90974c3cbe3SAl Viro drop_collected_mounts(tagged); 91074c3cbe3SAl Viro return failed; 91174c3cbe3SAl Viro } 91274c3cbe3SAl Viro 913916d7576SAl Viro 914916d7576SAl Viro static void audit_schedule_prune(void) 915916d7576SAl Viro { 916f1aaf262SImre Palik wake_up_process(prune_thread); 917916d7576SAl Viro } 918916d7576SAl Viro 919916d7576SAl Viro /* 920916d7576SAl Viro * ... and that one is done if evict_chunk() decides to delay until the end 921916d7576SAl Viro * of syscall. Runs synchronously. 922916d7576SAl Viro */ 923916d7576SAl Viro void audit_kill_trees(struct list_head *list) 924916d7576SAl Viro { 925916d7576SAl Viro mutex_lock(&audit_cmd_mutex); 926916d7576SAl Viro mutex_lock(&audit_filter_mutex); 927916d7576SAl Viro 928916d7576SAl Viro while (!list_empty(list)) { 929916d7576SAl Viro struct audit_tree *victim; 930916d7576SAl Viro 931916d7576SAl Viro victim = list_entry(list->next, struct audit_tree, list); 932916d7576SAl Viro kill_rules(victim); 933916d7576SAl Viro list_del_init(&victim->list); 934916d7576SAl Viro 935916d7576SAl Viro mutex_unlock(&audit_filter_mutex); 936916d7576SAl Viro 937916d7576SAl Viro prune_one(victim); 938916d7576SAl Viro 939916d7576SAl Viro mutex_lock(&audit_filter_mutex); 940916d7576SAl Viro } 941916d7576SAl Viro 942916d7576SAl Viro mutex_unlock(&audit_filter_mutex); 943916d7576SAl Viro mutex_unlock(&audit_cmd_mutex); 94474c3cbe3SAl Viro } 94574c3cbe3SAl Viro 94674c3cbe3SAl Viro /* 94774c3cbe3SAl Viro * Here comes the stuff asynchronous to auditctl operations 94874c3cbe3SAl Viro */ 94974c3cbe3SAl Viro 95074c3cbe3SAl Viro static void evict_chunk(struct audit_chunk *chunk) 95174c3cbe3SAl Viro { 95274c3cbe3SAl Viro struct audit_tree *owner; 953916d7576SAl Viro struct list_head *postponed = audit_killed_trees(); 954916d7576SAl Viro int need_prune = 0; 95574c3cbe3SAl Viro int n; 95674c3cbe3SAl Viro 95774c3cbe3SAl Viro if (chunk->dead) 95874c3cbe3SAl Viro return; 95974c3cbe3SAl Viro 96074c3cbe3SAl Viro chunk->dead = 1; 96174c3cbe3SAl Viro mutex_lock(&audit_filter_mutex); 96274c3cbe3SAl Viro spin_lock(&hash_lock); 96374c3cbe3SAl Viro while (!list_empty(&chunk->trees)) { 96474c3cbe3SAl Viro owner = list_entry(chunk->trees.next, 96574c3cbe3SAl Viro struct audit_tree, same_root); 96674c3cbe3SAl Viro owner->goner = 1; 96774c3cbe3SAl Viro owner->root = NULL; 96874c3cbe3SAl Viro list_del_init(&owner->same_root); 96974c3cbe3SAl Viro spin_unlock(&hash_lock); 970916d7576SAl Viro if (!postponed) { 97174c3cbe3SAl Viro kill_rules(owner); 97274c3cbe3SAl Viro list_move(&owner->list, &prune_list); 973916d7576SAl Viro need_prune = 1; 974916d7576SAl Viro } else { 975916d7576SAl Viro list_move(&owner->list, postponed); 976916d7576SAl Viro } 97774c3cbe3SAl Viro spin_lock(&hash_lock); 97874c3cbe3SAl Viro } 97974c3cbe3SAl Viro list_del_rcu(&chunk->hash); 98074c3cbe3SAl Viro for (n = 0; n < chunk->count; n++) 98174c3cbe3SAl Viro list_del_init(&chunk->owners[n].list); 98274c3cbe3SAl Viro spin_unlock(&hash_lock); 983f1aaf262SImre Palik mutex_unlock(&audit_filter_mutex); 984916d7576SAl Viro if (need_prune) 985916d7576SAl Viro audit_schedule_prune(); 98674c3cbe3SAl Viro } 98774c3cbe3SAl Viro 9883a9b16b4SEric Paris static int audit_tree_handle_event(struct fsnotify_group *group, 9897053aee2SJan Kara struct inode *to_tell, 990ce8f76fbSEric Paris struct fsnotify_mark *inode_mark, 9917053aee2SJan Kara struct fsnotify_mark *vfsmount_mark, 9923cd5eca8SAl Viro u32 mask, const void *data, int data_type, 99345a22f4cSJan Kara const unsigned char *file_name, u32 cookie) 99474c3cbe3SAl Viro { 99583c4c4b0SJan Kara return 0; 99628a3a7ebSEric Paris } 99774c3cbe3SAl Viro 998e61ce867SEric Paris static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify_group *group) 99928a3a7ebSEric Paris { 100028a3a7ebSEric Paris struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark); 100128a3a7ebSEric Paris 100274c3cbe3SAl Viro evict_chunk(chunk); 1003b3e8692bSMiklos Szeredi 1004b3e8692bSMiklos Szeredi /* 1005b3e8692bSMiklos Szeredi * We are guaranteed to have at least one reference to the mark from 1006b3e8692bSMiklos Szeredi * either the inode or the caller of fsnotify_destroy_mark(). 1007b3e8692bSMiklos Szeredi */ 1008b3e8692bSMiklos Szeredi BUG_ON(atomic_read(&entry->refcnt) < 1); 100974c3cbe3SAl Viro } 101074c3cbe3SAl Viro 101128a3a7ebSEric Paris static const struct fsnotify_ops audit_tree_ops = { 101228a3a7ebSEric Paris .handle_event = audit_tree_handle_event, 101328a3a7ebSEric Paris .freeing_mark = audit_tree_freeing_mark, 101474c3cbe3SAl Viro }; 101574c3cbe3SAl Viro 101674c3cbe3SAl Viro static int __init audit_tree_init(void) 101774c3cbe3SAl Viro { 101874c3cbe3SAl Viro int i; 101974c3cbe3SAl Viro 10200d2e2a1dSEric Paris audit_tree_group = fsnotify_alloc_group(&audit_tree_ops); 102128a3a7ebSEric Paris if (IS_ERR(audit_tree_group)) 102228a3a7ebSEric Paris audit_panic("cannot initialize fsnotify group for rectree watches"); 102374c3cbe3SAl Viro 102474c3cbe3SAl Viro for (i = 0; i < HASH_SIZE; i++) 102574c3cbe3SAl Viro INIT_LIST_HEAD(&chunk_hash_heads[i]); 102674c3cbe3SAl Viro 102774c3cbe3SAl Viro return 0; 102874c3cbe3SAl Viro } 102974c3cbe3SAl Viro __initcall(audit_tree_init); 1030