namespace.c (88b387824fdaecb6ba0f471acf0aadf7d24739fd) namespace.c (2d8f30380ab8c706f4e0a8f1aaa22b5886e9ac8a)
1/*
2 * linux/fs/namespace.c
3 *
4 * (C) Copyright Al Viro 2000, 2001
5 * Released under GPL v2.
6 *
7 * Based on code from fs/super.c, copyright Linus Torvalds and others.
8 * Heavily rewritten.

--- 1116 unchanged lines hidden (view full) ---

1125 * This is important for filesystems which use unnamed block devices.
1126 *
1127 * We now support a flag for forced unmount like the other 'big iron'
1128 * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
1129 */
1130
1131asmlinkage long sys_umount(char __user * name, int flags)
1132{
1/*
2 * linux/fs/namespace.c
3 *
4 * (C) Copyright Al Viro 2000, 2001
5 * Released under GPL v2.
6 *
7 * Based on code from fs/super.c, copyright Linus Torvalds and others.
8 * Heavily rewritten.

--- 1116 unchanged lines hidden (view full) ---

1125 * This is important for filesystems which use unnamed block devices.
1126 *
1127 * We now support a flag for forced unmount like the other 'big iron'
1128 * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
1129 */
1130
1131asmlinkage long sys_umount(char __user * name, int flags)
1132{
1133 struct nameidata nd;
1133 struct path path;
1134 int retval;
1135
1134 int retval;
1135
1136 retval = __user_walk(name, LOOKUP_FOLLOW, &nd);
1136 retval = user_path(name, &path);
1137 if (retval)
1138 goto out;
1139 retval = -EINVAL;
1137 if (retval)
1138 goto out;
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;
1144
1145 retval = -EPERM;
1146 if (!capable(CAP_SYS_ADMIN))
1147 goto dput_and_out;
1148
1143 goto dput_and_out;
1144
1145 retval = -EPERM;
1146 if (!capable(CAP_SYS_ADMIN))
1147 goto dput_and_out;
1148
1149 retval = do_umount(nd.path.mnt, flags);
1149 retval = do_umount(path.mnt, flags);
1150dput_and_out:
1151 /* we mustn't call path_put() as that would clear mnt_expiry_mark */
1150dput_and_out:
1151 /* we mustn't call path_put() as that would clear mnt_expiry_mark */
1152 dput(nd.path.dentry);
1153 mntput_no_expire(nd.path.mnt);
1152 dput(path.dentry);
1153 mntput_no_expire(path.mnt);
1154out:
1155 return retval;
1156}
1157
1158#ifdef __ARCH_WANT_SYS_OLDUMOUNT
1159
1160/*
1161 * The 2.0 compatible umount. No flags.

--- 1012 unchanged lines hidden (view full) ---

2174 * /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
2175 * though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
2176 * first.
2177 */
2178asmlinkage long sys_pivot_root(const char __user * new_root,
2179 const char __user * put_old)
2180{
2181 struct vfsmount *tmp;
1154out:
1155 return retval;
1156}
1157
1158#ifdef __ARCH_WANT_SYS_OLDUMOUNT
1159
1160/*
1161 * The 2.0 compatible umount. No flags.

--- 1012 unchanged lines hidden (view full) ---

2174 * /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
2175 * though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
2176 * first.
2177 */
2178asmlinkage long sys_pivot_root(const char __user * new_root,
2179 const char __user * put_old)
2180{
2181 struct vfsmount *tmp;
2182 struct nameidata new_nd, old_nd;
2183 struct path parent_path, root_parent, root;
2182 struct path new, old, parent_path, root_parent, root;
2184 int error;
2185
2186 if (!capable(CAP_SYS_ADMIN))
2187 return -EPERM;
2188
2183 int error;
2184
2185 if (!capable(CAP_SYS_ADMIN))
2186 return -EPERM;
2187
2189 error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
2190 &new_nd);
2188 error = user_path_dir(new_root, &new);
2191 if (error)
2192 goto out0;
2193 error = -EINVAL;
2189 if (error)
2190 goto out0;
2191 error = -EINVAL;
2194 if (!check_mnt(new_nd.path.mnt))
2192 if (!check_mnt(new.mnt))
2195 goto out1;
2196
2193 goto out1;
2194
2197 error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd);
2195 error = user_path_dir(put_old, &old);
2198 if (error)
2199 goto out1;
2200
2196 if (error)
2197 goto out1;
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;
2205 }
2206
2207 read_lock(&current->fs->lock);
2208 root = current->fs->root;
2209 path_get(&current->fs->root);
2210 read_unlock(&current->fs->lock);
2211 down_write(&namespace_sem);
2202 goto out1;
2203 }
2204
2205 read_lock(&current->fs->lock);
2206 root = current->fs->root;
2207 path_get(&current->fs->root);
2208 read_unlock(&current->fs->lock);
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) ||
2215 IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) ||
2212 if (IS_MNT_SHARED(old.mnt) ||
2213 IS_MNT_SHARED(new.mnt->mnt_parent) ||
2216 IS_MNT_SHARED(root.mnt->mnt_parent))
2217 goto out2;
2218 if (!check_mnt(root.mnt))
2219 goto out2;
2220 error = -ENOENT;
2214 IS_MNT_SHARED(root.mnt->mnt_parent))
2215 goto out2;
2216 if (!check_mnt(root.mnt))
2217 goto out2;
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;
2227 error = -EBUSY;
2224 goto out2;
2225 error = -EBUSY;
2228 if (new_nd.path.mnt == root.mnt ||
2229 old_nd.path.mnt == root.mnt)
2226 if (new.mnt == root.mnt ||
2227 old.mnt == root.mnt)
2230 goto out2; /* loop, on the same file system */
2231 error = -EINVAL;
2232 if (root.mnt->mnt_root != root.dentry)
2233 goto out2; /* not a mountpoint */
2234 if (root.mnt->mnt_parent == root.mnt)
2235 goto out2; /* not attached */
2228 goto out2; /* loop, on the same file system */
2229 error = -EINVAL;
2230 if (root.mnt->mnt_root != root.dentry)
2231 goto out2; /* not a mountpoint */
2232 if (root.mnt->mnt_parent == root.mnt)
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 */
2240 /* make sure we can reach put_old from new_root */
2237 goto out2; /* not attached */
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 (;;) {
2245 if (tmp->mnt_parent == tmp)
2246 goto out3; /* already mounted on put_old */
2242 for (;;) {
2243 if (tmp->mnt_parent == tmp)
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;
2249 tmp = tmp->mnt_parent;
2250 }
2246 break;
2247 tmp = tmp->mnt_parent;
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);
2257 /* mount old root on put_old */
2254 detach_mnt(root.mnt, &root_parent);
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);
2262 spin_unlock(&vfsmount_lock);
2259 touch_mnt_namespace(current->nsproxy->mnt_ns);
2260 spin_unlock(&vfsmount_lock);
2263 chroot_fs_refs(&root, &new_nd.path);
2264 security_sb_post_pivotroot(&root, &new_nd.path);
2261 chroot_fs_refs(&root, &new);
2262 security_sb_post_pivotroot(&root, &new);
2265 error = 0;
2266 path_put(&root_parent);
2267 path_put(&parent_path);
2268out2:
2263 error = 0;
2264 path_put(&root_parent);
2265 path_put(&parent_path);
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);
2271 path_put(&root);
2268 up_write(&namespace_sem);
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:
2276 return error;
2277out3:
2278 spin_unlock(&vfsmount_lock);
2279 goto out2;
2280}
2281
2282static void __init init_mount_tree(void)

--- 74 unchanged lines hidden ---
2273out0:
2274 return error;
2275out3:
2276 spin_unlock(&vfsmount_lock);
2277 goto out2;
2278}
2279
2280static void __init init_mount_tree(void)

--- 74 unchanged lines hidden ---