diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c index 89a612e392eb..b234e4ec0a71 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2184,6 +2184,188 @@ user_path_parent(int dfd, const char __user *path, struct nameidata *nd, | |||
2184 | return s; | 2184 | return s; |
2185 | } | 2185 | } |
2186 | 2186 | ||
2187 | /** | ||
2188 | * umount_lookup_last - look up last component for umount | ||
2189 | * @nd: pathwalk nameidata - currently pointing at parent directory of "last" | ||
2190 | * @path: pointer to container for result | ||
2191 | * | ||
2192 | * This is a special lookup_last function just for umount. In this case, we | ||
2193 | * need to resolve the path without doing any revalidation. | ||
2194 | * | ||
2195 | * The nameidata should be the result of doing a LOOKUP_PARENT pathwalk. Since | ||
2196 | * mountpoints are always pinned in the dcache, their ancestors are too. Thus, | ||
2197 | * in almost all cases, this lookup will be served out of the dcache. The only | ||
2198 | * cases where it won't are if nd->last refers to a symlink or the path is | ||
2199 | * bogus and it doesn't exist. | ||
2200 | * | ||
2201 | * Returns: | ||
2202 | * -error: if there was an error during lookup. This includes -ENOENT if the | ||
2203 | * lookup found a negative dentry. The nd->path reference will also be | ||
2204 | * put in this case. | ||
2205 | * | ||
2206 | * 0: if we successfully resolved nd->path and found it to not to be a | ||
2207 | * symlink that needs to be followed. "path" will also be populated. | ||
2208 | * The nd->path reference will also be put. | ||
2209 | * | ||
2210 | * 1: if we successfully resolved nd->last and found it to be a symlink | ||
2211 | * that needs to be followed. "path" will be populated with the path | ||
2212 | * to the link, and nd->path will *not* be put. | ||
2213 | */ | ||
2214 | static int | ||
2215 | umount_lookup_last(struct nameidata *nd, struct path *path) | ||
2216 | { | ||
2217 | int error = 0; | ||
2218 | struct dentry *dentry; | ||
2219 | struct dentry *dir = nd->path.dentry; | ||
2220 | |||
2221 | if (unlikely(nd->flags & LOOKUP_RCU)) { | ||
2222 | WARN_ON_ONCE(1); | ||
2223 | error = -ECHILD; | ||
2224 | goto error_check; | ||
2225 | } | ||
2226 | |||
2227 | nd->flags &= ~LOOKUP_PARENT; | ||
2228 | |||
2229 | if (unlikely(nd->last_type != LAST_NORM)) { | ||
2230 | error = handle_dots(nd, nd->last_type); | ||
2231 | if (!error) | ||
2232 | dentry = dget(nd->path.dentry); | ||
2233 | goto error_check; | ||
2234 | } | ||
2235 | |||
2236 | mutex_lock(&dir->d_inode->i_mutex); | ||
2237 | dentry = d_lookup(dir, &nd->last); | ||
2238 | if (!dentry) { | ||
2239 | /* | ||
2240 | * No cached dentry. Mounted dentries are pinned in the cache, | ||
2241 | * so that means that this dentry is probably a symlink or the | ||
2242 | * path doesn't actually point to a mounted dentry. | ||
2243 | */ | ||
2244 | dentry = d_alloc(dir, &nd->last); | ||
2245 | if (!dentry) { | ||
2246 | error = -ENOMEM; | ||
2247 | } else { | ||
2248 | dentry = lookup_real(dir->d_inode, dentry, nd->flags); | ||
2249 | if (IS_ERR(dentry)) | ||
2250 | error = PTR_ERR(dentry); | ||
2251 | } | ||
2252 | } | ||
2253 | mutex_unlock(&dir->d_inode->i_mutex); | ||
2254 | |||
2255 | error_check: | ||
2256 | if (!error) { | ||
2257 | if (!dentry->d_inode) { | ||
2258 | error = -ENOENT; | ||
2259 | dput(dentry); | ||
2260 | } else { | ||
2261 | path->dentry = dentry; | ||
2262 | path->mnt = mntget(nd->path.mnt); | ||
2263 | if (should_follow_link(dentry->d_inode, | ||
2264 | nd->flags & LOOKUP_FOLLOW)) | ||
2265 | return 1; | ||
2266 | follow_mount(path); | ||
2267 | } | ||
2268 | } | ||
2269 | terminate_walk(nd); | ||
2270 | return error; | ||
2271 | } | ||
2272 | |||
2273 | /** | ||
2274 | * path_umountat - look up a path to be umounted | ||
2275 | * @dfd: directory file descriptor to start walk from | ||
2276 | * @name: full pathname to walk | ||
2277 | * @flags: lookup flags | ||
2278 | * @nd: pathwalk nameidata | ||
2279 | * | ||
2280 | * Look up the given name, but don't attempt to revalidate the last component. | ||
2281 | * Returns 0 and "path" will be valid on success; Retuns error otherwise. | ||
2282 | */ | ||
2283 | static int | ||
2284 | path_umountat(int dfd, const char *name, struct path *path, unsigned int flags) | ||
2285 | { | ||
2286 | struct file *base = NULL; | ||
2287 | struct nameidata nd; | ||
2288 | int err; | ||
2289 | |||
2290 | err = path_init(dfd, name, flags | LOOKUP_PARENT, &nd, &base); | ||
2291 | if (unlikely(err)) | ||
2292 | return err; | ||
2293 | |||
2294 | current->total_link_count = 0; | ||
2295 | err = link_path_walk(name, &nd); | ||
2296 | if (err) | ||
2297 | goto out; | ||
2298 | |||
2299 | /* If we're in rcuwalk, drop out of it to handle last component */ | ||
2300 | if (nd.flags & LOOKUP_RCU) { | ||
2301 | err = unlazy_walk(&nd, NULL); | ||
2302 | if (err) { | ||
2303 | terminate_walk(&nd); | ||
2304 | goto out; | ||
2305 | } | ||
2306 | } | ||
2307 | |||
2308 | err = umount_lookup_last(&nd, path); | ||
2309 | while (err > 0) { | ||
2310 | void *cookie; | ||
2311 | struct path link = *path; | ||
2312 | err = may_follow_link(&link, &nd); | ||
2313 | if (unlikely(err)) | ||
2314 | break; | ||
2315 | nd.flags |= LOOKUP_PARENT; | ||
2316 | err = follow_link(&link, &nd, &cookie); | ||
2317 | if (err) | ||
2318 | break; | ||
2319 | err = umount_lookup_last(&nd, path); | ||
2320 | put_link(&nd, &link, cookie); | ||
2321 | } | ||
2322 | out: | ||
2323 | if (base) | ||
2324 | fput(base); | ||
2325 | |||
2326 | if (nd.root.mnt && !(nd.flags & LOOKUP_ROOT)) | ||
2327 | path_put(&nd.root); | ||
2328 | |||
2329 | return err; | ||
2330 | } | ||
2331 | |||
2332 | /** | ||
2333 | * user_path_umountat - lookup a path from userland in order to umount it | ||
2334 | * @dfd: directory file descriptor | ||
2335 | * @name: pathname from userland | ||
2336 | * @flags: lookup flags | ||
2337 | * @path: pointer to container to hold result | ||
2338 | * | ||
2339 | * A umount is a special case for path walking. We're not actually interested | ||
2340 | * in the inode in this situation, and ESTALE errors can be a problem. We | ||
2341 | * simply want track down the dentry and vfsmount attached at the mountpoint | ||
2342 | * and avoid revalidating the last component. | ||
2343 | * | ||
2344 | * Returns 0 and populates "path" on success. | ||
2345 | */ | ||
2346 | int | ||
2347 | user_path_umountat(int dfd, const char __user *name, unsigned int flags, | ||
2348 | struct path *path) | ||
2349 | { | ||
2350 | struct filename *s = getname(name); | ||
2351 | int error; | ||
2352 | |||
2353 | if (IS_ERR(s)) | ||
2354 | return PTR_ERR(s); | ||
2355 | |||
2356 | error = path_umountat(dfd, s->name, path, flags | LOOKUP_RCU); | ||
2357 | if (unlikely(error == -ECHILD)) | ||
2358 | error = path_umountat(dfd, s->name, path, flags); | ||
2359 | if (unlikely(error == -ESTALE)) | ||
2360 | error = path_umountat(dfd, s->name, path, flags | LOOKUP_REVAL); | ||
2361 | |||
2362 | if (likely(!error)) | ||
2363 | audit_inode(s, path->dentry, 0); | ||
2364 | |||
2365 | putname(s); | ||
2366 | return error; | ||
2367 | } | ||
2368 | |||
2187 | /* | 2369 | /* |
2188 | * It's inline, so penalty for filesystems that don't use sticky bit is | 2370 | * It's inline, so penalty for filesystems that don't use sticky bit is |
2189 | * minimal. | 2371 | * minimal. |