diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 53 |
1 files changed, 25 insertions, 28 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 87d2d82010bb..1bf302d0478b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -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->path); | 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->path); | 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 */ |
@@ -1987,15 +1987,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1987 | const char __user * put_old) | 1987 | const char __user * put_old) |
1988 | { | 1988 | { |
1989 | struct vfsmount *tmp; | 1989 | struct vfsmount *tmp; |
1990 | struct nameidata new_nd, old_nd, user_nd; | 1990 | struct nameidata new_nd, old_nd; |
1991 | struct path parent_path, root_parent; | 1991 | struct path parent_path, root_parent, root; |
1992 | int error; | 1992 | int error; |
1993 | 1993 | ||
1994 | if (!capable(CAP_SYS_ADMIN)) | 1994 | if (!capable(CAP_SYS_ADMIN)) |
1995 | return -EPERM; | 1995 | return -EPERM; |
1996 | 1996 | ||
1997 | lock_kernel(); | ||
1998 | |||
1999 | error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, | 1997 | error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, |
2000 | &new_nd); | 1998 | &new_nd); |
2001 | if (error) | 1999 | if (error) |
@@ -2015,7 +2013,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
2015 | } | 2013 | } |
2016 | 2014 | ||
2017 | read_lock(¤t->fs->lock); | 2015 | read_lock(¤t->fs->lock); |
2018 | user_nd.path = current->fs->root; | 2016 | root = current->fs->root; |
2019 | path_get(¤t->fs->root); | 2017 | path_get(¤t->fs->root); |
2020 | read_unlock(¤t->fs->lock); | 2018 | read_unlock(¤t->fs->lock); |
2021 | down_write(&namespace_sem); | 2019 | down_write(&namespace_sem); |
@@ -2023,9 +2021,9 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
2023 | error = -EINVAL; | 2021 | error = -EINVAL; |
2024 | if (IS_MNT_SHARED(old_nd.path.mnt) || | 2022 | if (IS_MNT_SHARED(old_nd.path.mnt) || |
2025 | IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) || | 2023 | IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) || |
2026 | IS_MNT_SHARED(user_nd.path.mnt->mnt_parent)) | 2024 | IS_MNT_SHARED(root.mnt->mnt_parent)) |
2027 | goto out2; | 2025 | goto out2; |
2028 | if (!check_mnt(user_nd.path.mnt)) | 2026 | if (!check_mnt(root.mnt)) |
2029 | goto out2; | 2027 | goto out2; |
2030 | error = -ENOENT; | 2028 | error = -ENOENT; |
2031 | if (IS_DEADDIR(new_nd.path.dentry->d_inode)) | 2029 | if (IS_DEADDIR(new_nd.path.dentry->d_inode)) |
@@ -2035,13 +2033,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
2035 | 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)) |
2036 | goto out2; | 2034 | goto out2; |
2037 | error = -EBUSY; | 2035 | error = -EBUSY; |
2038 | if (new_nd.path.mnt == user_nd.path.mnt || | 2036 | if (new_nd.path.mnt == root.mnt || |
2039 | old_nd.path.mnt == user_nd.path.mnt) | 2037 | old_nd.path.mnt == root.mnt) |
2040 | goto out2; /* loop, on the same file system */ | 2038 | goto out2; /* loop, on the same file system */ |
2041 | error = -EINVAL; | 2039 | error = -EINVAL; |
2042 | if (user_nd.path.mnt->mnt_root != user_nd.path.dentry) | 2040 | if (root.mnt->mnt_root != root.dentry) |
2043 | goto out2; /* not a mountpoint */ | 2041 | goto out2; /* not a mountpoint */ |
2044 | if (user_nd.path.mnt->mnt_parent == user_nd.path.mnt) | 2042 | if (root.mnt->mnt_parent == root.mnt) |
2045 | goto out2; /* not attached */ | 2043 | goto out2; /* not attached */ |
2046 | if (new_nd.path.mnt->mnt_root != new_nd.path.dentry) | 2044 | if (new_nd.path.mnt->mnt_root != new_nd.path.dentry) |
2047 | goto out2; /* not a mountpoint */ | 2045 | goto out2; /* not a mountpoint */ |
@@ -2063,27 +2061,26 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
2063 | } 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)) |
2064 | goto out3; | 2062 | goto out3; |
2065 | detach_mnt(new_nd.path.mnt, &parent_path); | 2063 | detach_mnt(new_nd.path.mnt, &parent_path); |
2066 | detach_mnt(user_nd.path.mnt, &root_parent); | 2064 | detach_mnt(root.mnt, &root_parent); |
2067 | /* mount old root on put_old */ | 2065 | /* mount old root on put_old */ |
2068 | attach_mnt(user_nd.path.mnt, &old_nd.path); | 2066 | attach_mnt(root.mnt, &old_nd.path); |
2069 | /* mount new_root on / */ | 2067 | /* mount new_root on / */ |
2070 | attach_mnt(new_nd.path.mnt, &root_parent); | 2068 | attach_mnt(new_nd.path.mnt, &root_parent); |
2071 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 2069 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
2072 | spin_unlock(&vfsmount_lock); | 2070 | spin_unlock(&vfsmount_lock); |
2073 | chroot_fs_refs(&user_nd.path, &new_nd.path); | 2071 | chroot_fs_refs(&root, &new_nd.path); |
2074 | security_sb_post_pivotroot(&user_nd.path, &new_nd.path); | 2072 | security_sb_post_pivotroot(&root, &new_nd.path); |
2075 | error = 0; | 2073 | error = 0; |
2076 | path_put(&root_parent); | 2074 | path_put(&root_parent); |
2077 | path_put(&parent_path); | 2075 | path_put(&parent_path); |
2078 | out2: | 2076 | out2: |
2079 | mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); | 2077 | mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); |
2080 | up_write(&namespace_sem); | 2078 | up_write(&namespace_sem); |
2081 | path_put(&user_nd.path); | 2079 | path_put(&root); |
2082 | path_put(&old_nd.path); | 2080 | path_put(&old_nd.path); |
2083 | out1: | 2081 | out1: |
2084 | path_put(&new_nd.path); | 2082 | path_put(&new_nd.path); |
2085 | out0: | 2083 | out0: |
2086 | unlock_kernel(); | ||
2087 | return error; | 2084 | return error; |
2088 | out3: | 2085 | out3: |
2089 | spin_unlock(&vfsmount_lock); | 2086 | spin_unlock(&vfsmount_lock); |