Branch data Line data Source code
1 : : #include "audit.h"
2 : : #include <linux/fsnotify_backend.h>
3 : : #include <linux/namei.h>
4 : : #include <linux/mount.h>
5 : : #include <linux/kthread.h>
6 : : #include <linux/slab.h>
7 : :
8 : : struct audit_tree;
9 : : struct audit_chunk;
10 : :
11 : : struct audit_tree {
12 : : atomic_t count;
13 : : int goner;
14 : : struct audit_chunk *root;
15 : : struct list_head chunks;
16 : : struct list_head rules;
17 : : struct list_head list;
18 : : struct list_head same_root;
19 : : struct rcu_head head;
20 : : char pathname[];
21 : : };
22 : :
23 : : struct audit_chunk {
24 : : struct list_head hash;
25 : : struct fsnotify_mark mark;
26 : : struct list_head trees; /* with root here */
27 : : int dead;
28 : : int count;
29 : : atomic_long_t refs;
30 : : struct rcu_head head;
31 : : struct node {
32 : : struct list_head list;
33 : : struct audit_tree *owner;
34 : : unsigned index; /* index; upper bit indicates 'will prune' */
35 : : } owners[];
36 : : };
37 : :
38 : : static LIST_HEAD(tree_list);
39 : : static LIST_HEAD(prune_list);
40 : :
41 : : /*
42 : : * One struct chunk is attached to each inode of interest.
43 : : * We replace struct chunk on tagging/untagging.
44 : : * Rules have pointer to struct audit_tree.
45 : : * Rules have struct list_head rlist forming a list of rules over
46 : : * the same tree.
47 : : * References to struct chunk are collected at audit_inode{,_child}()
48 : : * time and used in AUDIT_TREE rule matching.
49 : : * These references are dropped at the same time we are calling
50 : : * audit_free_names(), etc.
51 : : *
52 : : * Cyclic lists galore:
53 : : * tree.chunks anchors chunk.owners[].list hash_lock
54 : : * tree.rules anchors rule.rlist audit_filter_mutex
55 : : * chunk.trees anchors tree.same_root hash_lock
56 : : * chunk.hash is a hash with middle bits of watch.inode as
57 : : * a hash function. RCU, hash_lock
58 : : *
59 : : * tree is refcounted; one reference for "some rules on rules_list refer to
60 : : * it", one for each chunk with pointer to it.
61 : : *
62 : : * chunk is refcounted by embedded fsnotify_mark + .refs (non-zero refcount
63 : : * of watch contributes 1 to .refs).
64 : : *
65 : : * node.index allows to get from node.list to containing chunk.
66 : : * MSB of that sucker is stolen to mark taggings that we might have to
67 : : * revert - several operations have very unpleasant cleanup logics and
68 : : * that makes a difference. Some.
69 : : */
70 : :
71 : : static struct fsnotify_group *audit_tree_group;
72 : :
73 : 0 : static struct audit_tree *alloc_tree(const char *s)
74 : : {
75 : : struct audit_tree *tree;
76 : :
77 : 0 : tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL);
78 [ # # ]: 0 : if (tree) {
79 : 0 : atomic_set(&tree->count, 1);
80 : 0 : tree->goner = 0;
81 : 0 : INIT_LIST_HEAD(&tree->chunks);
82 : 0 : INIT_LIST_HEAD(&tree->rules);
83 : 0 : INIT_LIST_HEAD(&tree->list);
84 : 0 : INIT_LIST_HEAD(&tree->same_root);
85 : 0 : tree->root = NULL;
86 : 0 : strcpy(tree->pathname, s);
87 : : }
88 : 0 : return tree;
89 : : }
90 : :
91 : : static inline void get_tree(struct audit_tree *tree)
92 : : {
93 : 0 : atomic_inc(&tree->count);
94 : : }
95 : :
96 : : static inline void put_tree(struct audit_tree *tree)
97 : : {
98 [ # # # # : 0 : if (atomic_dec_and_test(&tree->count))
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
99 : 0 : kfree_rcu(tree, head);
100 : : }
101 : :
102 : : /* to avoid bringing the entire thing in audit.h */
103 : 0 : const char *audit_tree_path(struct audit_tree *tree)
104 : : {
105 : 0 : return tree->pathname;
106 : : }
107 : :
108 : 0 : static void free_chunk(struct audit_chunk *chunk)
109 : : {
110 : : int i;
111 : :
112 [ # # ]: 0 : for (i = 0; i < chunk->count; i++) {
113 [ # # ]: 0 : if (chunk->owners[i].owner)
114 : : put_tree(chunk->owners[i].owner);
115 : : }
116 : 0 : kfree(chunk);
117 : 0 : }
118 : :
119 : 0 : void audit_put_chunk(struct audit_chunk *chunk)
120 : : {
121 [ # # ]: 0 : if (atomic_long_dec_and_test(&chunk->refs))
122 : 0 : free_chunk(chunk);
123 : 0 : }
124 : :
125 : 0 : static void __put_chunk(struct rcu_head *rcu)
126 : : {
127 : 0 : struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
128 : 0 : audit_put_chunk(chunk);
129 : 0 : }
130 : :
131 : 0 : static void audit_tree_destroy_watch(struct fsnotify_mark *entry)
132 : : {
133 : : struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark);
134 : 0 : call_rcu(&chunk->head, __put_chunk);
135 : 0 : }
136 : :
137 : 0 : static struct audit_chunk *alloc_chunk(int count)
138 : : {
139 : : struct audit_chunk *chunk;
140 : : size_t size;
141 : : int i;
142 : :
143 : 0 : size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node);
144 : : chunk = kzalloc(size, GFP_KERNEL);
145 [ # # ]: 0 : if (!chunk)
146 : : return NULL;
147 : :
148 : 0 : INIT_LIST_HEAD(&chunk->hash);
149 : 0 : INIT_LIST_HEAD(&chunk->trees);
150 : 0 : chunk->count = count;
151 : : atomic_long_set(&chunk->refs, 1);
152 [ # # ]: 0 : for (i = 0; i < count; i++) {
153 : 0 : INIT_LIST_HEAD(&chunk->owners[i].list);
154 : 0 : chunk->owners[i].index = i;
155 : : }
156 : 0 : fsnotify_init_mark(&chunk->mark, audit_tree_destroy_watch);
157 : 0 : return chunk;
158 : : }
159 : :
160 : : enum {HASH_SIZE = 128};
161 : : static struct list_head chunk_hash_heads[HASH_SIZE];
162 : : static __cacheline_aligned_in_smp DEFINE_SPINLOCK(hash_lock);
163 : :
164 : : static inline struct list_head *chunk_hash(const struct inode *inode)
165 : : {
166 : 0 : unsigned long n = (unsigned long)inode / L1_CACHE_BYTES;
167 : 0 : return chunk_hash_heads + n % HASH_SIZE;
168 : : }
169 : :
170 : : /* hash_lock & entry->lock is held by caller */
171 : : static void insert_hash(struct audit_chunk *chunk)
172 : : {
173 : : struct fsnotify_mark *entry = &chunk->mark;
174 : : struct list_head *list;
175 : :
176 [ # # ]: 0 : if (!entry->i.inode)
177 : : return;
178 : : list = chunk_hash(entry->i.inode);
179 : 0 : list_add_rcu(&chunk->hash, list);
180 : : }
181 : :
182 : : /* called under rcu_read_lock */
183 : 0 : struct audit_chunk *audit_tree_lookup(const struct inode *inode)
184 : : {
185 : : struct list_head *list = chunk_hash(inode);
186 : : struct audit_chunk *p;
187 : :
188 [ # # ]: 0 : list_for_each_entry_rcu(p, list, hash) {
189 : : /* mark.inode may have gone NULL, but who cares? */
190 [ # # ]: 0 : if (p->mark.i.inode == inode) {
191 : 0 : atomic_long_inc(&p->refs);
192 : 0 : return p;
193 : : }
194 : : }
195 : : return NULL;
196 : : }
197 : :
198 : 0 : int audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree)
199 : : {
200 : : int n;
201 [ # # ]: 0 : for (n = 0; n < chunk->count; n++)
202 [ # # ]: 0 : if (chunk->owners[n].owner == tree)
203 : : return 1;
204 : : return 0;
205 : : }
206 : :
207 : : /* tagging and untagging inodes with trees */
208 : :
209 : : static struct audit_chunk *find_chunk(struct node *p)
210 : : {
211 : 0 : int index = p->index & ~(1U<<31);
212 : 0 : p -= index;
213 : : return container_of(p, struct audit_chunk, owners[0]);
214 : : }
215 : :
216 : 0 : static void untag_chunk(struct node *p)
217 : : {
218 : 0 : struct audit_chunk *chunk = find_chunk(p);
219 : 0 : struct fsnotify_mark *entry = &chunk->mark;
220 : : struct audit_chunk *new = NULL;
221 : : struct audit_tree *owner;
222 : 0 : int size = chunk->count - 1;
223 : : int i, j;
224 : :
225 : 0 : fsnotify_get_mark(entry);
226 : :
227 : : spin_unlock(&hash_lock);
228 : :
229 [ # # ]: 0 : if (size)
230 : 0 : new = alloc_chunk(size);
231 : :
232 : : spin_lock(&entry->lock);
233 [ # # ][ # # ]: 0 : if (chunk->dead || !entry->i.inode) {
234 : : spin_unlock(&entry->lock);
235 [ # # ]: 0 : if (new)
236 : 0 : free_chunk(new);
237 : : goto out;
238 : : }
239 : :
240 : 0 : owner = p->owner;
241 : :
242 [ # # ]: 0 : if (!size) {
243 : 0 : chunk->dead = 1;
244 : : spin_lock(&hash_lock);
245 : 0 : list_del_init(&chunk->trees);
246 [ # # ]: 0 : if (owner->root == chunk)
247 : 0 : owner->root = NULL;
248 : 0 : list_del_init(&p->list);
249 : : list_del_rcu(&chunk->hash);
250 : : spin_unlock(&hash_lock);
251 : : spin_unlock(&entry->lock);
252 : 0 : fsnotify_destroy_mark(entry, audit_tree_group);
253 : 0 : goto out;
254 : : }
255 : :
256 [ # # ]: 0 : if (!new)
257 : : goto Fallback;
258 : :
259 : 0 : fsnotify_duplicate_mark(&new->mark, entry);
260 [ # # ]: 0 : if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) {
261 : 0 : fsnotify_put_mark(&new->mark);
262 : 0 : goto Fallback;
263 : : }
264 : :
265 : 0 : chunk->dead = 1;
266 : : spin_lock(&hash_lock);
267 : 0 : list_replace_init(&chunk->trees, &new->trees);
268 [ # # ]: 0 : if (owner->root == chunk) {
269 : 0 : list_del_init(&owner->same_root);
270 : 0 : owner->root = NULL;
271 : : }
272 : :
273 [ # # ]: 0 : for (i = j = 0; j <= size; i++, j++) {
274 : : struct audit_tree *s;
275 [ # # ]: 0 : if (&chunk->owners[j] == p) {
276 : 0 : list_del_init(&p->list);
277 : 0 : i--;
278 : 0 : continue;
279 : : }
280 : 0 : s = chunk->owners[j].owner;
281 : 0 : new->owners[i].owner = s;
282 : 0 : new->owners[i].index = chunk->owners[j].index - j + i;
283 [ # # ]: 0 : if (!s) /* result of earlier fallback */
284 : 0 : continue;
285 : : get_tree(s);
286 : 0 : list_replace_init(&chunk->owners[j].list, &new->owners[i].list);
287 : : }
288 : :
289 : 0 : list_replace_rcu(&chunk->hash, &new->hash);
290 [ # # ]: 0 : list_for_each_entry(owner, &new->trees, same_root)
291 : 0 : owner->root = new;
292 : : spin_unlock(&hash_lock);
293 : : spin_unlock(&entry->lock);
294 : 0 : fsnotify_destroy_mark(entry, audit_tree_group);
295 : 0 : fsnotify_put_mark(&new->mark); /* drop initial reference */
296 : 0 : goto out;
297 : :
298 : : Fallback:
299 : : // do the best we can
300 : : spin_lock(&hash_lock);
301 [ # # ]: 0 : if (owner->root == chunk) {
302 : 0 : list_del_init(&owner->same_root);
303 : 0 : owner->root = NULL;
304 : : }
305 : 0 : list_del_init(&p->list);
306 : 0 : p->owner = NULL;
307 : : put_tree(owner);
308 : : spin_unlock(&hash_lock);
309 : : spin_unlock(&entry->lock);
310 : : out:
311 : 0 : fsnotify_put_mark(entry);
312 : : spin_lock(&hash_lock);
313 : 0 : }
314 : :
315 : 0 : static int create_chunk(struct inode *inode, struct audit_tree *tree)
316 : : {
317 : : struct fsnotify_mark *entry;
318 : 0 : struct audit_chunk *chunk = alloc_chunk(1);
319 [ # # ]: 0 : if (!chunk)
320 : : return -ENOMEM;
321 : :
322 : 0 : entry = &chunk->mark;
323 [ # # ]: 0 : if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) {
324 : 0 : fsnotify_put_mark(entry);
325 : 0 : return -ENOSPC;
326 : : }
327 : :
328 : : spin_lock(&entry->lock);
329 : : spin_lock(&hash_lock);
330 [ # # ]: 0 : if (tree->goner) {
331 : : spin_unlock(&hash_lock);
332 : 0 : chunk->dead = 1;
333 : : spin_unlock(&entry->lock);
334 : 0 : fsnotify_destroy_mark(entry, audit_tree_group);
335 : 0 : fsnotify_put_mark(entry);
336 : 0 : return 0;
337 : : }
338 : 0 : chunk->owners[0].index = (1U << 31);
339 : 0 : chunk->owners[0].owner = tree;
340 : : get_tree(tree);
341 : 0 : list_add(&chunk->owners[0].list, &tree->chunks);
342 [ # # ]: 0 : if (!tree->root) {
343 : 0 : tree->root = chunk;
344 : 0 : list_add(&tree->same_root, &chunk->trees);
345 : : }
346 : : insert_hash(chunk);
347 : : spin_unlock(&hash_lock);
348 : : spin_unlock(&entry->lock);
349 : 0 : fsnotify_put_mark(entry); /* drop initial reference */
350 : 0 : return 0;
351 : : }
352 : :
353 : : /* the first tagged inode becomes root of tree */
354 : 0 : static int tag_chunk(struct inode *inode, struct audit_tree *tree)
355 : : {
356 : : struct fsnotify_mark *old_entry, *chunk_entry;
357 : : struct audit_tree *owner;
358 : : struct audit_chunk *chunk, *old;
359 : : struct node *p;
360 : : int n;
361 : :
362 : 0 : old_entry = fsnotify_find_inode_mark(audit_tree_group, inode);
363 [ # # ]: 0 : if (!old_entry)
364 : 0 : return create_chunk(inode, tree);
365 : :
366 : : old = container_of(old_entry, struct audit_chunk, mark);
367 : :
368 : : /* are we already there? */
369 : : spin_lock(&hash_lock);
370 [ # # ]: 0 : for (n = 0; n < old->count; n++) {
371 [ # # ]: 0 : if (old->owners[n].owner == tree) {
372 : : spin_unlock(&hash_lock);
373 : 0 : fsnotify_put_mark(old_entry);
374 : 0 : return 0;
375 : : }
376 : : }
377 : : spin_unlock(&hash_lock);
378 : :
379 : 0 : chunk = alloc_chunk(old->count + 1);
380 [ # # ]: 0 : if (!chunk) {
381 : 0 : fsnotify_put_mark(old_entry);
382 : 0 : return -ENOMEM;
383 : : }
384 : :
385 : 0 : chunk_entry = &chunk->mark;
386 : :
387 : : spin_lock(&old_entry->lock);
388 [ # # ]: 0 : if (!old_entry->i.inode) {
389 : : /* old_entry is being shot, lets just lie */
390 : : spin_unlock(&old_entry->lock);
391 : 0 : fsnotify_put_mark(old_entry);
392 : 0 : free_chunk(chunk);
393 : 0 : return -ENOENT;
394 : : }
395 : :
396 : 0 : fsnotify_duplicate_mark(chunk_entry, old_entry);
397 [ # # ]: 0 : if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, NULL, 1)) {
398 : : spin_unlock(&old_entry->lock);
399 : 0 : fsnotify_put_mark(chunk_entry);
400 : 0 : fsnotify_put_mark(old_entry);
401 : 0 : return -ENOSPC;
402 : : }
403 : :
404 : : /* even though we hold old_entry->lock, this is safe since chunk_entry->lock could NEVER have been grabbed before */
405 : : spin_lock(&chunk_entry->lock);
406 : : spin_lock(&hash_lock);
407 : :
408 : : /* we now hold old_entry->lock, chunk_entry->lock, and hash_lock */
409 [ # # ]: 0 : if (tree->goner) {
410 : : spin_unlock(&hash_lock);
411 : 0 : chunk->dead = 1;
412 : : spin_unlock(&chunk_entry->lock);
413 : : spin_unlock(&old_entry->lock);
414 : :
415 : 0 : fsnotify_destroy_mark(chunk_entry, audit_tree_group);
416 : :
417 : 0 : fsnotify_put_mark(chunk_entry);
418 : 0 : fsnotify_put_mark(old_entry);
419 : 0 : return 0;
420 : : }
421 : 0 : list_replace_init(&old->trees, &chunk->trees);
422 [ # # ]: 0 : for (n = 0, p = chunk->owners; n < old->count; n++, p++) {
423 : 0 : struct audit_tree *s = old->owners[n].owner;
424 : 0 : p->owner = s;
425 : 0 : p->index = old->owners[n].index;
426 [ # # ]: 0 : if (!s) /* result of fallback in untag */
427 : 0 : continue;
428 : : get_tree(s);
429 : 0 : list_replace_init(&old->owners[n].list, &p->list);
430 : : }
431 : 0 : p->index = (chunk->count - 1) | (1U<<31);
432 : 0 : p->owner = tree;
433 : : get_tree(tree);
434 : 0 : list_add(&p->list, &tree->chunks);
435 : 0 : list_replace_rcu(&old->hash, &chunk->hash);
436 [ # # ]: 0 : list_for_each_entry(owner, &chunk->trees, same_root)
437 : 0 : owner->root = chunk;
438 : 0 : old->dead = 1;
439 [ # # ]: 0 : if (!tree->root) {
440 : 0 : tree->root = chunk;
441 : 0 : list_add(&tree->same_root, &chunk->trees);
442 : : }
443 : : spin_unlock(&hash_lock);
444 : : spin_unlock(&chunk_entry->lock);
445 : : spin_unlock(&old_entry->lock);
446 : 0 : fsnotify_destroy_mark(old_entry, audit_tree_group);
447 : 0 : fsnotify_put_mark(chunk_entry); /* drop initial reference */
448 : 0 : fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */
449 : 0 : return 0;
450 : : }
451 : :
452 : 0 : static void audit_log_remove_rule(struct audit_krule *rule)
453 : : {
454 : : struct audit_buffer *ab;
455 : :
456 : 0 : ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
457 [ # # ]: 0 : if (unlikely(!ab))
458 : 0 : return;
459 : 0 : audit_log_format(ab, "op=");
460 : : audit_log_string(ab, "remove rule");
461 : 0 : audit_log_format(ab, " dir=");
462 : 0 : audit_log_untrustedstring(ab, rule->tree->pathname);
463 : 0 : audit_log_key(ab, rule->filterkey);
464 : 0 : audit_log_format(ab, " list=%d res=1", rule->listnr);
465 : 0 : audit_log_end(ab);
466 : : }
467 : :
468 : 0 : static void kill_rules(struct audit_tree *tree)
469 : : {
470 : : struct audit_krule *rule, *next;
471 : : struct audit_entry *entry;
472 : :
473 [ # # ]: 0 : list_for_each_entry_safe(rule, next, &tree->rules, rlist) {
474 : : entry = container_of(rule, struct audit_entry, rule);
475 : :
476 : : list_del_init(&rule->rlist);
477 [ # # ]: 0 : if (rule->tree) {
478 : : /* not a half-baked one */
479 : 0 : audit_log_remove_rule(rule);
480 : 0 : rule->tree = NULL;
481 : : list_del_rcu(&entry->list);
482 : : list_del(&entry->rule.list);
483 : 0 : call_rcu(&entry->rcu, audit_free_rule_rcu);
484 : : }
485 : : }
486 : 0 : }
487 : :
488 : : /*
489 : : * finish killing struct audit_tree
490 : : */
491 : 0 : static void prune_one(struct audit_tree *victim)
492 : : {
493 : : spin_lock(&hash_lock);
494 [ # # ]: 0 : while (!list_empty(&victim->chunks)) {
495 : : struct node *p;
496 : :
497 : : p = list_entry(victim->chunks.next, struct node, list);
498 : :
499 : 0 : untag_chunk(p);
500 : : }
501 : : spin_unlock(&hash_lock);
502 : : put_tree(victim);
503 : 0 : }
504 : :
505 : : /* trim the uncommitted chunks from tree */
506 : :
507 : 0 : static void trim_marked(struct audit_tree *tree)
508 : : {
509 : : struct list_head *p, *q;
510 : : spin_lock(&hash_lock);
511 [ # # ]: 0 : if (tree->goner) {
512 : : spin_unlock(&hash_lock);
513 : 0 : return;
514 : : }
515 : : /* reorder */
516 [ # # ]: 0 : for (p = tree->chunks.next; p != &tree->chunks; p = q) {
517 : : struct node *node = list_entry(p, struct node, list);
518 : 0 : q = p->next;
519 [ # # ]: 0 : if (node->index & (1U<<31)) {
520 : : list_del_init(p);
521 : : list_add(p, &tree->chunks);
522 : : }
523 : : }
524 : :
525 [ # # ]: 0 : while (!list_empty(&tree->chunks)) {
526 : : struct node *node;
527 : :
528 : : node = list_entry(tree->chunks.next, struct node, list);
529 : :
530 : : /* have we run out of marked? */
531 [ # # ]: 0 : if (!(node->index & (1U<<31)))
532 : : break;
533 : :
534 : 0 : untag_chunk(node);
535 : : }
536 [ # # ][ # # ]: 0 : if (!tree->root && !tree->goner) {
537 : 0 : tree->goner = 1;
538 : : spin_unlock(&hash_lock);
539 : 0 : mutex_lock(&audit_filter_mutex);
540 : 0 : kill_rules(tree);
541 : 0 : list_del_init(&tree->list);
542 : 0 : mutex_unlock(&audit_filter_mutex);
543 : 0 : prune_one(tree);
544 : : } else {
545 : : spin_unlock(&hash_lock);
546 : : }
547 : : }
548 : :
549 : : static void audit_schedule_prune(void);
550 : :
551 : : /* called with audit_filter_mutex */
552 : 0 : int audit_remove_tree_rule(struct audit_krule *rule)
553 : : {
554 : : struct audit_tree *tree;
555 : 0 : tree = rule->tree;
556 [ # # ]: 0 : if (tree) {
557 : : spin_lock(&hash_lock);
558 : 0 : list_del_init(&rule->rlist);
559 [ # # ][ # # ]: 0 : if (list_empty(&tree->rules) && !tree->goner) {
560 : 0 : tree->root = NULL;
561 : 0 : list_del_init(&tree->same_root);
562 : 0 : tree->goner = 1;
563 : 0 : list_move(&tree->list, &prune_list);
564 : 0 : rule->tree = NULL;
565 : : spin_unlock(&hash_lock);
566 : 0 : audit_schedule_prune();
567 : 0 : return 1;
568 : : }
569 : 0 : rule->tree = NULL;
570 : : spin_unlock(&hash_lock);
571 : 0 : return 1;
572 : : }
573 : : return 0;
574 : : }
575 : :
576 : 0 : static int compare_root(struct vfsmount *mnt, void *arg)
577 : : {
578 : 0 : return mnt->mnt_root->d_inode == arg;
579 : : }
580 : :
581 : 0 : void audit_trim_trees(void)
582 : : {
583 : : struct list_head cursor;
584 : :
585 : 0 : mutex_lock(&audit_filter_mutex);
586 : : list_add(&cursor, &tree_list);
587 [ # # ]: 0 : while (cursor.next != &tree_list) {
588 : : struct audit_tree *tree;
589 : : struct path path;
590 : : struct vfsmount *root_mnt;
591 : : struct node *node;
592 : : int err;
593 : :
594 : 0 : tree = container_of(cursor.next, struct audit_tree, list);
595 : : get_tree(tree);
596 : : list_del(&cursor);
597 : 0 : list_add(&cursor, &tree->list);
598 : 0 : mutex_unlock(&audit_filter_mutex);
599 : :
600 : 0 : err = kern_path(tree->pathname, 0, &path);
601 [ # # ]: 0 : if (err)
602 : : goto skip_it;
603 : :
604 : 0 : root_mnt = collect_mounts(&path);
605 : 0 : path_put(&path);
606 [ # # ]: 0 : if (IS_ERR(root_mnt))
607 : : goto skip_it;
608 : :
609 : : spin_lock(&hash_lock);
610 [ # # ]: 0 : list_for_each_entry(node, &tree->chunks, list) {
611 : : struct audit_chunk *chunk = find_chunk(node);
612 : : /* this could be NULL if the watch is dying else where... */
613 : 0 : struct inode *inode = chunk->mark.i.inode;
614 : 0 : node->index |= 1U<<31;
615 [ # # ]: 0 : if (iterate_mounts(compare_root, inode, root_mnt))
616 : 0 : node->index &= ~(1U<<31);
617 : : }
618 : : spin_unlock(&hash_lock);
619 : 0 : trim_marked(tree);
620 : 0 : drop_collected_mounts(root_mnt);
621 : : skip_it:
622 : : put_tree(tree);
623 : 0 : mutex_lock(&audit_filter_mutex);
624 : : }
625 : : list_del(&cursor);
626 : 0 : mutex_unlock(&audit_filter_mutex);
627 : 0 : }
628 : :
629 : 0 : int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
630 : : {
631 : :
632 [ # # ][ # # ]: 0 : if (pathname[0] != '/' ||
633 [ # # ]: 0 : rule->listnr != AUDIT_FILTER_EXIT ||
634 [ # # ]: 0 : op != Audit_equal ||
635 [ # # ][ # # ]: 0 : rule->inode_f || rule->watch || rule->tree)
636 : : return -EINVAL;
637 : 0 : rule->tree = alloc_tree(pathname);
638 [ # # ]: 0 : if (!rule->tree)
639 : : return -ENOMEM;
640 : 0 : return 0;
641 : : }
642 : :
643 : 0 : void audit_put_tree(struct audit_tree *tree)
644 : : {
645 : : put_tree(tree);
646 : 0 : }
647 : :
648 : 0 : static int tag_mount(struct vfsmount *mnt, void *arg)
649 : : {
650 : 0 : return tag_chunk(mnt->mnt_root->d_inode, arg);
651 : : }
652 : :
653 : : /* called with audit_filter_mutex */
654 : 0 : int audit_add_tree_rule(struct audit_krule *rule)
655 : : {
656 : 0 : struct audit_tree *seed = rule->tree, *tree;
657 : : struct path path;
658 : : struct vfsmount *mnt;
659 : : int err;
660 : :
661 : 0 : rule->tree = NULL;
662 [ # # ]: 0 : list_for_each_entry(tree, &tree_list, list) {
663 [ # # ]: 0 : if (!strcmp(seed->pathname, tree->pathname)) {
664 : : put_tree(seed);
665 : 0 : rule->tree = tree;
666 : 0 : list_add(&rule->rlist, &tree->rules);
667 : 0 : return 0;
668 : : }
669 : : }
670 : : tree = seed;
671 : 0 : list_add(&tree->list, &tree_list);
672 : 0 : list_add(&rule->rlist, &tree->rules);
673 : : /* do not set rule->tree yet */
674 : 0 : mutex_unlock(&audit_filter_mutex);
675 : :
676 : 0 : err = kern_path(tree->pathname, 0, &path);
677 [ # # ]: 0 : if (err)
678 : : goto Err;
679 : 0 : mnt = collect_mounts(&path);
680 : 0 : path_put(&path);
681 [ # # ]: 0 : if (IS_ERR(mnt)) {
682 : : err = PTR_ERR(mnt);
683 : 0 : goto Err;
684 : : }
685 : :
686 : : get_tree(tree);
687 : 0 : err = iterate_mounts(tag_mount, tree, mnt);
688 : 0 : drop_collected_mounts(mnt);
689 : :
690 [ # # ]: 0 : if (!err) {
691 : : struct node *node;
692 : : spin_lock(&hash_lock);
693 [ # # ]: 0 : list_for_each_entry(node, &tree->chunks, list)
694 : 0 : node->index &= ~(1U<<31);
695 : : spin_unlock(&hash_lock);
696 : : } else {
697 : 0 : trim_marked(tree);
698 : 0 : goto Err;
699 : : }
700 : :
701 : 0 : mutex_lock(&audit_filter_mutex);
702 [ # # ]: 0 : if (list_empty(&rule->rlist)) {
703 : : put_tree(tree);
704 : : return -ENOENT;
705 : : }
706 : 0 : rule->tree = tree;
707 : : put_tree(tree);
708 : :
709 : : return 0;
710 : : Err:
711 : 0 : mutex_lock(&audit_filter_mutex);
712 : : list_del_init(&tree->list);
713 : : list_del_init(&tree->rules);
714 : : put_tree(tree);
715 : 0 : return err;
716 : : }
717 : :
718 : 0 : int audit_tag_tree(char *old, char *new)
719 : : {
720 : : struct list_head cursor, barrier;
721 : : int failed = 0;
722 : : struct path path1, path2;
723 : : struct vfsmount *tagged;
724 : : int err;
725 : :
726 : 0 : err = kern_path(new, 0, &path2);
727 [ # # ]: 0 : if (err)
728 : : return err;
729 : 0 : tagged = collect_mounts(&path2);
730 : 0 : path_put(&path2);
731 [ # # ]: 0 : if (IS_ERR(tagged))
732 : 0 : return PTR_ERR(tagged);
733 : :
734 : 0 : err = kern_path(old, 0, &path1);
735 [ # # ]: 0 : if (err) {
736 : 0 : drop_collected_mounts(tagged);
737 : 0 : return err;
738 : : }
739 : :
740 : 0 : mutex_lock(&audit_filter_mutex);
741 : : list_add(&barrier, &tree_list);
742 : : list_add(&cursor, &barrier);
743 : :
744 [ # # ]: 0 : while (cursor.next != &tree_list) {
745 : : struct audit_tree *tree;
746 : : int good_one = 0;
747 : :
748 : 0 : tree = container_of(cursor.next, struct audit_tree, list);
749 : : get_tree(tree);
750 : : list_del(&cursor);
751 : 0 : list_add(&cursor, &tree->list);
752 : 0 : mutex_unlock(&audit_filter_mutex);
753 : :
754 : 0 : err = kern_path(tree->pathname, 0, &path2);
755 [ # # ]: 0 : if (!err) {
756 : 0 : good_one = path_is_under(&path1, &path2);
757 : 0 : path_put(&path2);
758 : : }
759 : :
760 [ # # ]: 0 : if (!good_one) {
761 : : put_tree(tree);
762 : 0 : mutex_lock(&audit_filter_mutex);
763 : 0 : continue;
764 : : }
765 : :
766 : 0 : failed = iterate_mounts(tag_mount, tree, tagged);
767 [ # # ]: 0 : if (failed) {
768 : : put_tree(tree);
769 : 0 : mutex_lock(&audit_filter_mutex);
770 : 0 : break;
771 : : }
772 : :
773 : 0 : mutex_lock(&audit_filter_mutex);
774 : : spin_lock(&hash_lock);
775 [ # # ]: 0 : if (!tree->goner) {
776 : : list_del(&tree->list);
777 : : list_add(&tree->list, &tree_list);
778 : : }
779 : : spin_unlock(&hash_lock);
780 : : put_tree(tree);
781 : : }
782 : :
783 [ # # ]: 0 : while (barrier.prev != &tree_list) {
784 : : struct audit_tree *tree;
785 : :
786 : 0 : tree = container_of(barrier.prev, struct audit_tree, list);
787 : : get_tree(tree);
788 : : list_del(&tree->list);
789 : 0 : list_add(&tree->list, &barrier);
790 : 0 : mutex_unlock(&audit_filter_mutex);
791 : :
792 [ # # ]: 0 : if (!failed) {
793 : : struct node *node;
794 : : spin_lock(&hash_lock);
795 [ # # ]: 0 : list_for_each_entry(node, &tree->chunks, list)
796 : 0 : node->index &= ~(1U<<31);
797 : : spin_unlock(&hash_lock);
798 : : } else {
799 : 0 : trim_marked(tree);
800 : : }
801 : :
802 : : put_tree(tree);
803 : 0 : mutex_lock(&audit_filter_mutex);
804 : : }
805 : : list_del(&barrier);
806 : : list_del(&cursor);
807 : 0 : mutex_unlock(&audit_filter_mutex);
808 : 0 : path_put(&path1);
809 : 0 : drop_collected_mounts(tagged);
810 : 0 : return failed;
811 : : }
812 : :
813 : : /*
814 : : * That gets run when evict_chunk() ends up needing to kill audit_tree.
815 : : * Runs from a separate thread.
816 : : */
817 : 0 : static int prune_tree_thread(void *unused)
818 : : {
819 : 0 : mutex_lock(&audit_cmd_mutex);
820 : 0 : mutex_lock(&audit_filter_mutex);
821 : :
822 [ # # ]: 0 : while (!list_empty(&prune_list)) {
823 : : struct audit_tree *victim;
824 : :
825 : 0 : victim = list_entry(prune_list.next, struct audit_tree, list);
826 : 0 : list_del_init(&victim->list);
827 : :
828 : 0 : mutex_unlock(&audit_filter_mutex);
829 : :
830 : 0 : prune_one(victim);
831 : :
832 : 0 : mutex_lock(&audit_filter_mutex);
833 : : }
834 : :
835 : 0 : mutex_unlock(&audit_filter_mutex);
836 : 0 : mutex_unlock(&audit_cmd_mutex);
837 : 0 : return 0;
838 : : }
839 : :
840 : 0 : static void audit_schedule_prune(void)
841 : : {
842 [ # # ]: 0 : kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
843 : 0 : }
844 : :
845 : : /*
846 : : * ... and that one is done if evict_chunk() decides to delay until the end
847 : : * of syscall. Runs synchronously.
848 : : */
849 : 0 : void audit_kill_trees(struct list_head *list)
850 : : {
851 : 0 : mutex_lock(&audit_cmd_mutex);
852 : 0 : mutex_lock(&audit_filter_mutex);
853 : :
854 [ # # ]: 0 : while (!list_empty(list)) {
855 : : struct audit_tree *victim;
856 : :
857 : 0 : victim = list_entry(list->next, struct audit_tree, list);
858 : 0 : kill_rules(victim);
859 : 0 : list_del_init(&victim->list);
860 : :
861 : 0 : mutex_unlock(&audit_filter_mutex);
862 : :
863 : 0 : prune_one(victim);
864 : :
865 : 0 : mutex_lock(&audit_filter_mutex);
866 : : }
867 : :
868 : 0 : mutex_unlock(&audit_filter_mutex);
869 : 0 : mutex_unlock(&audit_cmd_mutex);
870 : 0 : }
871 : :
872 : : /*
873 : : * Here comes the stuff asynchronous to auditctl operations
874 : : */
875 : :
876 : 0 : static void evict_chunk(struct audit_chunk *chunk)
877 : : {
878 : : struct audit_tree *owner;
879 : 0 : struct list_head *postponed = audit_killed_trees();
880 : : int need_prune = 0;
881 : : int n;
882 : :
883 [ # # ]: 0 : if (chunk->dead)
884 : 0 : return;
885 : :
886 : 0 : chunk->dead = 1;
887 : 0 : mutex_lock(&audit_filter_mutex);
888 : : spin_lock(&hash_lock);
889 [ # # ]: 0 : while (!list_empty(&chunk->trees)) {
890 : 0 : owner = list_entry(chunk->trees.next,
891 : : struct audit_tree, same_root);
892 : 0 : owner->goner = 1;
893 : 0 : owner->root = NULL;
894 : 0 : list_del_init(&owner->same_root);
895 : : spin_unlock(&hash_lock);
896 [ # # ]: 0 : if (!postponed) {
897 : 0 : kill_rules(owner);
898 : 0 : list_move(&owner->list, &prune_list);
899 : : need_prune = 1;
900 : : } else {
901 : 0 : list_move(&owner->list, postponed);
902 : : }
903 : : spin_lock(&hash_lock);
904 : : }
905 : : list_del_rcu(&chunk->hash);
906 [ # # ]: 0 : for (n = 0; n < chunk->count; n++)
907 : 0 : list_del_init(&chunk->owners[n].list);
908 : : spin_unlock(&hash_lock);
909 [ # # ]: 0 : if (need_prune)
910 : 0 : audit_schedule_prune();
911 : 0 : mutex_unlock(&audit_filter_mutex);
912 : : }
913 : :
914 : 0 : static int audit_tree_handle_event(struct fsnotify_group *group,
915 : : struct inode *to_tell,
916 : : struct fsnotify_mark *inode_mark,
917 : : struct fsnotify_mark *vfsmount_mark,
918 : : u32 mask, void *data, int data_type,
919 : : const unsigned char *file_name, u32 cookie)
920 : : {
921 : 0 : return 0;
922 : : }
923 : :
924 : 0 : static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify_group *group)
925 : : {
926 : 0 : struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark);
927 : :
928 : 0 : evict_chunk(chunk);
929 : :
930 : : /*
931 : : * We are guaranteed to have at least one reference to the mark from
932 : : * either the inode or the caller of fsnotify_destroy_mark().
933 : : */
934 [ # # ]: 0 : BUG_ON(atomic_read(&entry->refcnt) < 1);
935 : 0 : }
936 : :
937 : : static const struct fsnotify_ops audit_tree_ops = {
938 : : .handle_event = audit_tree_handle_event,
939 : : .freeing_mark = audit_tree_freeing_mark,
940 : : };
941 : :
942 : 0 : static int __init audit_tree_init(void)
943 : : {
944 : : int i;
945 : :
946 : 0 : audit_tree_group = fsnotify_alloc_group(&audit_tree_ops);
947 [ # # ]: 0 : if (IS_ERR(audit_tree_group))
948 : 0 : audit_panic("cannot initialize fsnotify group for rectree watches");
949 : :
950 [ # # ]: 0 : for (i = 0; i < HASH_SIZE; i++)
951 : 0 : INIT_LIST_HEAD(&chunk_hash_heads[i]);
952 : :
953 : 0 : return 0;
954 : : }
955 : : __initcall(audit_tree_init);
|