diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/namespace.c | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 7953c96a2071..6324dfc80dc6 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -155,15 +155,15 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) | |||
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) | 158 | static void detach_mnt(struct vfsmount *mnt, struct path *old_path) |
159 | { | 159 | { |
160 | old_nd->path.dentry = mnt->mnt_mountpoint; | 160 | old_path->dentry = mnt->mnt_mountpoint; |
161 | old_nd->path.mnt = mnt->mnt_parent; | 161 | old_path->mnt = mnt->mnt_parent; |
162 | mnt->mnt_parent = mnt; | 162 | mnt->mnt_parent = mnt; |
163 | mnt->mnt_mountpoint = mnt->mnt_root; | 163 | mnt->mnt_mountpoint = mnt->mnt_root; |
164 | list_del_init(&mnt->mnt_child); | 164 | list_del_init(&mnt->mnt_child); |
165 | list_del_init(&mnt->mnt_hash); | 165 | list_del_init(&mnt->mnt_hash); |
166 | old_nd->path.dentry->d_mounted--; | 166 | old_path->dentry->d_mounted--; |
167 | } | 167 | } |
168 | 168 | ||
169 | void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, | 169 | void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, |
@@ -174,12 +174,12 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, | |||
174 | dentry->d_mounted++; | 174 | dentry->d_mounted++; |
175 | } | 175 | } |
176 | 176 | ||
177 | static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) | 177 | static void attach_mnt(struct vfsmount *mnt, struct path *path) |
178 | { | 178 | { |
179 | mnt_set_mountpoint(nd->path.mnt, nd->path.dentry, mnt); | 179 | mnt_set_mountpoint(path->mnt, path->dentry, mnt); |
180 | list_add_tail(&mnt->mnt_hash, mount_hashtable + | 180 | list_add_tail(&mnt->mnt_hash, mount_hashtable + |
181 | hash(nd->path.mnt, nd->path.dentry)); | 181 | hash(path->mnt, path->dentry)); |
182 | list_add_tail(&mnt->mnt_child, &nd->path.mnt->mnt_mounts); | 182 | list_add_tail(&mnt->mnt_child, &path->mnt->mnt_mounts); |
183 | } | 183 | } |
184 | 184 | ||
185 | /* | 185 | /* |
@@ -744,7 +744,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, | |||
744 | int flag) | 744 | int flag) |
745 | { | 745 | { |
746 | struct vfsmount *res, *p, *q, *r, *s; | 746 | struct vfsmount *res, *p, *q, *r, *s; |
747 | struct nameidata nd; | 747 | struct path path; |
748 | 748 | ||
749 | if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) | 749 | if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) |
750 | return NULL; | 750 | return NULL; |
@@ -769,14 +769,14 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, | |||
769 | q = q->mnt_parent; | 769 | q = q->mnt_parent; |
770 | } | 770 | } |
771 | p = s; | 771 | p = s; |
772 | nd.path.mnt = q; | 772 | path.mnt = q; |
773 | nd.path.dentry = p->mnt_mountpoint; | 773 | path.dentry = p->mnt_mountpoint; |
774 | q = clone_mnt(p, p->mnt_root, flag); | 774 | q = clone_mnt(p, p->mnt_root, flag); |
775 | if (!q) | 775 | if (!q) |
776 | goto Enomem; | 776 | goto Enomem; |
777 | spin_lock(&vfsmount_lock); | 777 | spin_lock(&vfsmount_lock); |
778 | list_add_tail(&q->mnt_list, &res->mnt_list); | 778 | list_add_tail(&q->mnt_list, &res->mnt_list); |
779 | attach_mnt(q, &nd); | 779 | attach_mnt(q, &path); |
780 | spin_unlock(&vfsmount_lock); | 780 | spin_unlock(&vfsmount_lock); |
781 | } | 781 | } |
782 | } | 782 | } |
@@ -876,11 +876,11 @@ void drop_collected_mounts(struct vfsmount *mnt) | |||
876 | * in allocations. | 876 | * in allocations. |
877 | */ | 877 | */ |
878 | static int attach_recursive_mnt(struct vfsmount *source_mnt, | 878 | static int attach_recursive_mnt(struct vfsmount *source_mnt, |
879 | struct nameidata *nd, struct nameidata *parent_nd) | 879 | struct path *path, struct path *parent_path) |
880 | { | 880 | { |
881 | LIST_HEAD(tree_list); | 881 | LIST_HEAD(tree_list); |
882 | struct vfsmount *dest_mnt = nd->path.mnt; | 882 | struct vfsmount *dest_mnt = path->mnt; |
883 | struct dentry *dest_dentry = nd->path.dentry; | 883 | struct dentry *dest_dentry = path->dentry; |
884 | struct vfsmount *child, *p; | 884 | struct vfsmount *child, *p; |
885 | 885 | ||
886 | if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) | 886 | if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) |
@@ -892,9 +892,9 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, | |||
892 | } | 892 | } |
893 | 893 | ||
894 | spin_lock(&vfsmount_lock); | 894 | spin_lock(&vfsmount_lock); |
895 | if (parent_nd) { | 895 | if (parent_path) { |
896 | detach_mnt(source_mnt, parent_nd); | 896 | detach_mnt(source_mnt, parent_path); |
897 | attach_mnt(source_mnt, nd); | 897 | attach_mnt(source_mnt, path); |
898 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 898 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
899 | } else { | 899 | } else { |
900 | mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); | 900 | mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); |
@@ -930,7 +930,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) | |||
930 | 930 | ||
931 | err = -ENOENT; | 931 | err = -ENOENT; |
932 | if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry)) | 932 | if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry)) |
933 | err = attach_recursive_mnt(mnt, nd, NULL); | 933 | err = attach_recursive_mnt(mnt, &nd->path, NULL); |
934 | out_unlock: | 934 | out_unlock: |
935 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); | 935 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); |
936 | if (!err) | 936 | if (!err) |
@@ -1059,7 +1059,8 @@ static inline int tree_contains_unbindable(struct vfsmount *mnt) | |||
1059 | */ | 1059 | */ |
1060 | static noinline int do_move_mount(struct nameidata *nd, char *old_name) | 1060 | static noinline int do_move_mount(struct nameidata *nd, char *old_name) |
1061 | { | 1061 | { |
1062 | struct nameidata old_nd, parent_nd; | 1062 | struct nameidata old_nd; |
1063 | struct path parent_path; | ||
1063 | struct vfsmount *p; | 1064 | struct vfsmount *p; |
1064 | int err = 0; | 1065 | int err = 0; |
1065 | if (!capable(CAP_SYS_ADMIN)) | 1066 | if (!capable(CAP_SYS_ADMIN)) |
@@ -1114,7 +1115,7 @@ static noinline int do_move_mount(struct nameidata *nd, char *old_name) | |||
1114 | if (p == old_nd.path.mnt) | 1115 | if (p == old_nd.path.mnt) |
1115 | goto out1; | 1116 | goto out1; |
1116 | 1117 | ||
1117 | err = attach_recursive_mnt(old_nd.path.mnt, nd, &parent_nd); | 1118 | err = attach_recursive_mnt(old_nd.path.mnt, &nd->path, &parent_path); |
1118 | if (err) | 1119 | if (err) |
1119 | goto out1; | 1120 | goto out1; |
1120 | 1121 | ||
@@ -1128,7 +1129,7 @@ out1: | |||
1128 | out: | 1129 | out: |
1129 | up_write(&namespace_sem); | 1130 | up_write(&namespace_sem); |
1130 | if (!err) | 1131 | if (!err) |
1131 | path_put(&parent_nd.path); | 1132 | path_put(&parent_path); |
1132 | path_put(&old_nd.path); | 1133 | path_put(&old_nd.path); |
1133 | return err; | 1134 | return err; |
1134 | } | 1135 | } |
@@ -1683,7 +1684,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path) | |||
1683 | path_put(&old_pwd); | 1684 | path_put(&old_pwd); |
1684 | } | 1685 | } |
1685 | 1686 | ||
1686 | static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) | 1687 | static void chroot_fs_refs(struct path *old_root, struct path *new_root) |
1687 | { | 1688 | { |
1688 | struct task_struct *g, *p; | 1689 | struct task_struct *g, *p; |
1689 | struct fs_struct *fs; | 1690 | struct fs_struct *fs; |
@@ -1695,12 +1696,12 @@ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) | |||
1695 | if (fs) { | 1696 | if (fs) { |
1696 | atomic_inc(&fs->count); | 1697 | atomic_inc(&fs->count); |
1697 | task_unlock(p); | 1698 | task_unlock(p); |
1698 | if (fs->root.dentry == old_nd->path.dentry | 1699 | if (fs->root.dentry == old_root->dentry |
1699 | && fs->root.mnt == old_nd->path.mnt) | 1700 | && fs->root.mnt == old_root->mnt) |
1700 | set_fs_root(fs, &new_nd->path); | 1701 | set_fs_root(fs, new_root); |
1701 | if (fs->pwd.dentry == old_nd->path.dentry | 1702 | if (fs->pwd.dentry == old_root->dentry |
1702 | && fs->pwd.mnt == old_nd->path.mnt) | 1703 | && fs->pwd.mnt == old_root->mnt) |
1703 | set_fs_pwd(fs, &new_nd->path); | 1704 | set_fs_pwd(fs, new_root); |
1704 | put_fs_struct(fs); | 1705 | put_fs_struct(fs); |
1705 | } else | 1706 | } else |
1706 | task_unlock(p); | 1707 | task_unlock(p); |
@@ -1737,7 +1738,8 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1737 | const char __user * put_old) | 1738 | const char __user * put_old) |
1738 | { | 1739 | { |
1739 | struct vfsmount *tmp; | 1740 | struct vfsmount *tmp; |
1740 | struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; | 1741 | struct nameidata new_nd, old_nd, user_nd; |
1742 | struct path parent_path, root_parent; | ||
1741 | int error; | 1743 | int error; |
1742 | 1744 | ||
1743 | if (!capable(CAP_SYS_ADMIN)) | 1745 | if (!capable(CAP_SYS_ADMIN)) |
@@ -1811,19 +1813,19 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1811 | goto out3; | 1813 | goto out3; |
1812 | } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry)) | 1814 | } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry)) |
1813 | goto out3; | 1815 | goto out3; |
1814 | detach_mnt(new_nd.path.mnt, &parent_nd); | 1816 | detach_mnt(new_nd.path.mnt, &parent_path); |
1815 | detach_mnt(user_nd.path.mnt, &root_parent); | 1817 | detach_mnt(user_nd.path.mnt, &root_parent); |
1816 | /* mount old root on put_old */ | 1818 | /* mount old root on put_old */ |
1817 | attach_mnt(user_nd.path.mnt, &old_nd); | 1819 | attach_mnt(user_nd.path.mnt, &old_nd.path); |
1818 | /* mount new_root on / */ | 1820 | /* mount new_root on / */ |
1819 | attach_mnt(new_nd.path.mnt, &root_parent); | 1821 | attach_mnt(new_nd.path.mnt, &root_parent); |
1820 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 1822 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
1821 | spin_unlock(&vfsmount_lock); | 1823 | spin_unlock(&vfsmount_lock); |
1822 | chroot_fs_refs(&user_nd, &new_nd); | 1824 | chroot_fs_refs(&user_nd.path, &new_nd.path); |
1823 | security_sb_post_pivotroot(&user_nd, &new_nd); | 1825 | security_sb_post_pivotroot(&user_nd, &new_nd); |
1824 | error = 0; | 1826 | error = 0; |
1825 | path_put(&root_parent.path); | 1827 | path_put(&root_parent); |
1826 | path_put(&parent_nd.path); | 1828 | path_put(&parent_path); |
1827 | out2: | 1829 | out2: |
1828 | mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); | 1830 | mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); |
1829 | up_write(&namespace_sem); | 1831 | up_write(&namespace_sem); |