diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-01-30 13:16:21 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-03-03 14:07:55 -0500 |
commit | 2096f759abcb42200a81d776f597362fd9265024 (patch) | |
tree | f0784653a50713f9f91f39e24c40abacbfbb6427 | |
parent | 495d6c9c6595ec7b37910dfd42634839431d21fd (diff) |
New helper: path_is_under(path1, path2)
Analog of is_subdir for vfsmount,dentry pairs, moved from audit_tree.c
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/dcache.c | 24 | ||||
-rw-r--r-- | include/linux/fs.h | 1 | ||||
-rw-r--r-- | kernel/audit_tree.c | 51 |
3 files changed, 37 insertions, 39 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 4365998b8df4..74da947b160b 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -2191,6 +2191,30 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry) | |||
2191 | return result; | 2191 | return result; |
2192 | } | 2192 | } |
2193 | 2193 | ||
2194 | int path_is_under(struct path *path1, struct path *path2) | ||
2195 | { | ||
2196 | struct vfsmount *mnt = path1->mnt; | ||
2197 | struct dentry *dentry = path1->dentry; | ||
2198 | int res; | ||
2199 | spin_lock(&vfsmount_lock); | ||
2200 | if (mnt != path2->mnt) { | ||
2201 | for (;;) { | ||
2202 | if (mnt->mnt_parent == mnt) { | ||
2203 | spin_unlock(&vfsmount_lock); | ||
2204 | return 0; | ||
2205 | } | ||
2206 | if (mnt->mnt_parent == path2->mnt) | ||
2207 | break; | ||
2208 | mnt = mnt->mnt_parent; | ||
2209 | } | ||
2210 | dentry = mnt->mnt_mountpoint; | ||
2211 | } | ||
2212 | res = is_subdir(dentry, path2->dentry); | ||
2213 | spin_unlock(&vfsmount_lock); | ||
2214 | return res; | ||
2215 | } | ||
2216 | EXPORT_SYMBOL(path_is_under); | ||
2217 | |||
2194 | void d_genocide(struct dentry *root) | 2218 | void d_genocide(struct dentry *root) |
2195 | { | 2219 | { |
2196 | struct dentry *this_parent = root; | 2220 | struct dentry *this_parent = root; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index d443c9dd3caa..8d53bc17f93f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2126,6 +2126,7 @@ extern struct file * open_exec(const char *); | |||
2126 | 2126 | ||
2127 | /* fs/dcache.c -- generic fs support functions */ | 2127 | /* fs/dcache.c -- generic fs support functions */ |
2128 | extern int is_subdir(struct dentry *, struct dentry *); | 2128 | extern int is_subdir(struct dentry *, struct dentry *); |
2129 | extern int path_is_under(struct path *, struct path *); | ||
2129 | extern ino_t find_inode_number(struct dentry *, struct qstr *); | 2130 | extern ino_t find_inode_number(struct dentry *, struct qstr *); |
2130 | 2131 | ||
2131 | #include <linux/err.h> | 2132 | #include <linux/err.h> |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 4b05bd9479db..f09b42d9c32d 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
@@ -603,22 +603,6 @@ skip_it: | |||
603 | mutex_unlock(&audit_filter_mutex); | 603 | mutex_unlock(&audit_filter_mutex); |
604 | } | 604 | } |
605 | 605 | ||
606 | static int is_under(struct vfsmount *mnt, struct dentry *dentry, | ||
607 | struct path *path) | ||
608 | { | ||
609 | if (mnt != path->mnt) { | ||
610 | for (;;) { | ||
611 | if (mnt->mnt_parent == mnt) | ||
612 | return 0; | ||
613 | if (mnt->mnt_parent == path->mnt) | ||
614 | break; | ||
615 | mnt = mnt->mnt_parent; | ||
616 | } | ||
617 | dentry = mnt->mnt_mountpoint; | ||
618 | } | ||
619 | return is_subdir(dentry, path->dentry); | ||
620 | } | ||
621 | |||
622 | int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) | 606 | int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) |
623 | { | 607 | { |
624 | 608 | ||
@@ -714,29 +698,24 @@ int audit_tag_tree(char *old, char *new) | |||
714 | { | 698 | { |
715 | struct list_head cursor, barrier; | 699 | struct list_head cursor, barrier; |
716 | int failed = 0; | 700 | int failed = 0; |
717 | struct path path; | 701 | struct path path1, path2; |
718 | struct vfsmount *tagged; | 702 | struct vfsmount *tagged; |
719 | struct list_head list; | 703 | struct list_head list; |
720 | struct vfsmount *mnt; | ||
721 | struct dentry *dentry; | ||
722 | int err; | 704 | int err; |
723 | 705 | ||
724 | err = kern_path(new, 0, &path); | 706 | err = kern_path(new, 0, &path2); |
725 | if (err) | 707 | if (err) |
726 | return err; | 708 | return err; |
727 | tagged = collect_mounts(&path); | 709 | tagged = collect_mounts(&path2); |
728 | path_put(&path); | 710 | path_put(&path2); |
729 | if (!tagged) | 711 | if (!tagged) |
730 | return -ENOMEM; | 712 | return -ENOMEM; |
731 | 713 | ||
732 | err = kern_path(old, 0, &path); | 714 | err = kern_path(old, 0, &path1); |
733 | if (err) { | 715 | if (err) { |
734 | drop_collected_mounts(tagged); | 716 | drop_collected_mounts(tagged); |
735 | return err; | 717 | return err; |
736 | } | 718 | } |
737 | mnt = mntget(path.mnt); | ||
738 | dentry = dget(path.dentry); | ||
739 | path_put(&path); | ||
740 | 719 | ||
741 | list_add_tail(&list, &tagged->mnt_list); | 720 | list_add_tail(&list, &tagged->mnt_list); |
742 | 721 | ||
@@ -747,6 +726,7 @@ int audit_tag_tree(char *old, char *new) | |||
747 | while (cursor.next != &tree_list) { | 726 | while (cursor.next != &tree_list) { |
748 | struct audit_tree *tree; | 727 | struct audit_tree *tree; |
749 | struct vfsmount *p; | 728 | struct vfsmount *p; |
729 | int good_one = 0; | ||
750 | 730 | ||
751 | tree = container_of(cursor.next, struct audit_tree, list); | 731 | tree = container_of(cursor.next, struct audit_tree, list); |
752 | get_tree(tree); | 732 | get_tree(tree); |
@@ -754,23 +734,17 @@ int audit_tag_tree(char *old, char *new) | |||
754 | list_add(&cursor, &tree->list); | 734 | list_add(&cursor, &tree->list); |
755 | mutex_unlock(&audit_filter_mutex); | 735 | mutex_unlock(&audit_filter_mutex); |
756 | 736 | ||
757 | err = kern_path(tree->pathname, 0, &path); | 737 | err = kern_path(tree->pathname, 0, &path2); |
758 | if (err) { | 738 | if (!err) { |
759 | put_tree(tree); | 739 | good_one = path_is_under(&path1, &path2); |
760 | mutex_lock(&audit_filter_mutex); | 740 | path_put(&path2); |
761 | continue; | ||
762 | } | 741 | } |
763 | 742 | ||
764 | spin_lock(&vfsmount_lock); | 743 | if (!good_one) { |
765 | if (!is_under(mnt, dentry, &path)) { | ||
766 | spin_unlock(&vfsmount_lock); | ||
767 | path_put(&path); | ||
768 | put_tree(tree); | 744 | put_tree(tree); |
769 | mutex_lock(&audit_filter_mutex); | 745 | mutex_lock(&audit_filter_mutex); |
770 | continue; | 746 | continue; |
771 | } | 747 | } |
772 | spin_unlock(&vfsmount_lock); | ||
773 | path_put(&path); | ||
774 | 748 | ||
775 | list_for_each_entry(p, &list, mnt_list) { | 749 | list_for_each_entry(p, &list, mnt_list) { |
776 | failed = tag_chunk(p->mnt_root->d_inode, tree); | 750 | failed = tag_chunk(p->mnt_root->d_inode, tree); |
@@ -820,8 +794,7 @@ int audit_tag_tree(char *old, char *new) | |||
820 | list_del(&cursor); | 794 | list_del(&cursor); |
821 | list_del(&list); | 795 | list_del(&list); |
822 | mutex_unlock(&audit_filter_mutex); | 796 | mutex_unlock(&audit_filter_mutex); |
823 | dput(dentry); | 797 | path_put(&path1); |
824 | mntput(mnt); | ||
825 | drop_collected_mounts(tagged); | 798 | drop_collected_mounts(tagged); |
826 | return failed; | 799 | return failed; |
827 | } | 800 | } |