aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c74
1 files changed, 36 insertions, 38 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 26380f59953..411728c0c8b 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1130,27 +1130,27 @@ static int do_umount(struct vfsmount *mnt, int flags)
1130 1130
1131asmlinkage long sys_umount(char __user * name, int flags) 1131asmlinkage long sys_umount(char __user * name, int flags)
1132{ 1132{
1133 struct nameidata nd; 1133 struct path path;
1134 int retval; 1134 int retval;
1135 1135
1136 retval = __user_walk(name, LOOKUP_FOLLOW, &nd); 1136 retval = user_path(name, &path);
1137 if (retval) 1137 if (retval)
1138 goto out; 1138 goto out;
1139 retval = -EINVAL; 1139 retval = -EINVAL;
1140 if (nd.path.dentry != nd.path.mnt->mnt_root) 1140 if (path.dentry != path.mnt->mnt_root)
1141 goto dput_and_out; 1141 goto dput_and_out;
1142 if (!check_mnt(nd.path.mnt)) 1142 if (!check_mnt(path.mnt))
1143 goto dput_and_out; 1143 goto dput_and_out;
1144 1144
1145 retval = -EPERM; 1145 retval = -EPERM;
1146 if (!capable(CAP_SYS_ADMIN)) 1146 if (!capable(CAP_SYS_ADMIN))
1147 goto dput_and_out; 1147 goto dput_and_out;
1148 1148
1149 retval = do_umount(nd.path.mnt, flags); 1149 retval = do_umount(path.mnt, flags);
1150dput_and_out: 1150dput_and_out:
1151 /* we mustn't call path_put() as that would clear mnt_expiry_mark */ 1151 /* we mustn't call path_put() as that would clear mnt_expiry_mark */
1152 dput(nd.path.dentry); 1152 dput(path.dentry);
1153 mntput_no_expire(nd.path.mnt); 1153 mntput_no_expire(path.mnt);
1154out: 1154out:
1155 return retval; 1155 return retval;
1156} 1156}
@@ -2179,28 +2179,26 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
2179 const char __user * put_old) 2179 const char __user * put_old)
2180{ 2180{
2181 struct vfsmount *tmp; 2181 struct vfsmount *tmp;
2182 struct nameidata new_nd, old_nd; 2182 struct path new, old, parent_path, root_parent, root;
2183 struct path parent_path, root_parent, root;
2184 int error; 2183 int error;
2185 2184
2186 if (!capable(CAP_SYS_ADMIN)) 2185 if (!capable(CAP_SYS_ADMIN))
2187 return -EPERM; 2186 return -EPERM;
2188 2187
2189 error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, 2188 error = user_path_dir(new_root, &new);
2190 &new_nd);
2191 if (error) 2189 if (error)
2192 goto out0; 2190 goto out0;
2193 error = -EINVAL; 2191 error = -EINVAL;
2194 if (!check_mnt(new_nd.path.mnt)) 2192 if (!check_mnt(new.mnt))
2195 goto out1; 2193 goto out1;
2196 2194
2197 error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd); 2195 error = user_path_dir(put_old, &old);
2198 if (error) 2196 if (error)
2199 goto out1; 2197 goto out1;
2200 2198
2201 error = security_sb_pivotroot(&old_nd.path, &new_nd.path); 2199 error = security_sb_pivotroot(&old, &new);
2202 if (error) { 2200 if (error) {
2203 path_put(&old_nd.path); 2201 path_put(&old);
2204 goto out1; 2202 goto out1;
2205 } 2203 }
2206 2204
@@ -2209,69 +2207,69 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
2209 path_get(&current->fs->root); 2207 path_get(&current->fs->root);
2210 read_unlock(&current->fs->lock); 2208 read_unlock(&current->fs->lock);
2211 down_write(&namespace_sem); 2209 down_write(&namespace_sem);
2212 mutex_lock(&old_nd.path.dentry->d_inode->i_mutex); 2210 mutex_lock(&old.dentry->d_inode->i_mutex);
2213 error = -EINVAL; 2211 error = -EINVAL;
2214 if (IS_MNT_SHARED(old_nd.path.mnt) || 2212 if (IS_MNT_SHARED(old.mnt) ||
2215 IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) || 2213 IS_MNT_SHARED(new.mnt->mnt_parent) ||
2216 IS_MNT_SHARED(root.mnt->mnt_parent)) 2214 IS_MNT_SHARED(root.mnt->mnt_parent))
2217 goto out2; 2215 goto out2;
2218 if (!check_mnt(root.mnt)) 2216 if (!check_mnt(root.mnt))
2219 goto out2; 2217 goto out2;
2220 error = -ENOENT; 2218 error = -ENOENT;
2221 if (IS_DEADDIR(new_nd.path.dentry->d_inode)) 2219 if (IS_DEADDIR(new.dentry->d_inode))
2222 goto out2; 2220 goto out2;
2223 if (d_unhashed(new_nd.path.dentry) && !IS_ROOT(new_nd.path.dentry)) 2221 if (d_unhashed(new.dentry) && !IS_ROOT(new.dentry))
2224 goto out2; 2222 goto out2;
2225 if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry)) 2223 if (d_unhashed(old.dentry) && !IS_ROOT(old.dentry))
2226 goto out2; 2224 goto out2;
2227 error = -EBUSY; 2225 error = -EBUSY;
2228 if (new_nd.path.mnt == root.mnt || 2226 if (new.mnt == root.mnt ||
2229 old_nd.path.mnt == root.mnt) 2227 old.mnt == root.mnt)
2230 goto out2; /* loop, on the same file system */ 2228 goto out2; /* loop, on the same file system */
2231 error = -EINVAL; 2229 error = -EINVAL;
2232 if (root.mnt->mnt_root != root.dentry) 2230 if (root.mnt->mnt_root != root.dentry)
2233 goto out2; /* not a mountpoint */ 2231 goto out2; /* not a mountpoint */
2234 if (root.mnt->mnt_parent == root.mnt) 2232 if (root.mnt->mnt_parent == root.mnt)
2235 goto out2; /* not attached */ 2233 goto out2; /* not attached */
2236 if (new_nd.path.mnt->mnt_root != new_nd.path.dentry) 2234 if (new.mnt->mnt_root != new.dentry)
2237 goto out2; /* not a mountpoint */ 2235 goto out2; /* not a mountpoint */
2238 if (new_nd.path.mnt->mnt_parent == new_nd.path.mnt) 2236 if (new.mnt->mnt_parent == new.mnt)
2239 goto out2; /* not attached */ 2237 goto out2; /* not attached */
2240 /* make sure we can reach put_old from new_root */ 2238 /* make sure we can reach put_old from new_root */
2241 tmp = old_nd.path.mnt; 2239 tmp = old.mnt;
2242 spin_lock(&vfsmount_lock); 2240 spin_lock(&vfsmount_lock);
2243 if (tmp != new_nd.path.mnt) { 2241 if (tmp != new.mnt) {
2244 for (;;) { 2242 for (;;) {
2245 if (tmp->mnt_parent == tmp) 2243 if (tmp->mnt_parent == tmp)
2246 goto out3; /* already mounted on put_old */ 2244 goto out3; /* already mounted on put_old */
2247 if (tmp->mnt_parent == new_nd.path.mnt) 2245 if (tmp->mnt_parent == new.mnt)
2248 break; 2246 break;
2249 tmp = tmp->mnt_parent; 2247 tmp = tmp->mnt_parent;
2250 } 2248 }
2251 if (!is_subdir(tmp->mnt_mountpoint, new_nd.path.dentry)) 2249 if (!is_subdir(tmp->mnt_mountpoint, new.dentry))
2252 goto out3; 2250 goto out3;
2253 } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry)) 2251 } else if (!is_subdir(old.dentry, new.dentry))
2254 goto out3; 2252 goto out3;
2255 detach_mnt(new_nd.path.mnt, &parent_path); 2253 detach_mnt(new.mnt, &parent_path);
2256 detach_mnt(root.mnt, &root_parent); 2254 detach_mnt(root.mnt, &root_parent);
2257 /* mount old root on put_old */ 2255 /* mount old root on put_old */
2258 attach_mnt(root.mnt, &old_nd.path); 2256 attach_mnt(root.mnt, &old);
2259 /* mount new_root on / */ 2257 /* mount new_root on / */
2260 attach_mnt(new_nd.path.mnt, &root_parent); 2258 attach_mnt(new.mnt, &root_parent);
2261 touch_mnt_namespace(current->nsproxy->mnt_ns); 2259 touch_mnt_namespace(current->nsproxy->mnt_ns);
2262 spin_unlock(&vfsmount_lock); 2260 spin_unlock(&vfsmount_lock);
2263 chroot_fs_refs(&root, &new_nd.path); 2261 chroot_fs_refs(&root, &new);
2264 security_sb_post_pivotroot(&root, &new_nd.path); 2262 security_sb_post_pivotroot(&root, &new);
2265 error = 0; 2263 error = 0;
2266 path_put(&root_parent); 2264 path_put(&root_parent);
2267 path_put(&parent_path); 2265 path_put(&parent_path);
2268out2: 2266out2:
2269 mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); 2267 mutex_unlock(&old.dentry->d_inode->i_mutex);
2270 up_write(&namespace_sem); 2268 up_write(&namespace_sem);
2271 path_put(&root); 2269 path_put(&root);
2272 path_put(&old_nd.path); 2270 path_put(&old);
2273out1: 2271out1:
2274 path_put(&new_nd.path); 2272 path_put(&new);
2275out0: 2273out0:
2276 return error; 2274 return error;
2277out3: 2275out3: