aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c182
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 */
2214static int
2215umount_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
2255error_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 */
2283static int
2284path_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 }
2322out:
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 */
2346int
2347user_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.