Commit 2096f759abcb42200a81d776f597362fd9265024
1 parent
495d6c9c65
Exists in
master
and in
7 other branches
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>
Showing 3 changed files with 37 additions and 39 deletions Side-by-side Diff
fs/dcache.c
... | ... | @@ -2191,6 +2191,30 @@ |
2191 | 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 | 2218 | void d_genocide(struct dentry *root) |
2195 | 2219 | { |
2196 | 2220 | struct dentry *this_parent = root; |
include/linux/fs.h
... | ... | @@ -2126,6 +2126,7 @@ |
2126 | 2126 | |
2127 | 2127 | /* fs/dcache.c -- generic fs support functions */ |
2128 | 2128 | extern int is_subdir(struct dentry *, struct dentry *); |
2129 | +extern int path_is_under(struct path *, struct path *); | |
2129 | 2130 | extern ino_t find_inode_number(struct dentry *, struct qstr *); |
2130 | 2131 | |
2131 | 2132 | #include <linux/err.h> |
kernel/audit_tree.c
... | ... | @@ -603,22 +603,6 @@ |
603 | 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 | 606 | int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) |
623 | 607 | { |
624 | 608 | |
625 | 609 | |
626 | 610 | |
627 | 611 | |
628 | 612 | |
629 | 613 | |
... | ... | @@ -714,29 +698,24 @@ |
714 | 698 | { |
715 | 699 | struct list_head cursor, barrier; |
716 | 700 | int failed = 0; |
717 | - struct path path; | |
701 | + struct path path1, path2; | |
718 | 702 | struct vfsmount *tagged; |
719 | 703 | struct list_head list; |
720 | - struct vfsmount *mnt; | |
721 | - struct dentry *dentry; | |
722 | 704 | int err; |
723 | 705 | |
724 | - err = kern_path(new, 0, &path); | |
706 | + err = kern_path(new, 0, &path2); | |
725 | 707 | if (err) |
726 | 708 | return err; |
727 | - tagged = collect_mounts(&path); | |
728 | - path_put(&path); | |
709 | + tagged = collect_mounts(&path2); | |
710 | + path_put(&path2); | |
729 | 711 | if (!tagged) |
730 | 712 | return -ENOMEM; |
731 | 713 | |
732 | - err = kern_path(old, 0, &path); | |
714 | + err = kern_path(old, 0, &path1); | |
733 | 715 | if (err) { |
734 | 716 | drop_collected_mounts(tagged); |
735 | 717 | return err; |
736 | 718 | } |
737 | - mnt = mntget(path.mnt); | |
738 | - dentry = dget(path.dentry); | |
739 | - path_put(&path); | |
740 | 719 | |
741 | 720 | list_add_tail(&list, &tagged->mnt_list); |
742 | 721 | |
... | ... | @@ -747,6 +726,7 @@ |
747 | 726 | while (cursor.next != &tree_list) { |
748 | 727 | struct audit_tree *tree; |
749 | 728 | struct vfsmount *p; |
729 | + int good_one = 0; | |
750 | 730 | |
751 | 731 | tree = container_of(cursor.next, struct audit_tree, list); |
752 | 732 | get_tree(tree); |
753 | 733 | |
754 | 734 | |
... | ... | @@ -754,23 +734,17 @@ |
754 | 734 | list_add(&cursor, &tree->list); |
755 | 735 | mutex_unlock(&audit_filter_mutex); |
756 | 736 | |
757 | - err = kern_path(tree->pathname, 0, &path); | |
758 | - if (err) { | |
759 | - put_tree(tree); | |
760 | - mutex_lock(&audit_filter_mutex); | |
761 | - continue; | |
737 | + err = kern_path(tree->pathname, 0, &path2); | |
738 | + if (!err) { | |
739 | + good_one = path_is_under(&path1, &path2); | |
740 | + path_put(&path2); | |
762 | 741 | } |
763 | 742 | |
764 | - spin_lock(&vfsmount_lock); | |
765 | - if (!is_under(mnt, dentry, &path)) { | |
766 | - spin_unlock(&vfsmount_lock); | |
767 | - path_put(&path); | |
743 | + if (!good_one) { | |
768 | 744 | put_tree(tree); |
769 | 745 | mutex_lock(&audit_filter_mutex); |
770 | 746 | continue; |
771 | 747 | } |
772 | - spin_unlock(&vfsmount_lock); | |
773 | - path_put(&path); | |
774 | 748 | |
775 | 749 | list_for_each_entry(p, &list, mnt_list) { |
776 | 750 | failed = tag_chunk(p->mnt_root->d_inode, tree); |
... | ... | @@ -820,8 +794,7 @@ |
820 | 794 | list_del(&cursor); |
821 | 795 | list_del(&list); |
822 | 796 | mutex_unlock(&audit_filter_mutex); |
823 | - dput(dentry); | |
824 | - mntput(mnt); | |
797 | + path_put(&path1); | |
825 | 798 | drop_collected_mounts(tagged); |
826 | 799 | return failed; |
827 | 800 | } |