diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-01-30 22:51:25 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-03-03 14:07:57 -0500 |
commit | 1f707137b55764740981d022d29c622832a61880 (patch) | |
tree | af5f72ea7df1afbc1f3b5bb53a3ab3d8ebaae1e0 | |
parent | 462d60577a997aa87c935ae4521bd303733a9f2b (diff) |
new helper: iterate_mounts()
apply function to vfsmounts in set returned by collect_mounts(),
stop if it returns non-zero.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/namespace.c | 15 | ||||
-rw-r--r-- | include/linux/fs.h | 3 | ||||
-rw-r--r-- | kernel/audit_tree.c | 49 |
3 files changed, 33 insertions, 34 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index d25d4602ab50..d5906c19e08e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1246,6 +1246,21 @@ void drop_collected_mounts(struct vfsmount *mnt) | |||
1246 | release_mounts(&umount_list); | 1246 | release_mounts(&umount_list); |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, | ||
1250 | struct vfsmount *root) | ||
1251 | { | ||
1252 | struct vfsmount *mnt; | ||
1253 | int res = f(root, arg); | ||
1254 | if (res) | ||
1255 | return res; | ||
1256 | list_for_each_entry(mnt, &root->mnt_list, mnt_list) { | ||
1257 | res = f(mnt, arg); | ||
1258 | if (res) | ||
1259 | return res; | ||
1260 | } | ||
1261 | return 0; | ||
1262 | } | ||
1263 | |||
1249 | static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) | 1264 | static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) |
1250 | { | 1265 | { |
1251 | struct vfsmount *p; | 1266 | struct vfsmount *p; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 8d53bc17f93f..e764f247d0ab 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1794,7 +1794,8 @@ extern int may_umount(struct vfsmount *); | |||
1794 | extern long do_mount(char *, char *, char *, unsigned long, void *); | 1794 | extern long do_mount(char *, char *, char *, unsigned long, void *); |
1795 | extern struct vfsmount *collect_mounts(struct path *); | 1795 | extern struct vfsmount *collect_mounts(struct path *); |
1796 | extern void drop_collected_mounts(struct vfsmount *); | 1796 | extern void drop_collected_mounts(struct vfsmount *); |
1797 | 1797 | extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *, | |
1798 | struct vfsmount *); | ||
1798 | extern int vfs_statfs(struct dentry *, struct kstatfs *); | 1799 | extern int vfs_statfs(struct dentry *, struct kstatfs *); |
1799 | 1800 | ||
1800 | extern int current_umask(void); | 1801 | extern int current_umask(void); |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index f09b42d9c32d..028e85663f27 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
@@ -548,6 +548,11 @@ int audit_remove_tree_rule(struct audit_krule *rule) | |||
548 | return 0; | 548 | return 0; |
549 | } | 549 | } |
550 | 550 | ||
551 | static int compare_root(struct vfsmount *mnt, void *arg) | ||
552 | { | ||
553 | return mnt->mnt_root->d_inode == arg; | ||
554 | } | ||
555 | |||
551 | void audit_trim_trees(void) | 556 | void audit_trim_trees(void) |
552 | { | 557 | { |
553 | struct list_head cursor; | 558 | struct list_head cursor; |
@@ -559,7 +564,6 @@ void audit_trim_trees(void) | |||
559 | struct path path; | 564 | struct path path; |
560 | struct vfsmount *root_mnt; | 565 | struct vfsmount *root_mnt; |
561 | struct node *node; | 566 | struct node *node; |
562 | struct list_head list; | ||
563 | int err; | 567 | int err; |
564 | 568 | ||
565 | tree = container_of(cursor.next, struct audit_tree, list); | 569 | tree = container_of(cursor.next, struct audit_tree, list); |
@@ -577,24 +581,16 @@ void audit_trim_trees(void) | |||
577 | if (!root_mnt) | 581 | if (!root_mnt) |
578 | goto skip_it; | 582 | goto skip_it; |
579 | 583 | ||
580 | list_add_tail(&list, &root_mnt->mnt_list); | ||
581 | spin_lock(&hash_lock); | 584 | spin_lock(&hash_lock); |
582 | list_for_each_entry(node, &tree->chunks, list) { | 585 | list_for_each_entry(node, &tree->chunks, list) { |
583 | struct audit_chunk *chunk = find_chunk(node); | 586 | struct inode *inode = find_chunk(node)->watch.inode; |
584 | struct inode *inode = chunk->watch.inode; | ||
585 | struct vfsmount *mnt; | ||
586 | node->index |= 1U<<31; | 587 | node->index |= 1U<<31; |
587 | list_for_each_entry(mnt, &list, mnt_list) { | 588 | if (iterate_mounts(compare_root, inode, root_mnt)) |
588 | if (mnt->mnt_root->d_inode == inode) { | 589 | node->index &= ~(1U<<31); |
589 | node->index &= ~(1U<<31); | ||
590 | break; | ||
591 | } | ||
592 | } | ||
593 | } | 590 | } |
594 | spin_unlock(&hash_lock); | 591 | spin_unlock(&hash_lock); |
595 | trim_marked(tree); | 592 | trim_marked(tree); |
596 | put_tree(tree); | 593 | put_tree(tree); |
597 | list_del_init(&list); | ||
598 | drop_collected_mounts(root_mnt); | 594 | drop_collected_mounts(root_mnt); |
599 | skip_it: | 595 | skip_it: |
600 | mutex_lock(&audit_filter_mutex); | 596 | mutex_lock(&audit_filter_mutex); |
@@ -622,13 +618,17 @@ void audit_put_tree(struct audit_tree *tree) | |||
622 | put_tree(tree); | 618 | put_tree(tree); |
623 | } | 619 | } |
624 | 620 | ||
621 | static int tag_mount(struct vfsmount *mnt, void *arg) | ||
622 | { | ||
623 | return tag_chunk(mnt->mnt_root->d_inode, arg); | ||
624 | } | ||
625 | |||
625 | /* called with audit_filter_mutex */ | 626 | /* called with audit_filter_mutex */ |
626 | int audit_add_tree_rule(struct audit_krule *rule) | 627 | int audit_add_tree_rule(struct audit_krule *rule) |
627 | { | 628 | { |
628 | struct audit_tree *seed = rule->tree, *tree; | 629 | struct audit_tree *seed = rule->tree, *tree; |
629 | struct path path; | 630 | struct path path; |
630 | struct vfsmount *mnt, *p; | 631 | struct vfsmount *mnt; |
631 | struct list_head list; | ||
632 | int err; | 632 | int err; |
633 | 633 | ||
634 | list_for_each_entry(tree, &tree_list, list) { | 634 | list_for_each_entry(tree, &tree_list, list) { |
@@ -654,16 +654,9 @@ int audit_add_tree_rule(struct audit_krule *rule) | |||
654 | err = -ENOMEM; | 654 | err = -ENOMEM; |
655 | goto Err; | 655 | goto Err; |
656 | } | 656 | } |
657 | list_add_tail(&list, &mnt->mnt_list); | ||
658 | 657 | ||
659 | get_tree(tree); | 658 | get_tree(tree); |
660 | list_for_each_entry(p, &list, mnt_list) { | 659 | err = iterate_mounts(tag_mount, tree, mnt); |
661 | err = tag_chunk(p->mnt_root->d_inode, tree); | ||
662 | if (err) | ||
663 | break; | ||
664 | } | ||
665 | |||
666 | list_del(&list); | ||
667 | drop_collected_mounts(mnt); | 660 | drop_collected_mounts(mnt); |
668 | 661 | ||
669 | if (!err) { | 662 | if (!err) { |
@@ -700,7 +693,6 @@ int audit_tag_tree(char *old, char *new) | |||
700 | int failed = 0; | 693 | int failed = 0; |
701 | struct path path1, path2; | 694 | struct path path1, path2; |
702 | struct vfsmount *tagged; | 695 | struct vfsmount *tagged; |
703 | struct list_head list; | ||
704 | int err; | 696 | int err; |
705 | 697 | ||
706 | err = kern_path(new, 0, &path2); | 698 | err = kern_path(new, 0, &path2); |
@@ -717,15 +709,12 @@ int audit_tag_tree(char *old, char *new) | |||
717 | return err; | 709 | return err; |
718 | } | 710 | } |
719 | 711 | ||
720 | list_add_tail(&list, &tagged->mnt_list); | ||
721 | |||
722 | mutex_lock(&audit_filter_mutex); | 712 | mutex_lock(&audit_filter_mutex); |
723 | list_add(&barrier, &tree_list); | 713 | list_add(&barrier, &tree_list); |
724 | list_add(&cursor, &barrier); | 714 | list_add(&cursor, &barrier); |
725 | 715 | ||
726 | while (cursor.next != &tree_list) { | 716 | while (cursor.next != &tree_list) { |
727 | struct audit_tree *tree; | 717 | struct audit_tree *tree; |
728 | struct vfsmount *p; | ||
729 | int good_one = 0; | 718 | int good_one = 0; |
730 | 719 | ||
731 | tree = container_of(cursor.next, struct audit_tree, list); | 720 | tree = container_of(cursor.next, struct audit_tree, list); |
@@ -746,12 +735,7 @@ int audit_tag_tree(char *old, char *new) | |||
746 | continue; | 735 | continue; |
747 | } | 736 | } |
748 | 737 | ||
749 | list_for_each_entry(p, &list, mnt_list) { | 738 | failed = iterate_mounts(tag_mount, tree, tagged); |
750 | failed = tag_chunk(p->mnt_root->d_inode, tree); | ||
751 | if (failed) | ||
752 | break; | ||
753 | } | ||
754 | |||
755 | if (failed) { | 739 | if (failed) { |
756 | put_tree(tree); | 740 | put_tree(tree); |
757 | mutex_lock(&audit_filter_mutex); | 741 | mutex_lock(&audit_filter_mutex); |
@@ -792,7 +776,6 @@ int audit_tag_tree(char *old, char *new) | |||
792 | } | 776 | } |
793 | list_del(&barrier); | 777 | list_del(&barrier); |
794 | list_del(&cursor); | 778 | list_del(&cursor); |
795 | list_del(&list); | ||
796 | mutex_unlock(&audit_filter_mutex); | 779 | mutex_unlock(&audit_filter_mutex); |
797 | path_put(&path1); | 780 | path_put(&path1); |
798 | drop_collected_mounts(tagged); | 781 | drop_collected_mounts(tagged); |