diff options
| -rw-r--r-- | fs/inotify.c | 150 | ||||
| -rw-r--r-- | include/linux/inotify.h | 11 | ||||
| -rw-r--r-- | kernel/audit_tree.c | 91 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 14 |
4 files changed, 218 insertions, 48 deletions
diff --git a/fs/inotify.c b/fs/inotify.c index 690e72595e6e..7bbed1b89825 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
| @@ -106,6 +106,20 @@ void get_inotify_watch(struct inotify_watch *watch) | |||
| 106 | } | 106 | } |
| 107 | EXPORT_SYMBOL_GPL(get_inotify_watch); | 107 | EXPORT_SYMBOL_GPL(get_inotify_watch); |
| 108 | 108 | ||
| 109 | int pin_inotify_watch(struct inotify_watch *watch) | ||
| 110 | { | ||
| 111 | struct super_block *sb = watch->inode->i_sb; | ||
| 112 | spin_lock(&sb_lock); | ||
| 113 | if (sb->s_count >= S_BIAS) { | ||
| 114 | atomic_inc(&sb->s_active); | ||
| 115 | spin_unlock(&sb_lock); | ||
| 116 | atomic_inc(&watch->count); | ||
| 117 | return 1; | ||
| 118 | } | ||
| 119 | spin_unlock(&sb_lock); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 109 | /** | 123 | /** |
| 110 | * put_inotify_watch - decrements the ref count on a given watch. cleans up | 124 | * put_inotify_watch - decrements the ref count on a given watch. cleans up |
| 111 | * watch references if the count reaches zero. inotify_watch is freed by | 125 | * watch references if the count reaches zero. inotify_watch is freed by |
| @@ -124,6 +138,13 @@ void put_inotify_watch(struct inotify_watch *watch) | |||
| 124 | } | 138 | } |
| 125 | EXPORT_SYMBOL_GPL(put_inotify_watch); | 139 | EXPORT_SYMBOL_GPL(put_inotify_watch); |
| 126 | 140 | ||
| 141 | void unpin_inotify_watch(struct inotify_watch *watch) | ||
| 142 | { | ||
| 143 | struct super_block *sb = watch->inode->i_sb; | ||
| 144 | put_inotify_watch(watch); | ||
| 145 | deactivate_super(sb); | ||
| 146 | } | ||
| 147 | |||
| 127 | /* | 148 | /* |
| 128 | * inotify_handle_get_wd - returns the next WD for use by the given handle | 149 | * inotify_handle_get_wd - returns the next WD for use by the given handle |
| 129 | * | 150 | * |
| @@ -479,6 +500,112 @@ void inotify_init_watch(struct inotify_watch *watch) | |||
| 479 | } | 500 | } |
| 480 | EXPORT_SYMBOL_GPL(inotify_init_watch); | 501 | EXPORT_SYMBOL_GPL(inotify_init_watch); |
| 481 | 502 | ||
| 503 | /* | ||
| 504 | * Watch removals suck violently. To kick the watch out we need (in this | ||
| 505 | * order) inode->inotify_mutex and ih->mutex. That's fine if we have | ||
| 506 | * a hold on inode; however, for all other cases we need to make damn sure | ||
| 507 | * we don't race with umount. We can *NOT* just grab a reference to a | ||
| 508 | * watch - inotify_unmount_inodes() will happily sail past it and we'll end | ||
| 509 | * with reference to inode potentially outliving its superblock. Ideally | ||
| 510 | * we just want to grab an active reference to superblock if we can; that | ||
| 511 | * will make sure we won't go into inotify_umount_inodes() until we are | ||
| 512 | * done. Cleanup is just deactivate_super(). However, that leaves a messy | ||
| 513 | * case - what if we *are* racing with umount() and active references to | ||
| 514 | * superblock can't be acquired anymore? We can bump ->s_count, grab | ||
| 515 | * ->s_umount, which will almost certainly wait until the superblock is shut | ||
| 516 | * down and the watch in question is pining for fjords. That's fine, but | ||
| 517 | * there is a problem - we might have hit the window between ->s_active | ||
| 518 | * getting to 0 / ->s_count - below S_BIAS (i.e. the moment when superblock | ||
| 519 | * is past the point of no return and is heading for shutdown) and the | ||
| 520 | * moment when deactivate_super() acquires ->s_umount. We could just do | ||
| 521 | * drop_super() yield() and retry, but that's rather antisocial and this | ||
| 522 | * stuff is luser-triggerable. OTOH, having grabbed ->s_umount and having | ||
| 523 | * found that we'd got there first (i.e. that ->s_root is non-NULL) we know | ||
| 524 | * that we won't race with inotify_umount_inodes(). So we could grab a | ||
| 525 | * reference to watch and do the rest as above, just with drop_super() instead | ||
| 526 | * of deactivate_super(), right? Wrong. We had to drop ih->mutex before we | ||
| 527 | * could grab ->s_umount. So the watch could've been gone already. | ||
| 528 | * | ||
| 529 | * That still can be dealt with - we need to save watch->wd, do idr_find() | ||
| 530 | * and compare its result with our pointer. If they match, we either have | ||
| 531 | * the damn thing still alive or we'd lost not one but two races at once, | ||
| 532 | * the watch had been killed and a new one got created with the same ->wd | ||
| 533 | * at the same address. That couldn't have happened in inotify_destroy(), | ||
| 534 | * but inotify_rm_wd() could run into that. Still, "new one got created" | ||
| 535 | * is not a problem - we have every right to kill it or leave it alone, | ||
| 536 | * whatever's more convenient. | ||
| 537 | * | ||
| 538 | * So we can use idr_find(...) == watch && watch->inode->i_sb == sb as | ||
| 539 | * "grab it and kill it" check. If it's been our original watch, we are | ||
| 540 | * fine, if it's a newcomer - nevermind, just pretend that we'd won the | ||
| 541 | * race and kill the fscker anyway; we are safe since we know that its | ||
| 542 | * superblock won't be going away. | ||
| 543 | * | ||
| 544 | * And yes, this is far beyond mere "not very pretty"; so's the entire | ||
| 545 | * concept of inotify to start with. | ||
| 546 | */ | ||
| 547 | |||
| 548 | /** | ||
| 549 | * pin_to_kill - pin the watch down for removal | ||
| 550 | * @ih: inotify handle | ||
| 551 | * @watch: watch to kill | ||
| 552 | * | ||
| 553 | * Called with ih->mutex held, drops it. Possible return values: | ||
| 554 | * 0 - nothing to do, it has died | ||
| 555 | * 1 - remove it, drop the reference and deactivate_super() | ||
| 556 | * 2 - remove it, drop the reference and drop_super(); we tried hard to avoid | ||
| 557 | * that variant, since it involved a lot of PITA, but that's the best that | ||
| 558 | * could've been done. | ||
| 559 | */ | ||
| 560 | static int pin_to_kill(struct inotify_handle *ih, struct inotify_watch *watch) | ||
| 561 | { | ||
| 562 | struct super_block *sb = watch->inode->i_sb; | ||
| 563 | s32 wd = watch->wd; | ||
| 564 | |||
| 565 | spin_lock(&sb_lock); | ||
| 566 | if (sb->s_count >= S_BIAS) { | ||
| 567 | atomic_inc(&sb->s_active); | ||
| 568 | spin_unlock(&sb_lock); | ||
| 569 | get_inotify_watch(watch); | ||
| 570 | mutex_unlock(&ih->mutex); | ||
| 571 | return 1; /* the best outcome */ | ||
| 572 | } | ||
| 573 | sb->s_count++; | ||
| 574 | spin_unlock(&sb_lock); | ||
| 575 | mutex_unlock(&ih->mutex); /* can't grab ->s_umount under it */ | ||
| 576 | down_read(&sb->s_umount); | ||
| 577 | if (likely(!sb->s_root)) { | ||
| 578 | /* fs is already shut down; the watch is dead */ | ||
| 579 | drop_super(sb); | ||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | /* raced with the final deactivate_super() */ | ||
| 583 | mutex_lock(&ih->mutex); | ||
| 584 | if (idr_find(&ih->idr, wd) != watch || watch->inode->i_sb != sb) { | ||
| 585 | /* the watch is dead */ | ||
| 586 | mutex_unlock(&ih->mutex); | ||
| 587 | drop_super(sb); | ||
| 588 | return 0; | ||
| 589 | } | ||
| 590 | /* still alive or freed and reused with the same sb and wd; kill */ | ||
| 591 | get_inotify_watch(watch); | ||
| 592 | mutex_unlock(&ih->mutex); | ||
| 593 | return 2; | ||
| 594 | } | ||
| 595 | |||
| 596 | static void unpin_and_kill(struct inotify_watch *watch, int how) | ||
| 597 | { | ||
| 598 | struct super_block *sb = watch->inode->i_sb; | ||
| 599 | put_inotify_watch(watch); | ||
| 600 | switch (how) { | ||
| 601 | case 1: | ||
| 602 | deactivate_super(sb); | ||
| 603 | break; | ||
| 604 | case 2: | ||
| 605 | drop_super(sb); | ||
| 606 | } | ||
| 607 | } | ||
| 608 | |||
| 482 | /** | 609 | /** |
| 483 | * inotify_destroy - clean up and destroy an inotify instance | 610 | * inotify_destroy - clean up and destroy an inotify instance |
| 484 | * @ih: inotify handle | 611 | * @ih: inotify handle |
| @@ -490,11 +617,15 @@ void inotify_destroy(struct inotify_handle *ih) | |||
| 490 | * pretty. We cannot do a simple iteration over the list, because we | 617 | * pretty. We cannot do a simple iteration over the list, because we |
| 491 | * do not know the inode until we iterate to the watch. But we need to | 618 | * do not know the inode until we iterate to the watch. But we need to |
| 492 | * hold inode->inotify_mutex before ih->mutex. The following works. | 619 | * hold inode->inotify_mutex before ih->mutex. The following works. |
| 620 | * | ||
| 621 | * AV: it had to become even uglier to start working ;-/ | ||
| 493 | */ | 622 | */ |
| 494 | while (1) { | 623 | while (1) { |
| 495 | struct inotify_watch *watch; | 624 | struct inotify_watch *watch; |
| 496 | struct list_head *watches; | 625 | struct list_head *watches; |
| 626 | struct super_block *sb; | ||
| 497 | struct inode *inode; | 627 | struct inode *inode; |
| 628 | int how; | ||
| 498 | 629 | ||
| 499 | mutex_lock(&ih->mutex); | 630 | mutex_lock(&ih->mutex); |
| 500 | watches = &ih->watches; | 631 | watches = &ih->watches; |
| @@ -503,8 +634,10 @@ void inotify_destroy(struct inotify_handle *ih) | |||
| 503 | break; | 634 | break; |
| 504 | } | 635 | } |
| 505 | watch = list_first_entry(watches, struct inotify_watch, h_list); | 636 | watch = list_first_entry(watches, struct inotify_watch, h_list); |
| 506 | get_inotify_watch(watch); | 637 | sb = watch->inode->i_sb; |
| 507 | mutex_unlock(&ih->mutex); | 638 | how = pin_to_kill(ih, watch); |
| 639 | if (!how) | ||
| 640 | continue; | ||
| 508 | 641 | ||
| 509 | inode = watch->inode; | 642 | inode = watch->inode; |
| 510 | mutex_lock(&inode->inotify_mutex); | 643 | mutex_lock(&inode->inotify_mutex); |
| @@ -518,7 +651,7 @@ void inotify_destroy(struct inotify_handle *ih) | |||
| 518 | 651 | ||
| 519 | mutex_unlock(&ih->mutex); | 652 | mutex_unlock(&ih->mutex); |
| 520 | mutex_unlock(&inode->inotify_mutex); | 653 | mutex_unlock(&inode->inotify_mutex); |
| 521 | put_inotify_watch(watch); | 654 | unpin_and_kill(watch, how); |
| 522 | } | 655 | } |
| 523 | 656 | ||
| 524 | /* free this handle: the put matching the get in inotify_init() */ | 657 | /* free this handle: the put matching the get in inotify_init() */ |
| @@ -719,7 +852,9 @@ void inotify_evict_watch(struct inotify_watch *watch) | |||
| 719 | int inotify_rm_wd(struct inotify_handle *ih, u32 wd) | 852 | int inotify_rm_wd(struct inotify_handle *ih, u32 wd) |
| 720 | { | 853 | { |
| 721 | struct inotify_watch *watch; | 854 | struct inotify_watch *watch; |
| 855 | struct super_block *sb; | ||
| 722 | struct inode *inode; | 856 | struct inode *inode; |
| 857 | int how; | ||
| 723 | 858 | ||
| 724 | mutex_lock(&ih->mutex); | 859 | mutex_lock(&ih->mutex); |
| 725 | watch = idr_find(&ih->idr, wd); | 860 | watch = idr_find(&ih->idr, wd); |
| @@ -727,9 +862,12 @@ int inotify_rm_wd(struct inotify_handle *ih, u32 wd) | |||
| 727 | mutex_unlock(&ih->mutex); | 862 | mutex_unlock(&ih->mutex); |
| 728 | return -EINVAL; | 863 | return -EINVAL; |
| 729 | } | 864 | } |
| 730 | get_inotify_watch(watch); | 865 | sb = watch->inode->i_sb; |
| 866 | how = pin_to_kill(ih, watch); | ||
| 867 | if (!how) | ||
| 868 | return 0; | ||
| 869 | |||
| 731 | inode = watch->inode; | 870 | inode = watch->inode; |
| 732 | mutex_unlock(&ih->mutex); | ||
| 733 | 871 | ||
| 734 | mutex_lock(&inode->inotify_mutex); | 872 | mutex_lock(&inode->inotify_mutex); |
| 735 | mutex_lock(&ih->mutex); | 873 | mutex_lock(&ih->mutex); |
| @@ -740,7 +878,7 @@ int inotify_rm_wd(struct inotify_handle *ih, u32 wd) | |||
| 740 | 878 | ||
| 741 | mutex_unlock(&ih->mutex); | 879 | mutex_unlock(&ih->mutex); |
| 742 | mutex_unlock(&inode->inotify_mutex); | 880 | mutex_unlock(&inode->inotify_mutex); |
| 743 | put_inotify_watch(watch); | 881 | unpin_and_kill(watch, how); |
| 744 | 882 | ||
| 745 | return 0; | 883 | return 0; |
| 746 | } | 884 | } |
diff --git a/include/linux/inotify.h b/include/linux/inotify.h index bd578578a8b9..37ea2894b3c0 100644 --- a/include/linux/inotify.h +++ b/include/linux/inotify.h | |||
| @@ -134,6 +134,8 @@ extern void inotify_remove_watch_locked(struct inotify_handle *, | |||
| 134 | struct inotify_watch *); | 134 | struct inotify_watch *); |
| 135 | extern void get_inotify_watch(struct inotify_watch *); | 135 | extern void get_inotify_watch(struct inotify_watch *); |
| 136 | extern void put_inotify_watch(struct inotify_watch *); | 136 | extern void put_inotify_watch(struct inotify_watch *); |
| 137 | extern int pin_inotify_watch(struct inotify_watch *); | ||
| 138 | extern void unpin_inotify_watch(struct inotify_watch *); | ||
| 137 | 139 | ||
| 138 | #else | 140 | #else |
| 139 | 141 | ||
| @@ -228,6 +230,15 @@ static inline void put_inotify_watch(struct inotify_watch *watch) | |||
| 228 | { | 230 | { |
| 229 | } | 231 | } |
| 230 | 232 | ||
| 233 | extern inline int pin_inotify_watch(struct inotify_watch *watch) | ||
| 234 | { | ||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | extern inline void unpin_inotify_watch(struct inotify_watch *watch) | ||
| 239 | { | ||
| 240 | } | ||
| 241 | |||
| 231 | #endif /* CONFIG_INOTIFY */ | 242 | #endif /* CONFIG_INOTIFY */ |
| 232 | 243 | ||
| 233 | #endif /* __KERNEL __ */ | 244 | #endif /* __KERNEL __ */ |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 8ba0e0d934f2..8b509441f49a 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
| @@ -24,6 +24,7 @@ struct audit_chunk { | |||
| 24 | struct list_head trees; /* with root here */ | 24 | struct list_head trees; /* with root here */ |
| 25 | int dead; | 25 | int dead; |
| 26 | int count; | 26 | int count; |
| 27 | atomic_long_t refs; | ||
| 27 | struct rcu_head head; | 28 | struct rcu_head head; |
| 28 | struct node { | 29 | struct node { |
| 29 | struct list_head list; | 30 | struct list_head list; |
| @@ -56,7 +57,8 @@ static LIST_HEAD(prune_list); | |||
| 56 | * tree is refcounted; one reference for "some rules on rules_list refer to | 57 | * tree is refcounted; one reference for "some rules on rules_list refer to |
| 57 | * it", one for each chunk with pointer to it. | 58 | * it", one for each chunk with pointer to it. |
| 58 | * | 59 | * |
| 59 | * chunk is refcounted by embedded inotify_watch. | 60 | * chunk is refcounted by embedded inotify_watch + .refs (non-zero refcount |
| 61 | * of watch contributes 1 to .refs). | ||
| 60 | * | 62 | * |
| 61 | * node.index allows to get from node.list to containing chunk. | 63 | * node.index allows to get from node.list to containing chunk. |
| 62 | * MSB of that sucker is stolen to mark taggings that we might have to | 64 | * MSB of that sucker is stolen to mark taggings that we might have to |
| @@ -121,6 +123,7 @@ static struct audit_chunk *alloc_chunk(int count) | |||
| 121 | INIT_LIST_HEAD(&chunk->hash); | 123 | INIT_LIST_HEAD(&chunk->hash); |
| 122 | INIT_LIST_HEAD(&chunk->trees); | 124 | INIT_LIST_HEAD(&chunk->trees); |
| 123 | chunk->count = count; | 125 | chunk->count = count; |
| 126 | atomic_long_set(&chunk->refs, 1); | ||
| 124 | for (i = 0; i < count; i++) { | 127 | for (i = 0; i < count; i++) { |
| 125 | INIT_LIST_HEAD(&chunk->owners[i].list); | 128 | INIT_LIST_HEAD(&chunk->owners[i].list); |
| 126 | chunk->owners[i].index = i; | 129 | chunk->owners[i].index = i; |
| @@ -129,9 +132,8 @@ static struct audit_chunk *alloc_chunk(int count) | |||
| 129 | return chunk; | 132 | return chunk; |
| 130 | } | 133 | } |
| 131 | 134 | ||
| 132 | static void __free_chunk(struct rcu_head *rcu) | 135 | static void free_chunk(struct audit_chunk *chunk) |
| 133 | { | 136 | { |
| 134 | struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head); | ||
| 135 | int i; | 137 | int i; |
| 136 | 138 | ||
| 137 | for (i = 0; i < chunk->count; i++) { | 139 | for (i = 0; i < chunk->count; i++) { |
| @@ -141,14 +143,16 @@ static void __free_chunk(struct rcu_head *rcu) | |||
| 141 | kfree(chunk); | 143 | kfree(chunk); |
| 142 | } | 144 | } |
| 143 | 145 | ||
| 144 | static inline void free_chunk(struct audit_chunk *chunk) | 146 | void audit_put_chunk(struct audit_chunk *chunk) |
| 145 | { | 147 | { |
| 146 | call_rcu(&chunk->head, __free_chunk); | 148 | if (atomic_long_dec_and_test(&chunk->refs)) |
| 149 | free_chunk(chunk); | ||
| 147 | } | 150 | } |
| 148 | 151 | ||
| 149 | void audit_put_chunk(struct audit_chunk *chunk) | 152 | static void __put_chunk(struct rcu_head *rcu) |
| 150 | { | 153 | { |
| 151 | put_inotify_watch(&chunk->watch); | 154 | struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head); |
| 155 | audit_put_chunk(chunk); | ||
| 152 | } | 156 | } |
| 153 | 157 | ||
| 154 | enum {HASH_SIZE = 128}; | 158 | enum {HASH_SIZE = 128}; |
| @@ -176,7 +180,7 @@ struct audit_chunk *audit_tree_lookup(const struct inode *inode) | |||
| 176 | 180 | ||
| 177 | list_for_each_entry_rcu(p, list, hash) { | 181 | list_for_each_entry_rcu(p, list, hash) { |
| 178 | if (p->watch.inode == inode) { | 182 | if (p->watch.inode == inode) { |
| 179 | get_inotify_watch(&p->watch); | 183 | atomic_long_inc(&p->refs); |
| 180 | return p; | 184 | return p; |
| 181 | } | 185 | } |
| 182 | } | 186 | } |
| @@ -194,17 +198,49 @@ int audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree) | |||
| 194 | 198 | ||
| 195 | /* tagging and untagging inodes with trees */ | 199 | /* tagging and untagging inodes with trees */ |
| 196 | 200 | ||
| 197 | static void untag_chunk(struct audit_chunk *chunk, struct node *p) | 201 | static struct audit_chunk *find_chunk(struct node *p) |
| 202 | { | ||
| 203 | int index = p->index & ~(1U<<31); | ||
| 204 | p -= index; | ||
| 205 | return container_of(p, struct audit_chunk, owners[0]); | ||
| 206 | } | ||
| 207 | |||
| 208 | static void untag_chunk(struct node *p) | ||
| 198 | { | 209 | { |
| 210 | struct audit_chunk *chunk = find_chunk(p); | ||
| 199 | struct audit_chunk *new; | 211 | struct audit_chunk *new; |
| 200 | struct audit_tree *owner; | 212 | struct audit_tree *owner; |
| 201 | int size = chunk->count - 1; | 213 | int size = chunk->count - 1; |
| 202 | int i, j; | 214 | int i, j; |
| 203 | 215 | ||
| 216 | if (!pin_inotify_watch(&chunk->watch)) { | ||
| 217 | /* | ||
| 218 | * Filesystem is shutting down; all watches are getting | ||
| 219 | * evicted, just take it off the node list for this | ||
| 220 | * tree and let the eviction logics take care of the | ||
| 221 | * rest. | ||
| 222 | */ | ||
| 223 | owner = p->owner; | ||
| 224 | if (owner->root == chunk) { | ||
| 225 | list_del_init(&owner->same_root); | ||
| 226 | owner->root = NULL; | ||
| 227 | } | ||
| 228 | list_del_init(&p->list); | ||
| 229 | p->owner = NULL; | ||
| 230 | put_tree(owner); | ||
| 231 | return; | ||
| 232 | } | ||
| 233 | |||
| 234 | spin_unlock(&hash_lock); | ||
| 235 | |||
| 236 | /* | ||
| 237 | * pin_inotify_watch() succeeded, so the watch won't go away | ||
| 238 | * from under us. | ||
| 239 | */ | ||
| 204 | mutex_lock(&chunk->watch.inode->inotify_mutex); | 240 | mutex_lock(&chunk->watch.inode->inotify_mutex); |
| 205 | if (chunk->dead) { | 241 | if (chunk->dead) { |
| 206 | mutex_unlock(&chunk->watch.inode->inotify_mutex); | 242 | mutex_unlock(&chunk->watch.inode->inotify_mutex); |
| 207 | return; | 243 | goto out; |
| 208 | } | 244 | } |
| 209 | 245 | ||
| 210 | owner = p->owner; | 246 | owner = p->owner; |
| @@ -221,7 +257,7 @@ static void untag_chunk(struct audit_chunk *chunk, struct node *p) | |||
| 221 | inotify_evict_watch(&chunk->watch); | 257 | inotify_evict_watch(&chunk->watch); |
| 222 | mutex_unlock(&chunk->watch.inode->inotify_mutex); | 258 | mutex_unlock(&chunk->watch.inode->inotify_mutex); |
| 223 | put_inotify_watch(&chunk->watch); | 259 | put_inotify_watch(&chunk->watch); |
| 224 | return; | 260 | goto out; |
| 225 | } | 261 | } |
| 226 | 262 | ||
| 227 | new = alloc_chunk(size); | 263 | new = alloc_chunk(size); |
| @@ -263,7 +299,7 @@ static void untag_chunk(struct audit_chunk *chunk, struct node *p) | |||
| 263 | inotify_evict_watch(&chunk->watch); | 299 | inotify_evict_watch(&chunk->watch); |
| 264 | mutex_unlock(&chunk->watch.inode->inotify_mutex); | 300 | mutex_unlock(&chunk->watch.inode->inotify_mutex); |
| 265 | put_inotify_watch(&chunk->watch); | 301 | put_inotify_watch(&chunk->watch); |
| 266 | return; | 302 | goto out; |
| 267 | 303 | ||
| 268 | Fallback: | 304 | Fallback: |
| 269 | // do the best we can | 305 | // do the best we can |
| @@ -277,6 +313,9 @@ Fallback: | |||
| 277 | put_tree(owner); | 313 | put_tree(owner); |
| 278 | spin_unlock(&hash_lock); | 314 | spin_unlock(&hash_lock); |
| 279 | mutex_unlock(&chunk->watch.inode->inotify_mutex); | 315 | mutex_unlock(&chunk->watch.inode->inotify_mutex); |
| 316 | out: | ||
| 317 | unpin_inotify_watch(&chunk->watch); | ||
| 318 | spin_lock(&hash_lock); | ||
| 280 | } | 319 | } |
| 281 | 320 | ||
| 282 | static int create_chunk(struct inode *inode, struct audit_tree *tree) | 321 | static int create_chunk(struct inode *inode, struct audit_tree *tree) |
| @@ -387,13 +426,6 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) | |||
| 387 | return 0; | 426 | return 0; |
| 388 | } | 427 | } |
| 389 | 428 | ||
| 390 | static struct audit_chunk *find_chunk(struct node *p) | ||
| 391 | { | ||
| 392 | int index = p->index & ~(1U<<31); | ||
| 393 | p -= index; | ||
| 394 | return container_of(p, struct audit_chunk, owners[0]); | ||
| 395 | } | ||
| 396 | |||
| 397 | static void kill_rules(struct audit_tree *tree) | 429 | static void kill_rules(struct audit_tree *tree) |
| 398 | { | 430 | { |
| 399 | struct audit_krule *rule, *next; | 431 | struct audit_krule *rule, *next; |
| @@ -431,17 +463,10 @@ static void prune_one(struct audit_tree *victim) | |||
| 431 | spin_lock(&hash_lock); | 463 | spin_lock(&hash_lock); |
| 432 | while (!list_empty(&victim->chunks)) { | 464 | while (!list_empty(&victim->chunks)) { |
| 433 | struct node *p; | 465 | struct node *p; |
| 434 | struct audit_chunk *chunk; | ||
| 435 | 466 | ||
| 436 | p = list_entry(victim->chunks.next, struct node, list); | 467 | p = list_entry(victim->chunks.next, struct node, list); |
| 437 | chunk = find_chunk(p); | ||
| 438 | get_inotify_watch(&chunk->watch); | ||
| 439 | spin_unlock(&hash_lock); | ||
| 440 | |||
| 441 | untag_chunk(chunk, p); | ||
| 442 | 468 | ||
| 443 | put_inotify_watch(&chunk->watch); | 469 | untag_chunk(p); |
| 444 | spin_lock(&hash_lock); | ||
| 445 | } | 470 | } |
| 446 | spin_unlock(&hash_lock); | 471 | spin_unlock(&hash_lock); |
| 447 | put_tree(victim); | 472 | put_tree(victim); |
| @@ -469,7 +494,6 @@ static void trim_marked(struct audit_tree *tree) | |||
| 469 | 494 | ||
| 470 | while (!list_empty(&tree->chunks)) { | 495 | while (!list_empty(&tree->chunks)) { |
| 471 | struct node *node; | 496 | struct node *node; |
| 472 | struct audit_chunk *chunk; | ||
| 473 | 497 | ||
| 474 | node = list_entry(tree->chunks.next, struct node, list); | 498 | node = list_entry(tree->chunks.next, struct node, list); |
| 475 | 499 | ||
| @@ -477,14 +501,7 @@ static void trim_marked(struct audit_tree *tree) | |||
| 477 | if (!(node->index & (1U<<31))) | 501 | if (!(node->index & (1U<<31))) |
| 478 | break; | 502 | break; |
| 479 | 503 | ||
| 480 | chunk = find_chunk(node); | 504 | untag_chunk(node); |
| 481 | get_inotify_watch(&chunk->watch); | ||
| 482 | spin_unlock(&hash_lock); | ||
| 483 | |||
| 484 | untag_chunk(chunk, node); | ||
| 485 | |||
| 486 | put_inotify_watch(&chunk->watch); | ||
| 487 | spin_lock(&hash_lock); | ||
| 488 | } | 505 | } |
| 489 | if (!tree->root && !tree->goner) { | 506 | if (!tree->root && !tree->goner) { |
| 490 | tree->goner = 1; | 507 | tree->goner = 1; |
| @@ -878,7 +895,7 @@ static void handle_event(struct inotify_watch *watch, u32 wd, u32 mask, | |||
| 878 | static void destroy_watch(struct inotify_watch *watch) | 895 | static void destroy_watch(struct inotify_watch *watch) |
| 879 | { | 896 | { |
| 880 | struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch); | 897 | struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch); |
| 881 | free_chunk(chunk); | 898 | call_rcu(&chunk->head, __put_chunk); |
| 882 | } | 899 | } |
| 883 | 900 | ||
| 884 | static const struct inotify_operations rtree_inotify_ops = { | 901 | static const struct inotify_operations rtree_inotify_ops = { |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index b7d354e2b0ef..9fd85a4640a0 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -1094,8 +1094,8 @@ static void audit_inotify_unregister(struct list_head *in_list) | |||
| 1094 | list_for_each_entry_safe(p, n, in_list, ilist) { | 1094 | list_for_each_entry_safe(p, n, in_list, ilist) { |
| 1095 | list_del(&p->ilist); | 1095 | list_del(&p->ilist); |
| 1096 | inotify_rm_watch(audit_ih, &p->wdata); | 1096 | inotify_rm_watch(audit_ih, &p->wdata); |
| 1097 | /* the put matching the get in audit_do_del_rule() */ | 1097 | /* the unpin matching the pin in audit_do_del_rule() */ |
| 1098 | put_inotify_watch(&p->wdata); | 1098 | unpin_inotify_watch(&p->wdata); |
| 1099 | } | 1099 | } |
| 1100 | } | 1100 | } |
| 1101 | 1101 | ||
| @@ -1389,9 +1389,13 @@ static inline int audit_del_rule(struct audit_entry *entry, | |||
| 1389 | /* Put parent on the inotify un-registration | 1389 | /* Put parent on the inotify un-registration |
| 1390 | * list. Grab a reference before releasing | 1390 | * list. Grab a reference before releasing |
| 1391 | * audit_filter_mutex, to be released in | 1391 | * audit_filter_mutex, to be released in |
| 1392 | * audit_inotify_unregister(). */ | 1392 | * audit_inotify_unregister(). |
| 1393 | list_add(&parent->ilist, &inotify_list); | 1393 | * If filesystem is going away, just leave |
| 1394 | get_inotify_watch(&parent->wdata); | 1394 | * the sucker alone, eviction will take |
| 1395 | * care of it. | ||
| 1396 | */ | ||
| 1397 | if (pin_inotify_watch(&parent->wdata)) | ||
| 1398 | list_add(&parent->ilist, &inotify_list); | ||
| 1395 | } | 1399 | } |
| 1396 | } | 1400 | } |
| 1397 | } | 1401 | } |
