aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c53
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
1208static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) 1208static 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);
1230out_unlock: 1230out_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(&current->fs->lock); 2015 read_lock(&current->fs->lock);
2018 user_nd.path = current->fs->root; 2016 root = current->fs->root;
2019 path_get(&current->fs->root); 2017 path_get(&current->fs->root);
2020 read_unlock(&current->fs->lock); 2018 read_unlock(&current->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);
2078out2: 2076out2:
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);
2083out1: 2081out1:
2084 path_put(&new_nd.path); 2082 path_put(&new_nd.path);
2085out0: 2083out0:
2086 unlock_kernel();
2087 return error; 2084 return error;
2088out3: 2085out3:
2089 spin_unlock(&vfsmount_lock); 2086 spin_unlock(&vfsmount_lock);