diff options
Diffstat (limited to 'fs/namespace.c')
| -rw-r--r-- | fs/namespace.c | 74 |
1 files changed, 36 insertions, 38 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 26380f599534..411728c0c8bb 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -1130,27 +1130,27 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
| 1130 | 1130 | ||
| 1131 | asmlinkage long sys_umount(char __user * name, int flags) | 1131 | asmlinkage 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); |
| 1150 | dput_and_out: | 1150 | dput_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); |
| 1154 | out: | 1154 | out: |
| 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(¤t->fs->root); | 2207 | path_get(¤t->fs->root); |
| 2210 | read_unlock(¤t->fs->lock); | 2208 | read_unlock(¤t->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); |
| 2268 | out2: | 2266 | out2: |
| 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); |
| 2273 | out1: | 2271 | out1: |
| 2274 | path_put(&new_nd.path); | 2272 | path_put(&new); |
| 2275 | out0: | 2273 | out0: |
| 2276 | return error; | 2274 | return error; |
| 2277 | out3: | 2275 | out3: |
