aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namei.c137
1 files changed, 57 insertions, 80 deletions
diff --git a/fs/namei.c b/fs/namei.c
index edb5e973f9b3..38ceb6e06eba 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1352,6 +1352,24 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
1352 return err; 1352 return err;
1353} 1353}
1354 1354
1355static int user_path_parent(int dfd, const char __user *path,
1356 struct nameidata *nd, char **name)
1357{
1358 char *s = getname(path);
1359 int error;
1360
1361 if (IS_ERR(s))
1362 return PTR_ERR(s);
1363
1364 error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd);
1365 if (error)
1366 putname(s);
1367 else
1368 *name = s;
1369
1370 return error;
1371}
1372
1355/* 1373/*
1356 * It's inline, so penalty for filesystems that don't use sticky bit is 1374 * It's inline, so penalty for filesystems that don't use sticky bit is
1357 * minimal. 1375 * minimal.
@@ -1989,20 +2007,18 @@ static int may_mknod(mode_t mode)
1989asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, 2007asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
1990 unsigned dev) 2008 unsigned dev)
1991{ 2009{
1992 int error = 0; 2010 int error;
1993 char * tmp; 2011 char *tmp;
1994 struct dentry * dentry; 2012 struct dentry *dentry;
1995 struct nameidata nd; 2013 struct nameidata nd;
1996 2014
1997 if (S_ISDIR(mode)) 2015 if (S_ISDIR(mode))
1998 return -EPERM; 2016 return -EPERM;
1999 tmp = getname(filename);
2000 if (IS_ERR(tmp))
2001 return PTR_ERR(tmp);
2002 2017
2003 error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); 2018 error = user_path_parent(dfd, filename, &nd, &tmp);
2004 if (error) 2019 if (error)
2005 goto out; 2020 return error;
2021
2006 dentry = lookup_create(&nd, 0); 2022 dentry = lookup_create(&nd, 0);
2007 if (IS_ERR(dentry)) { 2023 if (IS_ERR(dentry)) {
2008 error = PTR_ERR(dentry); 2024 error = PTR_ERR(dentry);
@@ -2034,7 +2050,6 @@ out_dput:
2034out_unlock: 2050out_unlock:
2035 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2051 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2036 path_put(&nd.path); 2052 path_put(&nd.path);
2037out:
2038 putname(tmp); 2053 putname(tmp);
2039 2054
2040 return error; 2055 return error;
@@ -2074,14 +2089,10 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
2074 struct dentry *dentry; 2089 struct dentry *dentry;
2075 struct nameidata nd; 2090 struct nameidata nd;
2076 2091
2077 tmp = getname(pathname); 2092 error = user_path_parent(dfd, pathname, &nd, &tmp);
2078 error = PTR_ERR(tmp); 2093 if (error)
2079 if (IS_ERR(tmp))
2080 goto out_err; 2094 goto out_err;
2081 2095
2082 error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
2083 if (error)
2084 goto out;
2085 dentry = lookup_create(&nd, 1); 2096 dentry = lookup_create(&nd, 1);
2086 error = PTR_ERR(dentry); 2097 error = PTR_ERR(dentry);
2087 if (IS_ERR(dentry)) 2098 if (IS_ERR(dentry))
@@ -2099,7 +2110,6 @@ out_dput:
2099out_unlock: 2110out_unlock:
2100 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2111 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2101 path_put(&nd.path); 2112 path_put(&nd.path);
2102out:
2103 putname(tmp); 2113 putname(tmp);
2104out_err: 2114out_err:
2105 return error; 2115 return error;
@@ -2177,13 +2187,9 @@ static long do_rmdir(int dfd, const char __user *pathname)
2177 struct dentry *dentry; 2187 struct dentry *dentry;
2178 struct nameidata nd; 2188 struct nameidata nd;
2179 2189
2180 name = getname(pathname); 2190 error = user_path_parent(dfd, pathname, &nd, &name);
2181 if(IS_ERR(name))
2182 return PTR_ERR(name);
2183
2184 error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
2185 if (error) 2191 if (error)
2186 goto exit; 2192 return error;
2187 2193
2188 switch(nd.last_type) { 2194 switch(nd.last_type) {
2189 case LAST_DOTDOT: 2195 case LAST_DOTDOT:
@@ -2212,7 +2218,6 @@ exit2:
2212 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2218 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2213exit1: 2219exit1:
2214 path_put(&nd.path); 2220 path_put(&nd.path);
2215exit:
2216 putname(name); 2221 putname(name);
2217 return error; 2222 return error;
2218} 2223}
@@ -2261,19 +2266,16 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
2261 */ 2266 */
2262static long do_unlinkat(int dfd, const char __user *pathname) 2267static long do_unlinkat(int dfd, const char __user *pathname)
2263{ 2268{
2264 int error = 0; 2269 int error;
2265 char * name; 2270 char *name;
2266 struct dentry *dentry; 2271 struct dentry *dentry;
2267 struct nameidata nd; 2272 struct nameidata nd;
2268 struct inode *inode = NULL; 2273 struct inode *inode = NULL;
2269 2274
2270 name = getname(pathname); 2275 error = user_path_parent(dfd, pathname, &nd, &name);
2271 if(IS_ERR(name))
2272 return PTR_ERR(name);
2273
2274 error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
2275 if (error) 2276 if (error)
2276 goto exit; 2277 return error;
2278
2277 error = -EISDIR; 2279 error = -EISDIR;
2278 if (nd.last_type != LAST_NORM) 2280 if (nd.last_type != LAST_NORM)
2279 goto exit1; 2281 goto exit1;
@@ -2300,7 +2302,6 @@ static long do_unlinkat(int dfd, const char __user *pathname)
2300 iput(inode); /* truncate the inode here */ 2302 iput(inode); /* truncate the inode here */
2301exit1: 2303exit1:
2302 path_put(&nd.path); 2304 path_put(&nd.path);
2303exit:
2304 putname(name); 2305 putname(name);
2305 return error; 2306 return error;
2306 2307
@@ -2350,23 +2351,20 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
2350asmlinkage long sys_symlinkat(const char __user *oldname, 2351asmlinkage long sys_symlinkat(const char __user *oldname,
2351 int newdfd, const char __user *newname) 2352 int newdfd, const char __user *newname)
2352{ 2353{
2353 int error = 0; 2354 int error;
2354 char * from; 2355 char *from;
2355 char * to; 2356 char *to;
2356 struct dentry *dentry; 2357 struct dentry *dentry;
2357 struct nameidata nd; 2358 struct nameidata nd;
2358 2359
2359 from = getname(oldname); 2360 from = getname(oldname);
2360 if(IS_ERR(from)) 2361 if (IS_ERR(from))
2361 return PTR_ERR(from); 2362 return PTR_ERR(from);
2362 to = getname(newname);
2363 error = PTR_ERR(to);
2364 if (IS_ERR(to))
2365 goto out_putname;
2366 2363
2367 error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); 2364 error = user_path_parent(newdfd, newname, &nd, &to);
2368 if (error) 2365 if (error)
2369 goto out; 2366 goto out_putname;
2367
2370 dentry = lookup_create(&nd, 0); 2368 dentry = lookup_create(&nd, 0);
2371 error = PTR_ERR(dentry); 2369 error = PTR_ERR(dentry);
2372 if (IS_ERR(dentry)) 2370 if (IS_ERR(dentry))
@@ -2382,7 +2380,6 @@ out_dput:
2382out_unlock: 2380out_unlock:
2383 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2381 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2384 path_put(&nd.path); 2382 path_put(&nd.path);
2385out:
2386 putname(to); 2383 putname(to);
2387out_putname: 2384out_putname:
2388 putname(from); 2385 putname(from);
@@ -2449,21 +2446,18 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
2449 struct nameidata nd; 2446 struct nameidata nd;
2450 struct path old_path; 2447 struct path old_path;
2451 int error; 2448 int error;
2452 char * to; 2449 char *to;
2453 2450
2454 if ((flags & ~AT_SYMLINK_FOLLOW) != 0) 2451 if ((flags & ~AT_SYMLINK_FOLLOW) != 0)
2455 return -EINVAL; 2452 return -EINVAL;
2456 2453
2457 to = getname(newname);
2458 if (IS_ERR(to))
2459 return PTR_ERR(to);
2460
2461 error = user_path_at(olddfd, oldname, 2454 error = user_path_at(olddfd, oldname,
2462 flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0, 2455 flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
2463 &old_path); 2456 &old_path);
2464 if (error) 2457 if (error)
2465 goto exit; 2458 return error;
2466 error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); 2459
2460 error = user_path_parent(newdfd, newname, &nd, &to);
2467 if (error) 2461 if (error)
2468 goto out; 2462 goto out;
2469 error = -EXDEV; 2463 error = -EXDEV;
@@ -2484,10 +2478,9 @@ out_unlock:
2484 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2478 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2485out_release: 2479out_release:
2486 path_put(&nd.path); 2480 path_put(&nd.path);
2481 putname(to);
2487out: 2482out:
2488 path_put(&old_path); 2483 path_put(&old_path);
2489exit:
2490 putname(to);
2491 2484
2492 return error; 2485 return error;
2493} 2486}
@@ -2643,20 +2636,22 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
2643 return error; 2636 return error;
2644} 2637}
2645 2638
2646static int do_rename(int olddfd, const char *oldname, 2639asmlinkage long sys_renameat(int olddfd, const char __user *oldname,
2647 int newdfd, const char *newname) 2640 int newdfd, const char __user *newname)
2648{ 2641{
2649 int error = 0; 2642 struct dentry *old_dir, *new_dir;
2650 struct dentry * old_dir, * new_dir; 2643 struct dentry *old_dentry, *new_dentry;
2651 struct dentry * old_dentry, *new_dentry; 2644 struct dentry *trap;
2652 struct dentry * trap;
2653 struct nameidata oldnd, newnd; 2645 struct nameidata oldnd, newnd;
2646 char *from;
2647 char *to;
2648 int error;
2654 2649
2655 error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd); 2650 error = user_path_parent(olddfd, oldname, &oldnd, &from);
2656 if (error) 2651 if (error)
2657 goto exit; 2652 goto exit;
2658 2653
2659 error = do_path_lookup(newdfd, newname, LOOKUP_PARENT, &newnd); 2654 error = user_path_parent(newdfd, newname, &newnd, &to);
2660 if (error) 2655 if (error)
2661 goto exit1; 2656 goto exit1;
2662 2657
@@ -2718,29 +2713,11 @@ exit3:
2718 unlock_rename(new_dir, old_dir); 2713 unlock_rename(new_dir, old_dir);
2719exit2: 2714exit2:
2720 path_put(&newnd.path); 2715 path_put(&newnd.path);
2716 putname(to);
2721exit1: 2717exit1:
2722 path_put(&oldnd.path); 2718 path_put(&oldnd.path);
2723exit:
2724 return error;
2725}
2726
2727asmlinkage long sys_renameat(int olddfd, const char __user *oldname,
2728 int newdfd, const char __user *newname)
2729{
2730 int error;
2731 char * from;
2732 char * to;
2733
2734 from = getname(oldname);
2735 if(IS_ERR(from))
2736 return PTR_ERR(from);
2737 to = getname(newname);
2738 error = PTR_ERR(to);
2739 if (!IS_ERR(to)) {
2740 error = do_rename(olddfd, from, newdfd, to);
2741 putname(to);
2742 }
2743 putname(from); 2719 putname(from);
2720exit:
2744 return error; 2721 return error;
2745} 2722}
2746 2723