aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/audit_tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/audit_tree.c')
-rw-r--r--kernel/audit_tree.c113
1 files changed, 36 insertions, 77 deletions
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 2451dc6f3282..028e85663f27 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -277,7 +277,7 @@ static void untag_chunk(struct node *p)
277 owner->root = NULL; 277 owner->root = NULL;
278 } 278 }
279 279
280 for (i = j = 0; i < size; i++, j++) { 280 for (i = j = 0; j <= size; i++, j++) {
281 struct audit_tree *s; 281 struct audit_tree *s;
282 if (&chunk->owners[j] == p) { 282 if (&chunk->owners[j] == p) {
283 list_del_init(&p->list); 283 list_del_init(&p->list);
@@ -290,7 +290,7 @@ static void untag_chunk(struct node *p)
290 if (!s) /* result of earlier fallback */ 290 if (!s) /* result of earlier fallback */
291 continue; 291 continue;
292 get_tree(s); 292 get_tree(s);
293 list_replace_init(&chunk->owners[i].list, &new->owners[j].list); 293 list_replace_init(&chunk->owners[j].list, &new->owners[i].list);
294 } 294 }
295 295
296 list_replace_rcu(&chunk->hash, &new->hash); 296 list_replace_rcu(&chunk->hash, &new->hash);
@@ -373,15 +373,17 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
373 for (n = 0; n < old->count; n++) { 373 for (n = 0; n < old->count; n++) {
374 if (old->owners[n].owner == tree) { 374 if (old->owners[n].owner == tree) {
375 spin_unlock(&hash_lock); 375 spin_unlock(&hash_lock);
376 put_inotify_watch(watch); 376 put_inotify_watch(&old->watch);
377 return 0; 377 return 0;
378 } 378 }
379 } 379 }
380 spin_unlock(&hash_lock); 380 spin_unlock(&hash_lock);
381 381
382 chunk = alloc_chunk(old->count + 1); 382 chunk = alloc_chunk(old->count + 1);
383 if (!chunk) 383 if (!chunk) {
384 put_inotify_watch(&old->watch);
384 return -ENOMEM; 385 return -ENOMEM;
386 }
385 387
386 mutex_lock(&inode->inotify_mutex); 388 mutex_lock(&inode->inotify_mutex);
387 if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) { 389 if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) {
@@ -425,7 +427,8 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
425 spin_unlock(&hash_lock); 427 spin_unlock(&hash_lock);
426 inotify_evict_watch(&old->watch); 428 inotify_evict_watch(&old->watch);
427 mutex_unlock(&inode->inotify_mutex); 429 mutex_unlock(&inode->inotify_mutex);
428 put_inotify_watch(&old->watch); 430 put_inotify_watch(&old->watch); /* pair to inotify_find_watch */
431 put_inotify_watch(&old->watch); /* and kill it */
429 return 0; 432 return 0;
430} 433}
431 434
@@ -545,6 +548,11 @@ int audit_remove_tree_rule(struct audit_krule *rule)
545 return 0; 548 return 0;
546} 549}
547 550
551static int compare_root(struct vfsmount *mnt, void *arg)
552{
553 return mnt->mnt_root->d_inode == arg;
554}
555
548void audit_trim_trees(void) 556void audit_trim_trees(void)
549{ 557{
550 struct list_head cursor; 558 struct list_head cursor;
@@ -556,7 +564,6 @@ void audit_trim_trees(void)
556 struct path path; 564 struct path path;
557 struct vfsmount *root_mnt; 565 struct vfsmount *root_mnt;
558 struct node *node; 566 struct node *node;
559 struct list_head list;
560 int err; 567 int err;
561 568
562 tree = container_of(cursor.next, struct audit_tree, list); 569 tree = container_of(cursor.next, struct audit_tree, list);
@@ -574,24 +581,16 @@ void audit_trim_trees(void)
574 if (!root_mnt) 581 if (!root_mnt)
575 goto skip_it; 582 goto skip_it;
576 583
577 list_add_tail(&list, &root_mnt->mnt_list);
578 spin_lock(&hash_lock); 584 spin_lock(&hash_lock);
579 list_for_each_entry(node, &tree->chunks, list) { 585 list_for_each_entry(node, &tree->chunks, list) {
580 struct audit_chunk *chunk = find_chunk(node); 586 struct inode *inode = find_chunk(node)->watch.inode;
581 struct inode *inode = chunk->watch.inode;
582 struct vfsmount *mnt;
583 node->index |= 1U<<31; 587 node->index |= 1U<<31;
584 list_for_each_entry(mnt, &list, mnt_list) { 588 if (iterate_mounts(compare_root, inode, root_mnt))
585 if (mnt->mnt_root->d_inode == inode) { 589 node->index &= ~(1U<<31);
586 node->index &= ~(1U<<31);
587 break;
588 }
589 }
590 } 590 }
591 spin_unlock(&hash_lock); 591 spin_unlock(&hash_lock);
592 trim_marked(tree); 592 trim_marked(tree);
593 put_tree(tree); 593 put_tree(tree);
594 list_del_init(&list);
595 drop_collected_mounts(root_mnt); 594 drop_collected_mounts(root_mnt);
596skip_it: 595skip_it:
597 mutex_lock(&audit_filter_mutex); 596 mutex_lock(&audit_filter_mutex);
@@ -600,22 +599,6 @@ skip_it:
600 mutex_unlock(&audit_filter_mutex); 599 mutex_unlock(&audit_filter_mutex);
601} 600}
602 601
603static int is_under(struct vfsmount *mnt, struct dentry *dentry,
604 struct path *path)
605{
606 if (mnt != path->mnt) {
607 for (;;) {
608 if (mnt->mnt_parent == mnt)
609 return 0;
610 if (mnt->mnt_parent == path->mnt)
611 break;
612 mnt = mnt->mnt_parent;
613 }
614 dentry = mnt->mnt_mountpoint;
615 }
616 return is_subdir(dentry, path->dentry);
617}
618
619int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) 602int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
620{ 603{
621 604
@@ -635,13 +618,17 @@ void audit_put_tree(struct audit_tree *tree)
635 put_tree(tree); 618 put_tree(tree);
636} 619}
637 620
621static int tag_mount(struct vfsmount *mnt, void *arg)
622{
623 return tag_chunk(mnt->mnt_root->d_inode, arg);
624}
625
638/* called with audit_filter_mutex */ 626/* called with audit_filter_mutex */
639int audit_add_tree_rule(struct audit_krule *rule) 627int audit_add_tree_rule(struct audit_krule *rule)
640{ 628{
641 struct audit_tree *seed = rule->tree, *tree; 629 struct audit_tree *seed = rule->tree, *tree;
642 struct path path; 630 struct path path;
643 struct vfsmount *mnt, *p; 631 struct vfsmount *mnt;
644 struct list_head list;
645 int err; 632 int err;
646 633
647 list_for_each_entry(tree, &tree_list, list) { 634 list_for_each_entry(tree, &tree_list, list) {
@@ -667,16 +654,9 @@ int audit_add_tree_rule(struct audit_krule *rule)
667 err = -ENOMEM; 654 err = -ENOMEM;
668 goto Err; 655 goto Err;
669 } 656 }
670 list_add_tail(&list, &mnt->mnt_list);
671 657
672 get_tree(tree); 658 get_tree(tree);
673 list_for_each_entry(p, &list, mnt_list) { 659 err = iterate_mounts(tag_mount, tree, mnt);
674 err = tag_chunk(p->mnt_root->d_inode, tree);
675 if (err)
676 break;
677 }
678
679 list_del(&list);
680 drop_collected_mounts(mnt); 660 drop_collected_mounts(mnt);
681 661
682 if (!err) { 662 if (!err) {
@@ -711,31 +691,23 @@ int audit_tag_tree(char *old, char *new)
711{ 691{
712 struct list_head cursor, barrier; 692 struct list_head cursor, barrier;
713 int failed = 0; 693 int failed = 0;
714 struct path path; 694 struct path path1, path2;
715 struct vfsmount *tagged; 695 struct vfsmount *tagged;
716 struct list_head list;
717 struct vfsmount *mnt;
718 struct dentry *dentry;
719 int err; 696 int err;
720 697
721 err = kern_path(new, 0, &path); 698 err = kern_path(new, 0, &path2);
722 if (err) 699 if (err)
723 return err; 700 return err;
724 tagged = collect_mounts(&path); 701 tagged = collect_mounts(&path2);
725 path_put(&path); 702 path_put(&path2);
726 if (!tagged) 703 if (!tagged)
727 return -ENOMEM; 704 return -ENOMEM;
728 705
729 err = kern_path(old, 0, &path); 706 err = kern_path(old, 0, &path1);
730 if (err) { 707 if (err) {
731 drop_collected_mounts(tagged); 708 drop_collected_mounts(tagged);
732 return err; 709 return err;
733 } 710 }
734 mnt = mntget(path.mnt);
735 dentry = dget(path.dentry);
736 path_put(&path);
737
738 list_add_tail(&list, &tagged->mnt_list);
739 711
740 mutex_lock(&audit_filter_mutex); 712 mutex_lock(&audit_filter_mutex);
741 list_add(&barrier, &tree_list); 713 list_add(&barrier, &tree_list);
@@ -743,7 +715,7 @@ int audit_tag_tree(char *old, char *new)
743 715
744 while (cursor.next != &tree_list) { 716 while (cursor.next != &tree_list) {
745 struct audit_tree *tree; 717 struct audit_tree *tree;
746 struct vfsmount *p; 718 int good_one = 0;
747 719
748 tree = container_of(cursor.next, struct audit_tree, list); 720 tree = container_of(cursor.next, struct audit_tree, list);
749 get_tree(tree); 721 get_tree(tree);
@@ -751,30 +723,19 @@ int audit_tag_tree(char *old, char *new)
751 list_add(&cursor, &tree->list); 723 list_add(&cursor, &tree->list);
752 mutex_unlock(&audit_filter_mutex); 724 mutex_unlock(&audit_filter_mutex);
753 725
754 err = kern_path(tree->pathname, 0, &path); 726 err = kern_path(tree->pathname, 0, &path2);
755 if (err) { 727 if (!err) {
756 put_tree(tree); 728 good_one = path_is_under(&path1, &path2);
757 mutex_lock(&audit_filter_mutex); 729 path_put(&path2);
758 continue;
759 } 730 }
760 731
761 spin_lock(&vfsmount_lock); 732 if (!good_one) {
762 if (!is_under(mnt, dentry, &path)) {
763 spin_unlock(&vfsmount_lock);
764 path_put(&path);
765 put_tree(tree); 733 put_tree(tree);
766 mutex_lock(&audit_filter_mutex); 734 mutex_lock(&audit_filter_mutex);
767 continue; 735 continue;
768 } 736 }
769 spin_unlock(&vfsmount_lock);
770 path_put(&path);
771
772 list_for_each_entry(p, &list, mnt_list) {
773 failed = tag_chunk(p->mnt_root->d_inode, tree);
774 if (failed)
775 break;
776 }
777 737
738 failed = iterate_mounts(tag_mount, tree, tagged);
778 if (failed) { 739 if (failed) {
779 put_tree(tree); 740 put_tree(tree);
780 mutex_lock(&audit_filter_mutex); 741 mutex_lock(&audit_filter_mutex);
@@ -815,10 +776,8 @@ int audit_tag_tree(char *old, char *new)
815 } 776 }
816 list_del(&barrier); 777 list_del(&barrier);
817 list_del(&cursor); 778 list_del(&cursor);
818 list_del(&list);
819 mutex_unlock(&audit_filter_mutex); 779 mutex_unlock(&audit_filter_mutex);
820 dput(dentry); 780 path_put(&path1);
821 mntput(mnt);
822 drop_collected_mounts(tagged); 781 drop_collected_mounts(tagged);
823 return failed; 782 return failed;
824} 783}