diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 66 |
1 files changed, 32 insertions, 34 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 678f7ce060f2..1bf302d0478b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1091,20 +1091,20 @@ Enomem: | |||
1091 | struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry) | 1091 | struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry) |
1092 | { | 1092 | { |
1093 | struct vfsmount *tree; | 1093 | struct vfsmount *tree; |
1094 | down_read(&namespace_sem); | 1094 | down_write(&namespace_sem); |
1095 | tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE); | 1095 | tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE); |
1096 | up_read(&namespace_sem); | 1096 | up_write(&namespace_sem); |
1097 | return tree; | 1097 | return tree; |
1098 | } | 1098 | } |
1099 | 1099 | ||
1100 | void drop_collected_mounts(struct vfsmount *mnt) | 1100 | void drop_collected_mounts(struct vfsmount *mnt) |
1101 | { | 1101 | { |
1102 | LIST_HEAD(umount_list); | 1102 | LIST_HEAD(umount_list); |
1103 | down_read(&namespace_sem); | 1103 | down_write(&namespace_sem); |
1104 | spin_lock(&vfsmount_lock); | 1104 | spin_lock(&vfsmount_lock); |
1105 | umount_tree(mnt, 0, &umount_list); | 1105 | umount_tree(mnt, 0, &umount_list); |
1106 | spin_unlock(&vfsmount_lock); | 1106 | spin_unlock(&vfsmount_lock); |
1107 | up_read(&namespace_sem); | 1107 | up_write(&namespace_sem); |
1108 | release_mounts(&umount_list); | 1108 | release_mounts(&umount_list); |
1109 | } | 1109 | } |
1110 | 1110 | ||
@@ -1205,32 +1205,32 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, | |||
1205 | return 0; | 1205 | return 0; |
1206 | } | 1206 | } |
1207 | 1207 | ||
1208 | static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) | 1208 | static int graft_tree(struct vfsmount *mnt, struct path *path) |
1209 | { | 1209 | { |
1210 | int err; | 1210 | int err; |
1211 | if (mnt->mnt_sb->s_flags & MS_NOUSER) | 1211 | if (mnt->mnt_sb->s_flags & MS_NOUSER) |
1212 | return -EINVAL; | 1212 | return -EINVAL; |
1213 | 1213 | ||
1214 | if (S_ISDIR(nd->path.dentry->d_inode->i_mode) != | 1214 | if (S_ISDIR(path->dentry->d_inode->i_mode) != |
1215 | S_ISDIR(mnt->mnt_root->d_inode->i_mode)) | 1215 | S_ISDIR(mnt->mnt_root->d_inode->i_mode)) |
1216 | return -ENOTDIR; | 1216 | return -ENOTDIR; |
1217 | 1217 | ||
1218 | err = -ENOENT; | 1218 | err = -ENOENT; |
1219 | mutex_lock(&nd->path.dentry->d_inode->i_mutex); | 1219 | mutex_lock(&path->dentry->d_inode->i_mutex); |
1220 | if (IS_DEADDIR(nd->path.dentry->d_inode)) | 1220 | if (IS_DEADDIR(path->dentry->d_inode)) |
1221 | goto out_unlock; | 1221 | goto out_unlock; |
1222 | 1222 | ||
1223 | err = security_sb_check_sb(mnt, nd); | 1223 | err = security_sb_check_sb(mnt, path); |
1224 | if (err) | 1224 | if (err) |
1225 | goto out_unlock; | 1225 | goto out_unlock; |
1226 | 1226 | ||
1227 | err = -ENOENT; | 1227 | err = -ENOENT; |
1228 | if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry)) | 1228 | if (IS_ROOT(path->dentry) || !d_unhashed(path->dentry)) |
1229 | err = attach_recursive_mnt(mnt, &nd->path, NULL); | 1229 | err = attach_recursive_mnt(mnt, path, NULL); |
1230 | out_unlock: | 1230 | out_unlock: |
1231 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); | 1231 | mutex_unlock(&path->dentry->d_inode->i_mutex); |
1232 | if (!err) | 1232 | if (!err) |
1233 | security_sb_post_addmount(mnt, nd); | 1233 | security_sb_post_addmount(mnt, path); |
1234 | return err; | 1234 | return err; |
1235 | } | 1235 | } |
1236 | 1236 | ||
@@ -1294,7 +1294,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name, | |||
1294 | if (!mnt) | 1294 | if (!mnt) |
1295 | goto out; | 1295 | goto out; |
1296 | 1296 | ||
1297 | err = graft_tree(mnt, nd); | 1297 | err = graft_tree(mnt, &nd->path); |
1298 | if (err) { | 1298 | if (err) { |
1299 | LIST_HEAD(umount_list); | 1299 | LIST_HEAD(umount_list); |
1300 | spin_lock(&vfsmount_lock); | 1300 | spin_lock(&vfsmount_lock); |
@@ -1501,7 +1501,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, | |||
1501 | goto unlock; | 1501 | goto unlock; |
1502 | 1502 | ||
1503 | newmnt->mnt_flags = mnt_flags; | 1503 | newmnt->mnt_flags = mnt_flags; |
1504 | if ((err = graft_tree(newmnt, nd))) | 1504 | if ((err = graft_tree(newmnt, &nd->path))) |
1505 | goto unlock; | 1505 | goto unlock; |
1506 | 1506 | ||
1507 | if (fslist) /* add to the specified expiration list */ | 1507 | if (fslist) /* add to the specified expiration list */ |
@@ -1746,7 +1746,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, | |||
1746 | if (retval) | 1746 | if (retval) |
1747 | return retval; | 1747 | return retval; |
1748 | 1748 | ||
1749 | retval = security_sb_mount(dev_name, &nd, type_page, flags, data_page); | 1749 | retval = security_sb_mount(dev_name, &nd.path, |
1750 | type_page, flags, data_page); | ||
1750 | if (retval) | 1751 | if (retval) |
1751 | goto dput_out; | 1752 | goto dput_out; |
1752 | 1753 | ||
@@ -1986,15 +1987,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1986 | const char __user * put_old) | 1987 | const char __user * put_old) |
1987 | { | 1988 | { |
1988 | struct vfsmount *tmp; | 1989 | struct vfsmount *tmp; |
1989 | struct nameidata new_nd, old_nd, user_nd; | 1990 | struct nameidata new_nd, old_nd; |
1990 | struct path parent_path, root_parent; | 1991 | struct path parent_path, root_parent, root; |
1991 | int error; | 1992 | int error; |
1992 | 1993 | ||
1993 | if (!capable(CAP_SYS_ADMIN)) | 1994 | if (!capable(CAP_SYS_ADMIN)) |
1994 | return -EPERM; | 1995 | return -EPERM; |
1995 | 1996 | ||
1996 | lock_kernel(); | ||
1997 | |||
1998 | error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, | 1997 | error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, |
1999 | &new_nd); | 1998 | &new_nd); |
2000 | if (error) | 1999 | if (error) |
@@ -2007,14 +2006,14 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
2007 | if (error) | 2006 | if (error) |
2008 | goto out1; | 2007 | goto out1; |
2009 | 2008 | ||
2010 | error = security_sb_pivotroot(&old_nd, &new_nd); | 2009 | error = security_sb_pivotroot(&old_nd.path, &new_nd.path); |
2011 | if (error) { | 2010 | if (error) { |
2012 | path_put(&old_nd.path); | 2011 | path_put(&old_nd.path); |
2013 | goto out1; | 2012 | goto out1; |
2014 | } | 2013 | } |
2015 | 2014 | ||
2016 | read_lock(¤t->fs->lock); | 2015 | read_lock(¤t->fs->lock); |
2017 | user_nd.path = current->fs->root; | 2016 | root = current->fs->root; |
2018 | path_get(¤t->fs->root); | 2017 | path_get(¤t->fs->root); |
2019 | read_unlock(¤t->fs->lock); | 2018 | read_unlock(¤t->fs->lock); |
2020 | down_write(&namespace_sem); | 2019 | down_write(&namespace_sem); |
@@ -2022,9 +2021,9 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
2022 | error = -EINVAL; | 2021 | error = -EINVAL; |
2023 | if (IS_MNT_SHARED(old_nd.path.mnt) || | 2022 | if (IS_MNT_SHARED(old_nd.path.mnt) || |
2024 | IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) || | 2023 | IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) || |
2025 | IS_MNT_SHARED(user_nd.path.mnt->mnt_parent)) | 2024 | IS_MNT_SHARED(root.mnt->mnt_parent)) |
2026 | goto out2; | 2025 | goto out2; |
2027 | if (!check_mnt(user_nd.path.mnt)) | 2026 | if (!check_mnt(root.mnt)) |
2028 | goto out2; | 2027 | goto out2; |
2029 | error = -ENOENT; | 2028 | error = -ENOENT; |
2030 | if (IS_DEADDIR(new_nd.path.dentry->d_inode)) | 2029 | if (IS_DEADDIR(new_nd.path.dentry->d_inode)) |
@@ -2034,13 +2033,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
2034 | if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry)) | 2033 | if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry)) |
2035 | goto out2; | 2034 | goto out2; |
2036 | error = -EBUSY; | 2035 | error = -EBUSY; |
2037 | if (new_nd.path.mnt == user_nd.path.mnt || | 2036 | if (new_nd.path.mnt == root.mnt || |
2038 | old_nd.path.mnt == user_nd.path.mnt) | 2037 | old_nd.path.mnt == root.mnt) |
2039 | goto out2; /* loop, on the same file system */ | 2038 | goto out2; /* loop, on the same file system */ |
2040 | error = -EINVAL; | 2039 | error = -EINVAL; |
2041 | if (user_nd.path.mnt->mnt_root != user_nd.path.dentry) | 2040 | if (root.mnt->mnt_root != root.dentry) |
2042 | goto out2; /* not a mountpoint */ | 2041 | goto out2; /* not a mountpoint */ |
2043 | if (user_nd.path.mnt->mnt_parent == user_nd.path.mnt) | 2042 | if (root.mnt->mnt_parent == root.mnt) |
2044 | goto out2; /* not attached */ | 2043 | goto out2; /* not attached */ |
2045 | if (new_nd.path.mnt->mnt_root != new_nd.path.dentry) | 2044 | if (new_nd.path.mnt->mnt_root != new_nd.path.dentry) |
2046 | goto out2; /* not a mountpoint */ | 2045 | goto out2; /* not a mountpoint */ |
@@ -2062,27 +2061,26 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
2062 | } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry)) | 2061 | } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry)) |
2063 | goto out3; | 2062 | goto out3; |
2064 | detach_mnt(new_nd.path.mnt, &parent_path); | 2063 | detach_mnt(new_nd.path.mnt, &parent_path); |
2065 | detach_mnt(user_nd.path.mnt, &root_parent); | 2064 | detach_mnt(root.mnt, &root_parent); |
2066 | /* mount old root on put_old */ | 2065 | /* mount old root on put_old */ |
2067 | attach_mnt(user_nd.path.mnt, &old_nd.path); | 2066 | attach_mnt(root.mnt, &old_nd.path); |
2068 | /* mount new_root on / */ | 2067 | /* mount new_root on / */ |
2069 | attach_mnt(new_nd.path.mnt, &root_parent); | 2068 | attach_mnt(new_nd.path.mnt, &root_parent); |
2070 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 2069 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
2071 | spin_unlock(&vfsmount_lock); | 2070 | spin_unlock(&vfsmount_lock); |
2072 | chroot_fs_refs(&user_nd.path, &new_nd.path); | 2071 | chroot_fs_refs(&root, &new_nd.path); |
2073 | security_sb_post_pivotroot(&user_nd, &new_nd); | 2072 | security_sb_post_pivotroot(&root, &new_nd.path); |
2074 | error = 0; | 2073 | error = 0; |
2075 | path_put(&root_parent); | 2074 | path_put(&root_parent); |
2076 | path_put(&parent_path); | 2075 | path_put(&parent_path); |
2077 | out2: | 2076 | out2: |
2078 | mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); | 2077 | mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); |
2079 | up_write(&namespace_sem); | 2078 | up_write(&namespace_sem); |
2080 | path_put(&user_nd.path); | 2079 | path_put(&root); |
2081 | path_put(&old_nd.path); | 2080 | path_put(&old_nd.path); |
2082 | out1: | 2081 | out1: |
2083 | path_put(&new_nd.path); | 2082 | path_put(&new_nd.path); |
2084 | out0: | 2083 | out0: |
2085 | unlock_kernel(); | ||
2086 | return error; | 2084 | return error; |
2087 | out3: | 2085 | out3: |
2088 | spin_unlock(&vfsmount_lock); | 2086 | spin_unlock(&vfsmount_lock); |