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(¤t->fs->lock); 2208 root = current->fs->root; 2209 path_get(¤t->fs->root); 2210 read_unlock(¤t->fs->lock); 2211 down_write(&namespace_sem); | 2202 goto out1; 2203 } 2204 2205 read_lock(¤t->fs->lock); 2206 root = current->fs->root; 2207 path_get(¤t->fs->root); 2208 read_unlock(¤t->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 --- |