hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/kernel/audit_tree.c
....@@ -25,9 +25,8 @@
2525 struct audit_chunk {
2626 struct list_head hash;
2727 unsigned long key;
28
- struct fsnotify_mark mark;
28
+ struct fsnotify_mark *mark;
2929 struct list_head trees; /* with root here */
30
- int dead;
3130 int count;
3231 atomic_long_t refs;
3332 struct rcu_head head;
....@@ -38,13 +37,25 @@
3837 } owners[];
3938 };
4039
40
+struct audit_tree_mark {
41
+ struct fsnotify_mark mark;
42
+ struct audit_chunk *chunk;
43
+};
44
+
4145 static LIST_HEAD(tree_list);
4246 static LIST_HEAD(prune_list);
4347 static struct task_struct *prune_thread;
4448
4549 /*
46
- * One struct chunk is attached to each inode of interest.
47
- * We replace struct chunk on tagging/untagging.
50
+ * One struct chunk is attached to each inode of interest through
51
+ * audit_tree_mark (fsnotify mark). We replace struct chunk on tagging /
52
+ * untagging, the mark is stable as long as there is chunk attached. The
53
+ * association between mark and chunk is protected by hash_lock and
54
+ * audit_tree_group->mark_mutex. Thus as long as we hold
55
+ * audit_tree_group->mark_mutex and check that the mark is alive by
56
+ * FSNOTIFY_MARK_FLAG_ATTACHED flag check, we are sure the mark points to
57
+ * the current chunk.
58
+ *
4859 * Rules have pointer to struct audit_tree.
4960 * Rules have struct list_head rlist forming a list of rules over
5061 * the same tree.
....@@ -63,8 +74,12 @@
6374 * tree is refcounted; one reference for "some rules on rules_list refer to
6475 * it", one for each chunk with pointer to it.
6576 *
66
- * chunk is refcounted by embedded fsnotify_mark + .refs (non-zero refcount
67
- * of watch contributes 1 to .refs).
77
+ * chunk is refcounted by embedded .refs. Mark associated with the chunk holds
78
+ * one chunk reference. This reference is dropped either when a mark is going
79
+ * to be freed (corresponding inode goes away) or when chunk attached to the
80
+ * mark gets replaced. This reference must be dropped using
81
+ * audit_mark_put_chunk() to make sure the reference is dropped only after RCU
82
+ * grace period as it protects RCU readers of the hash table.
6883 *
6984 * node.index allows to get from node.list to containing chunk.
7085 * MSB of that sucker is stolen to mark taggings that we might have to
....@@ -73,6 +88,7 @@
7388 */
7489
7590 static struct fsnotify_group *audit_tree_group;
91
+static struct kmem_cache *audit_tree_mark_cachep __read_mostly;
7692
7793 static struct audit_tree *alloc_tree(const char *s)
7894 {
....@@ -132,20 +148,49 @@
132148 audit_put_chunk(chunk);
133149 }
134150
135
-static void audit_tree_destroy_watch(struct fsnotify_mark *entry)
151
+/*
152
+ * Drop reference to the chunk that was held by the mark. This is the reference
153
+ * that gets dropped after we've removed the chunk from the hash table and we
154
+ * use it to make sure chunk cannot be freed before RCU grace period expires.
155
+ */
156
+static void audit_mark_put_chunk(struct audit_chunk *chunk)
136157 {
137
- struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark);
138158 call_rcu(&chunk->head, __put_chunk);
159
+}
160
+
161
+static inline struct audit_tree_mark *audit_mark(struct fsnotify_mark *mark)
162
+{
163
+ return container_of(mark, struct audit_tree_mark, mark);
164
+}
165
+
166
+static struct audit_chunk *mark_chunk(struct fsnotify_mark *mark)
167
+{
168
+ return audit_mark(mark)->chunk;
169
+}
170
+
171
+static void audit_tree_destroy_watch(struct fsnotify_mark *mark)
172
+{
173
+ kmem_cache_free(audit_tree_mark_cachep, audit_mark(mark));
174
+}
175
+
176
+static struct fsnotify_mark *alloc_mark(void)
177
+{
178
+ struct audit_tree_mark *amark;
179
+
180
+ amark = kmem_cache_zalloc(audit_tree_mark_cachep, GFP_KERNEL);
181
+ if (!amark)
182
+ return NULL;
183
+ fsnotify_init_mark(&amark->mark, audit_tree_group);
184
+ amark->mark.mask = FS_IN_IGNORED;
185
+ return &amark->mark;
139186 }
140187
141188 static struct audit_chunk *alloc_chunk(int count)
142189 {
143190 struct audit_chunk *chunk;
144
- size_t size;
145191 int i;
146192
147
- size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node);
148
- chunk = kzalloc(size, GFP_KERNEL);
193
+ chunk = kzalloc(struct_size(chunk, owners, count), GFP_KERNEL);
149194 if (!chunk)
150195 return NULL;
151196
....@@ -157,8 +202,6 @@
157202 INIT_LIST_HEAD(&chunk->owners[i].list);
158203 chunk->owners[i].index = i;
159204 }
160
- fsnotify_init_mark(&chunk->mark, audit_tree_group);
161
- chunk->mark.mask = FS_IN_IGNORED;
162205 return chunk;
163206 }
164207
....@@ -179,13 +222,17 @@
179222 return chunk_hash_heads + n % HASH_SIZE;
180223 }
181224
182
-/* hash_lock & entry->lock is held by caller */
225
+/* hash_lock & mark->group->mark_mutex is held by caller */
183226 static void insert_hash(struct audit_chunk *chunk)
184227 {
185228 struct list_head *list;
186229
187
- if (!(chunk->mark.flags & FSNOTIFY_MARK_FLAG_ATTACHED))
188
- return;
230
+ /*
231
+ * Make sure chunk is fully initialized before making it visible in the
232
+ * hash. Pairs with a data dependency barrier in READ_ONCE() in
233
+ * audit_tree_lookup().
234
+ */
235
+ smp_wmb();
189236 WARN_ON_ONCE(!chunk->key);
190237 list = chunk_hash(chunk->key);
191238 list_add_rcu(&chunk->hash, list);
....@@ -199,7 +246,11 @@
199246 struct audit_chunk *p;
200247
201248 list_for_each_entry_rcu(p, list, hash) {
202
- if (p->key == key) {
249
+ /*
250
+ * We use a data dependency barrier in READ_ONCE() to make sure
251
+ * the chunk we see is fully initialized.
252
+ */
253
+ if (READ_ONCE(p->key) == key) {
203254 atomic_long_inc(&p->refs);
204255 return p;
205256 }
....@@ -225,100 +276,56 @@
225276 return container_of(p, struct audit_chunk, owners[0]);
226277 }
227278
228
-static void untag_chunk(struct node *p)
279
+static void replace_mark_chunk(struct fsnotify_mark *mark,
280
+ struct audit_chunk *chunk)
229281 {
230
- struct audit_chunk *chunk = find_chunk(p);
231
- struct fsnotify_mark *entry = &chunk->mark;
232
- struct audit_chunk *new = NULL;
282
+ struct audit_chunk *old;
283
+
284
+ assert_spin_locked(&hash_lock);
285
+ old = mark_chunk(mark);
286
+ audit_mark(mark)->chunk = chunk;
287
+ if (chunk)
288
+ chunk->mark = mark;
289
+ if (old)
290
+ old->mark = NULL;
291
+}
292
+
293
+static void replace_chunk(struct audit_chunk *new, struct audit_chunk *old)
294
+{
233295 struct audit_tree *owner;
234
- int size = chunk->count - 1;
235296 int i, j;
236297
237
- fsnotify_get_mark(entry);
238
-
239
- spin_unlock(&hash_lock);
240
-
241
- if (size)
242
- new = alloc_chunk(size);
243
-
244
- mutex_lock(&entry->group->mark_mutex);
245
- spin_lock(&entry->lock);
246
- /*
247
- * mark_mutex protects mark from getting detached and thus also from
248
- * mark->connector->obj getting NULL.
249
- */
250
- if (chunk->dead || !(entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) {
251
- spin_unlock(&entry->lock);
252
- mutex_unlock(&entry->group->mark_mutex);
253
- if (new)
254
- fsnotify_put_mark(&new->mark);
255
- goto out;
256
- }
257
-
258
- owner = p->owner;
259
-
260
- if (!size) {
261
- chunk->dead = 1;
262
- spin_lock(&hash_lock);
263
- list_del_init(&chunk->trees);
264
- if (owner->root == chunk)
265
- owner->root = NULL;
266
- list_del_init(&p->list);
267
- list_del_rcu(&chunk->hash);
268
- spin_unlock(&hash_lock);
269
- spin_unlock(&entry->lock);
270
- mutex_unlock(&entry->group->mark_mutex);
271
- fsnotify_destroy_mark(entry, audit_tree_group);
272
- goto out;
273
- }
274
-
275
- if (!new)
276
- goto Fallback;
277
-
278
- if (fsnotify_add_mark_locked(&new->mark, entry->connector->obj,
279
- FSNOTIFY_OBJ_TYPE_INODE, 1)) {
280
- fsnotify_put_mark(&new->mark);
281
- goto Fallback;
282
- }
283
-
284
- chunk->dead = 1;
285
- spin_lock(&hash_lock);
286
- new->key = chunk->key;
287
- list_replace_init(&chunk->trees, &new->trees);
288
- if (owner->root == chunk) {
289
- list_del_init(&owner->same_root);
290
- owner->root = NULL;
291
- }
292
-
293
- for (i = j = 0; j <= size; i++, j++) {
294
- struct audit_tree *s;
295
- if (&chunk->owners[j] == p) {
296
- list_del_init(&p->list);
298
+ new->key = old->key;
299
+ list_splice_init(&old->trees, &new->trees);
300
+ list_for_each_entry(owner, &new->trees, same_root)
301
+ owner->root = new;
302
+ for (i = j = 0; j < old->count; i++, j++) {
303
+ if (!old->owners[j].owner) {
297304 i--;
298305 continue;
299306 }
300
- s = chunk->owners[j].owner;
301
- new->owners[i].owner = s;
302
- new->owners[i].index = chunk->owners[j].index - j + i;
303
- if (!s) /* result of earlier fallback */
307
+ owner = old->owners[j].owner;
308
+ new->owners[i].owner = owner;
309
+ new->owners[i].index = old->owners[j].index - j + i;
310
+ if (!owner) /* result of earlier fallback */
304311 continue;
305
- get_tree(s);
306
- list_replace_init(&chunk->owners[j].list, &new->owners[i].list);
312
+ get_tree(owner);
313
+ list_replace_init(&old->owners[j].list, &new->owners[i].list);
307314 }
315
+ replace_mark_chunk(old->mark, new);
316
+ /*
317
+ * Make sure chunk is fully initialized before making it visible in the
318
+ * hash. Pairs with a data dependency barrier in READ_ONCE() in
319
+ * audit_tree_lookup().
320
+ */
321
+ smp_wmb();
322
+ list_replace_rcu(&old->hash, &new->hash);
323
+}
308324
309
- list_replace_rcu(&chunk->hash, &new->hash);
310
- list_for_each_entry(owner, &new->trees, same_root)
311
- owner->root = new;
312
- spin_unlock(&hash_lock);
313
- spin_unlock(&entry->lock);
314
- mutex_unlock(&entry->group->mark_mutex);
315
- fsnotify_destroy_mark(entry, audit_tree_group);
316
- fsnotify_put_mark(&new->mark); /* drop initial reference */
317
- goto out;
325
+static void remove_chunk_node(struct audit_chunk *chunk, struct node *p)
326
+{
327
+ struct audit_tree *owner = p->owner;
318328
319
-Fallback:
320
- // do the best we can
321
- spin_lock(&hash_lock);
322329 if (owner->root == chunk) {
323330 list_del_init(&owner->same_root);
324331 owner->root = NULL;
....@@ -326,37 +333,102 @@
326333 list_del_init(&p->list);
327334 p->owner = NULL;
328335 put_tree(owner);
329
- spin_unlock(&hash_lock);
330
- spin_unlock(&entry->lock);
331
- mutex_unlock(&entry->group->mark_mutex);
332
-out:
333
- fsnotify_put_mark(entry);
334
- spin_lock(&hash_lock);
335336 }
336337
338
+static int chunk_count_trees(struct audit_chunk *chunk)
339
+{
340
+ int i;
341
+ int ret = 0;
342
+
343
+ for (i = 0; i < chunk->count; i++)
344
+ if (chunk->owners[i].owner)
345
+ ret++;
346
+ return ret;
347
+}
348
+
349
+static void untag_chunk(struct audit_chunk *chunk, struct fsnotify_mark *mark)
350
+{
351
+ struct audit_chunk *new;
352
+ int size;
353
+
354
+ mutex_lock(&audit_tree_group->mark_mutex);
355
+ /*
356
+ * mark_mutex stabilizes chunk attached to the mark so we can check
357
+ * whether it didn't change while we've dropped hash_lock.
358
+ */
359
+ if (!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) ||
360
+ mark_chunk(mark) != chunk)
361
+ goto out_mutex;
362
+
363
+ size = chunk_count_trees(chunk);
364
+ if (!size) {
365
+ spin_lock(&hash_lock);
366
+ list_del_init(&chunk->trees);
367
+ list_del_rcu(&chunk->hash);
368
+ replace_mark_chunk(mark, NULL);
369
+ spin_unlock(&hash_lock);
370
+ fsnotify_detach_mark(mark);
371
+ mutex_unlock(&audit_tree_group->mark_mutex);
372
+ audit_mark_put_chunk(chunk);
373
+ fsnotify_free_mark(mark);
374
+ return;
375
+ }
376
+
377
+ new = alloc_chunk(size);
378
+ if (!new)
379
+ goto out_mutex;
380
+
381
+ spin_lock(&hash_lock);
382
+ /*
383
+ * This has to go last when updating chunk as once replace_chunk() is
384
+ * called, new RCU readers can see the new chunk.
385
+ */
386
+ replace_chunk(new, chunk);
387
+ spin_unlock(&hash_lock);
388
+ mutex_unlock(&audit_tree_group->mark_mutex);
389
+ audit_mark_put_chunk(chunk);
390
+ return;
391
+
392
+out_mutex:
393
+ mutex_unlock(&audit_tree_group->mark_mutex);
394
+}
395
+
396
+/* Call with group->mark_mutex held, releases it */
337397 static int create_chunk(struct inode *inode, struct audit_tree *tree)
338398 {
339
- struct fsnotify_mark *entry;
399
+ struct fsnotify_mark *mark;
340400 struct audit_chunk *chunk = alloc_chunk(1);
341
- if (!chunk)
342
- return -ENOMEM;
343401
344
- entry = &chunk->mark;
345
- if (fsnotify_add_inode_mark(entry, inode, 0)) {
346
- fsnotify_put_mark(entry);
402
+ if (!chunk) {
403
+ mutex_unlock(&audit_tree_group->mark_mutex);
404
+ return -ENOMEM;
405
+ }
406
+
407
+ mark = alloc_mark();
408
+ if (!mark) {
409
+ mutex_unlock(&audit_tree_group->mark_mutex);
410
+ kfree(chunk);
411
+ return -ENOMEM;
412
+ }
413
+
414
+ if (fsnotify_add_inode_mark_locked(mark, inode, 0)) {
415
+ mutex_unlock(&audit_tree_group->mark_mutex);
416
+ fsnotify_put_mark(mark);
417
+ kfree(chunk);
347418 return -ENOSPC;
348419 }
349420
350
- spin_lock(&entry->lock);
351421 spin_lock(&hash_lock);
352422 if (tree->goner) {
353423 spin_unlock(&hash_lock);
354
- chunk->dead = 1;
355
- spin_unlock(&entry->lock);
356
- fsnotify_destroy_mark(entry, audit_tree_group);
357
- fsnotify_put_mark(entry);
424
+ fsnotify_detach_mark(mark);
425
+ mutex_unlock(&audit_tree_group->mark_mutex);
426
+ fsnotify_free_mark(mark);
427
+ fsnotify_put_mark(mark);
428
+ kfree(chunk);
358429 return 0;
359430 }
431
+ replace_mark_chunk(mark, chunk);
360432 chunk->owners[0].index = (1U << 31);
361433 chunk->owners[0].owner = tree;
362434 get_tree(tree);
....@@ -366,35 +438,48 @@
366438 list_add(&tree->same_root, &chunk->trees);
367439 }
368440 chunk->key = inode_to_key(inode);
441
+ /*
442
+ * Inserting into the hash table has to go last as once we do that RCU
443
+ * readers can see the chunk.
444
+ */
369445 insert_hash(chunk);
370446 spin_unlock(&hash_lock);
371
- spin_unlock(&entry->lock);
372
- fsnotify_put_mark(entry); /* drop initial reference */
447
+ mutex_unlock(&audit_tree_group->mark_mutex);
448
+ /*
449
+ * Drop our initial reference. When mark we point to is getting freed,
450
+ * we get notification through ->freeing_mark callback and cleanup
451
+ * chunk pointing to this mark.
452
+ */
453
+ fsnotify_put_mark(mark);
373454 return 0;
374455 }
375456
376457 /* the first tagged inode becomes root of tree */
377458 static int tag_chunk(struct inode *inode, struct audit_tree *tree)
378459 {
379
- struct fsnotify_mark *old_entry, *chunk_entry;
380
- struct audit_tree *owner;
460
+ struct fsnotify_mark *mark;
381461 struct audit_chunk *chunk, *old;
382462 struct node *p;
383463 int n;
384464
385
- old_entry = fsnotify_find_mark(&inode->i_fsnotify_marks,
386
- audit_tree_group);
387
- if (!old_entry)
465
+ mutex_lock(&audit_tree_group->mark_mutex);
466
+ mark = fsnotify_find_mark(&inode->i_fsnotify_marks, audit_tree_group);
467
+ if (!mark)
388468 return create_chunk(inode, tree);
389469
390
- old = container_of(old_entry, struct audit_chunk, mark);
391
-
470
+ /*
471
+ * Found mark is guaranteed to be attached and mark_mutex protects mark
472
+ * from getting detached and thus it makes sure there is chunk attached
473
+ * to the mark.
474
+ */
392475 /* are we already there? */
393476 spin_lock(&hash_lock);
477
+ old = mark_chunk(mark);
394478 for (n = 0; n < old->count; n++) {
395479 if (old->owners[n].owner == tree) {
396480 spin_unlock(&hash_lock);
397
- fsnotify_put_mark(old_entry);
481
+ mutex_unlock(&audit_tree_group->mark_mutex);
482
+ fsnotify_put_mark(mark);
398483 return 0;
399484 }
400485 }
....@@ -402,105 +487,59 @@
402487
403488 chunk = alloc_chunk(old->count + 1);
404489 if (!chunk) {
405
- fsnotify_put_mark(old_entry);
490
+ mutex_unlock(&audit_tree_group->mark_mutex);
491
+ fsnotify_put_mark(mark);
406492 return -ENOMEM;
407493 }
408494
409
- chunk_entry = &chunk->mark;
410
-
411
- mutex_lock(&old_entry->group->mark_mutex);
412
- spin_lock(&old_entry->lock);
413
- /*
414
- * mark_mutex protects mark from getting detached and thus also from
415
- * mark->connector->obj getting NULL.
416
- */
417
- if (!(old_entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) {
418
- /* old_entry is being shot, lets just lie */
419
- spin_unlock(&old_entry->lock);
420
- mutex_unlock(&old_entry->group->mark_mutex);
421
- fsnotify_put_mark(old_entry);
422
- fsnotify_put_mark(&chunk->mark);
423
- return -ENOENT;
424
- }
425
-
426
- if (fsnotify_add_mark_locked(chunk_entry, old_entry->connector->obj,
427
- FSNOTIFY_OBJ_TYPE_INODE, 1)) {
428
- spin_unlock(&old_entry->lock);
429
- mutex_unlock(&old_entry->group->mark_mutex);
430
- fsnotify_put_mark(chunk_entry);
431
- fsnotify_put_mark(old_entry);
432
- return -ENOSPC;
433
- }
434
-
435
- /* even though we hold old_entry->lock, this is safe since chunk_entry->lock could NEVER have been grabbed before */
436
- spin_lock(&chunk_entry->lock);
437495 spin_lock(&hash_lock);
438
-
439
- /* we now hold old_entry->lock, chunk_entry->lock, and hash_lock */
440496 if (tree->goner) {
441497 spin_unlock(&hash_lock);
442
- chunk->dead = 1;
443
- spin_unlock(&chunk_entry->lock);
444
- spin_unlock(&old_entry->lock);
445
- mutex_unlock(&old_entry->group->mark_mutex);
446
-
447
- fsnotify_destroy_mark(chunk_entry, audit_tree_group);
448
-
449
- fsnotify_put_mark(chunk_entry);
450
- fsnotify_put_mark(old_entry);
498
+ mutex_unlock(&audit_tree_group->mark_mutex);
499
+ fsnotify_put_mark(mark);
500
+ kfree(chunk);
451501 return 0;
452502 }
453
- chunk->key = old->key;
454
- list_replace_init(&old->trees, &chunk->trees);
455
- for (n = 0, p = chunk->owners; n < old->count; n++, p++) {
456
- struct audit_tree *s = old->owners[n].owner;
457
- p->owner = s;
458
- p->index = old->owners[n].index;
459
- if (!s) /* result of fallback in untag */
460
- continue;
461
- get_tree(s);
462
- list_replace_init(&old->owners[n].list, &p->list);
463
- }
503
+ p = &chunk->owners[chunk->count - 1];
464504 p->index = (chunk->count - 1) | (1U<<31);
465505 p->owner = tree;
466506 get_tree(tree);
467507 list_add(&p->list, &tree->chunks);
468
- list_replace_rcu(&old->hash, &chunk->hash);
469
- list_for_each_entry(owner, &chunk->trees, same_root)
470
- owner->root = chunk;
471
- old->dead = 1;
472508 if (!tree->root) {
473509 tree->root = chunk;
474510 list_add(&tree->same_root, &chunk->trees);
475511 }
512
+ /*
513
+ * This has to go last when updating chunk as once replace_chunk() is
514
+ * called, new RCU readers can see the new chunk.
515
+ */
516
+ replace_chunk(chunk, old);
476517 spin_unlock(&hash_lock);
477
- spin_unlock(&chunk_entry->lock);
478
- spin_unlock(&old_entry->lock);
479
- mutex_unlock(&old_entry->group->mark_mutex);
480
- fsnotify_destroy_mark(old_entry, audit_tree_group);
481
- fsnotify_put_mark(chunk_entry); /* drop initial reference */
482
- fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */
518
+ mutex_unlock(&audit_tree_group->mark_mutex);
519
+ fsnotify_put_mark(mark); /* pair to fsnotify_find_mark */
520
+ audit_mark_put_chunk(old);
521
+
483522 return 0;
484523 }
485524
486
-static void audit_tree_log_remove_rule(struct audit_krule *rule)
525
+static void audit_tree_log_remove_rule(struct audit_context *context,
526
+ struct audit_krule *rule)
487527 {
488528 struct audit_buffer *ab;
489529
490530 if (!audit_enabled)
491531 return;
492
- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
532
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
493533 if (unlikely(!ab))
494534 return;
495
- audit_log_format(ab, "op=remove_rule");
496
- audit_log_format(ab, " dir=");
535
+ audit_log_format(ab, "op=remove_rule dir=");
497536 audit_log_untrustedstring(ab, rule->tree->pathname);
498537 audit_log_key(ab, rule->filterkey);
499538 audit_log_format(ab, " list=%d res=1", rule->listnr);
500539 audit_log_end(ab);
501540 }
502541
503
-static void kill_rules(struct audit_tree *tree)
542
+static void kill_rules(struct audit_context *context, struct audit_tree *tree)
504543 {
505544 struct audit_krule *rule, *next;
506545 struct audit_entry *entry;
....@@ -511,7 +550,7 @@
511550 list_del_init(&rule->rlist);
512551 if (rule->tree) {
513552 /* not a half-baked one */
514
- audit_tree_log_remove_rule(rule);
553
+ audit_tree_log_remove_rule(context, rule);
515554 if (entry->rule.exe)
516555 audit_remove_mark(entry->rule.exe);
517556 rule->tree = NULL;
....@@ -523,19 +562,45 @@
523562 }
524563
525564 /*
526
- * finish killing struct audit_tree
565
+ * Remove tree from chunks. If 'tagged' is set, remove tree only from tagged
566
+ * chunks. The function expects tagged chunks are all at the beginning of the
567
+ * chunks list.
527568 */
528
-static void prune_one(struct audit_tree *victim)
569
+static void prune_tree_chunks(struct audit_tree *victim, bool tagged)
529570 {
530571 spin_lock(&hash_lock);
531572 while (!list_empty(&victim->chunks)) {
532573 struct node *p;
574
+ struct audit_chunk *chunk;
575
+ struct fsnotify_mark *mark;
533576
534
- p = list_entry(victim->chunks.next, struct node, list);
577
+ p = list_first_entry(&victim->chunks, struct node, list);
578
+ /* have we run out of marked? */
579
+ if (tagged && !(p->index & (1U<<31)))
580
+ break;
581
+ chunk = find_chunk(p);
582
+ mark = chunk->mark;
583
+ remove_chunk_node(chunk, p);
584
+ /* Racing with audit_tree_freeing_mark()? */
585
+ if (!mark)
586
+ continue;
587
+ fsnotify_get_mark(mark);
588
+ spin_unlock(&hash_lock);
535589
536
- untag_chunk(p);
590
+ untag_chunk(chunk, mark);
591
+ fsnotify_put_mark(mark);
592
+
593
+ spin_lock(&hash_lock);
537594 }
538595 spin_unlock(&hash_lock);
596
+}
597
+
598
+/*
599
+ * finish killing struct audit_tree
600
+ */
601
+static void prune_one(struct audit_tree *victim)
602
+{
603
+ prune_tree_chunks(victim, false);
539604 put_tree(victim);
540605 }
541606
....@@ -558,23 +623,16 @@
558623 list_add(p, &tree->chunks);
559624 }
560625 }
626
+ spin_unlock(&hash_lock);
561627
562
- while (!list_empty(&tree->chunks)) {
563
- struct node *node;
628
+ prune_tree_chunks(tree, true);
564629
565
- node = list_entry(tree->chunks.next, struct node, list);
566
-
567
- /* have we run out of marked? */
568
- if (!(node->index & (1U<<31)))
569
- break;
570
-
571
- untag_chunk(node);
572
- }
630
+ spin_lock(&hash_lock);
573631 if (!tree->root && !tree->goner) {
574632 tree->goner = 1;
575633 spin_unlock(&hash_lock);
576634 mutex_lock(&audit_filter_mutex);
577
- kill_rules(tree);
635
+ kill_rules(audit_context(), tree);
578636 list_del_init(&tree->list);
579637 mutex_unlock(&audit_filter_mutex);
580638 prune_one(tree);
....@@ -914,8 +972,10 @@
914972 * ... and that one is done if evict_chunk() decides to delay until the end
915973 * of syscall. Runs synchronously.
916974 */
917
-void audit_kill_trees(struct list_head *list)
975
+void audit_kill_trees(struct audit_context *context)
918976 {
977
+ struct list_head *list = &context->killed_trees;
978
+
919979 audit_ctl_lock();
920980 mutex_lock(&audit_filter_mutex);
921981
....@@ -923,7 +983,7 @@
923983 struct audit_tree *victim;
924984
925985 victim = list_entry(list->next, struct audit_tree, list);
926
- kill_rules(victim);
986
+ kill_rules(context, victim);
927987 list_del_init(&victim->list);
928988
929989 mutex_unlock(&audit_filter_mutex);
....@@ -948,10 +1008,6 @@
9481008 int need_prune = 0;
9491009 int n;
9501010
951
- if (chunk->dead)
952
- return;
953
-
954
- chunk->dead = 1;
9551011 mutex_lock(&audit_filter_mutex);
9561012 spin_lock(&hash_lock);
9571013 while (!list_empty(&chunk->trees)) {
....@@ -962,7 +1018,7 @@
9621018 list_del_init(&owner->same_root);
9631019 spin_unlock(&hash_lock);
9641020 if (!postponed) {
965
- kill_rules(owner);
1021
+ kill_rules(audit_context(), owner);
9661022 list_move(&owner->list, &prune_list);
9671023 need_prune = 1;
9681024 } else {
....@@ -979,30 +1035,38 @@
9791035 audit_schedule_prune();
9801036 }
9811037
982
-static int audit_tree_handle_event(struct fsnotify_group *group,
983
- struct inode *to_tell,
984
- u32 mask, const void *data, int data_type,
985
- const unsigned char *file_name, u32 cookie,
986
- struct fsnotify_iter_info *iter_info)
1038
+static int audit_tree_handle_event(struct fsnotify_mark *mark, u32 mask,
1039
+ struct inode *inode, struct inode *dir,
1040
+ const struct qstr *file_name, u32 cookie)
9871041 {
9881042 return 0;
9891043 }
9901044
991
-static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify_group *group)
1045
+static void audit_tree_freeing_mark(struct fsnotify_mark *mark,
1046
+ struct fsnotify_group *group)
9921047 {
993
- struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark);
1048
+ struct audit_chunk *chunk;
9941049
995
- evict_chunk(chunk);
1050
+ mutex_lock(&mark->group->mark_mutex);
1051
+ spin_lock(&hash_lock);
1052
+ chunk = mark_chunk(mark);
1053
+ replace_mark_chunk(mark, NULL);
1054
+ spin_unlock(&hash_lock);
1055
+ mutex_unlock(&mark->group->mark_mutex);
1056
+ if (chunk) {
1057
+ evict_chunk(chunk);
1058
+ audit_mark_put_chunk(chunk);
1059
+ }
9961060
9971061 /*
9981062 * We are guaranteed to have at least one reference to the mark from
9991063 * either the inode or the caller of fsnotify_destroy_mark().
10001064 */
1001
- BUG_ON(refcount_read(&entry->refcnt) < 1);
1065
+ BUG_ON(refcount_read(&mark->refcnt) < 1);
10021066 }
10031067
10041068 static const struct fsnotify_ops audit_tree_ops = {
1005
- .handle_event = audit_tree_handle_event,
1069
+ .handle_inode_event = audit_tree_handle_event,
10061070 .freeing_mark = audit_tree_freeing_mark,
10071071 .free_mark = audit_tree_destroy_watch,
10081072 };
....@@ -1011,6 +1075,8 @@
10111075 {
10121076 int i;
10131077
1078
+ audit_tree_mark_cachep = KMEM_CACHE(audit_tree_mark, SLAB_PANIC);
1079
+
10141080 audit_tree_group = fsnotify_alloc_group(&audit_tree_ops);
10151081 if (IS_ERR(audit_tree_group))
10161082 audit_panic("cannot initialize fsnotify group for rectree watches");