aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-07-22 09:59:21 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-07-26 20:53:34 -0400
commit2d8f30380ab8c706f4e0a8f1aaa22b5886e9ac8a (patch)
treeb798097fd831eab39f35c8c2e5a8ccfd7a850ef5
parent256984a83880ff7ac78055cb87baea48137f0b77 (diff)
[PATCH] sanitize __user_walk_fd() et.al.
* do not pass nameidata; struct path is all the callers want. * switch to new helpers: user_path_at(dfd, pathname, flags, &path) user_path(pathname, &path) user_lpath(pathname, &path) user_path_dir(pathname, &path) (fail if not a directory) The last 3 are trivial macro wrappers for the first one. * remove nameidata in callers. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/alpha/kernel/osf_sys.c10
-rw-r--r--arch/parisc/hpux/sys_hpux.c10
-rw-r--r--fs/coda/pioctl.c14
-rw-r--r--fs/compat.c20
-rw-r--r--fs/inotify_user.c22
-rw-r--r--fs/namei.c36
-rw-r--r--fs/namespace.c74
-rw-r--r--fs/open.c124
-rw-r--r--fs/stat.c32
-rw-r--r--fs/utimes.c8
-rw-r--r--fs/xattr.c96
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c14
-rw-r--r--include/linux/namei.h13
13 files changed, 235 insertions, 238 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 32ca1b927307..6e943135f0e0 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -253,15 +253,15 @@ do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,
253} 253}
254 254
255asmlinkage int 255asmlinkage int
256osf_statfs(char __user *path, struct osf_statfs __user *buffer, unsigned long bufsiz) 256osf_statfs(char __user *pathname, struct osf_statfs __user *buffer, unsigned long bufsiz)
257{ 257{
258 struct nameidata nd; 258 struct path path;
259 int retval; 259 int retval;
260 260
261 retval = user_path_walk(path, &nd); 261 retval = user_path(pathname, &path);
262 if (!retval) { 262 if (!retval) {
263 retval = do_osf_statfs(nd.path.dentry, buffer, bufsiz); 263 retval = do_osf_statfs(path.dentry, buffer, bufsiz);
264 path_put(&nd.path); 264 path_put(&path);
265 } 265 }
266 return retval; 266 return retval;
267} 267}
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index be255ebb609c..18072e03a019 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -210,19 +210,19 @@ static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf)
210} 210}
211 211
212/* hpux statfs */ 212/* hpux statfs */
213asmlinkage long hpux_statfs(const char __user *path, 213asmlinkage long hpux_statfs(const char __user *pathname,
214 struct hpux_statfs __user *buf) 214 struct hpux_statfs __user *buf)
215{ 215{
216 struct nameidata nd; 216 struct path path;
217 int error; 217 int error;
218 218
219 error = user_path_walk(path, &nd); 219 error = user_path(pathname, &path);
220 if (!error) { 220 if (!error) {
221 struct hpux_statfs tmp; 221 struct hpux_statfs tmp;
222 error = vfs_statfs_hpux(nd.path.dentry, &tmp); 222 error = vfs_statfs_hpux(path.dentry, &tmp);
223 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 223 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
224 error = -EFAULT; 224 error = -EFAULT;
225 path_put(&nd.path); 225 path_put(&path);
226 } 226 }
227 return error; 227 return error;
228} 228}
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index c38a98974fb0..c51365422aa8 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -49,7 +49,7 @@ static int coda_ioctl_permission(struct inode *inode, int mask)
49static int coda_pioctl(struct inode * inode, struct file * filp, 49static int coda_pioctl(struct inode * inode, struct file * filp,
50 unsigned int cmd, unsigned long user_data) 50 unsigned int cmd, unsigned long user_data)
51{ 51{
52 struct nameidata nd; 52 struct path path;
53 int error; 53 int error;
54 struct PioctlData data; 54 struct PioctlData data;
55 struct inode *target_inode = NULL; 55 struct inode *target_inode = NULL;
@@ -64,21 +64,21 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
64 * Look up the pathname. Note that the pathname is in 64 * Look up the pathname. Note that the pathname is in
65 * user memory, and namei takes care of this 65 * user memory, and namei takes care of this
66 */ 66 */
67 if ( data.follow ) { 67 if (data.follow) {
68 error = user_path_walk(data.path, &nd); 68 error = user_path(data.path, &path);
69 } else { 69 } else {
70 error = user_path_walk_link(data.path, &nd); 70 error = user_lpath(data.path, &path);
71 } 71 }
72 72
73 if ( error ) { 73 if ( error ) {
74 return error; 74 return error;
75 } else { 75 } else {
76 target_inode = nd.path.dentry->d_inode; 76 target_inode = path.dentry->d_inode;
77 } 77 }
78 78
79 /* return if it is not a Coda inode */ 79 /* return if it is not a Coda inode */
80 if ( target_inode->i_sb != inode->i_sb ) { 80 if ( target_inode->i_sb != inode->i_sb ) {
81 path_put(&nd.path); 81 path_put(&path);
82 return -EINVAL; 82 return -EINVAL;
83 } 83 }
84 84
@@ -87,7 +87,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
87 87
88 error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data); 88 error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
89 89
90 path_put(&nd.path); 90 path_put(&path);
91 return error; 91 return error;
92} 92}
93 93
diff --git a/fs/compat.c b/fs/compat.c
index 106eba28ec5a..c9d1472e65c5 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -234,18 +234,18 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
234 * The following statfs calls are copies of code from fs/open.c and 234 * The following statfs calls are copies of code from fs/open.c and
235 * should be checked against those from time to time 235 * should be checked against those from time to time
236 */ 236 */
237asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs __user *buf) 237asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf)
238{ 238{
239 struct nameidata nd; 239 struct path path;
240 int error; 240 int error;
241 241
242 error = user_path_walk(path, &nd); 242 error = user_path(pathname, &path);
243 if (!error) { 243 if (!error) {
244 struct kstatfs tmp; 244 struct kstatfs tmp;
245 error = vfs_statfs(nd.path.dentry, &tmp); 245 error = vfs_statfs(path.dentry, &tmp);
246 if (!error) 246 if (!error)
247 error = put_compat_statfs(buf, &tmp); 247 error = put_compat_statfs(buf, &tmp);
248 path_put(&nd.path); 248 path_put(&path);
249 } 249 }
250 return error; 250 return error;
251} 251}
@@ -299,21 +299,21 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
299 return 0; 299 return 0;
300} 300}
301 301
302asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf) 302asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf)
303{ 303{
304 struct nameidata nd; 304 struct path path;
305 int error; 305 int error;
306 306
307 if (sz != sizeof(*buf)) 307 if (sz != sizeof(*buf))
308 return -EINVAL; 308 return -EINVAL;
309 309
310 error = user_path_walk(path, &nd); 310 error = user_path(pathname, &path);
311 if (!error) { 311 if (!error) {
312 struct kstatfs tmp; 312 struct kstatfs tmp;
313 error = vfs_statfs(nd.path.dentry, &tmp); 313 error = vfs_statfs(path.dentry, &tmp);
314 if (!error) 314 if (!error)
315 error = put_compat_statfs64(buf, &tmp); 315 error = put_compat_statfs64(buf, &tmp);
316 path_put(&nd.path); 316 path_put(&path);
317 } 317 }
318 return error; 318 return error;
319} 319}
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 9b99ebf28884..60249429a253 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -354,20 +354,20 @@ static void inotify_dev_event_dequeue(struct inotify_device *dev)
354} 354}
355 355
356/* 356/*
357 * find_inode - resolve a user-given path to a specific inode and return a nd 357 * find_inode - resolve a user-given path to a specific inode
358 */ 358 */
359static int find_inode(const char __user *dirname, struct nameidata *nd, 359static int find_inode(const char __user *dirname, struct path *path,
360 unsigned flags) 360 unsigned flags)
361{ 361{
362 int error; 362 int error;
363 363
364 error = __user_walk(dirname, flags, nd); 364 error = user_path_at(AT_FDCWD, dirname, flags, path);
365 if (error) 365 if (error)
366 return error; 366 return error;
367 /* you can only watch an inode if you have read permissions on it */ 367 /* you can only watch an inode if you have read permissions on it */
368 error = inode_permission(nd->path.dentry->d_inode, MAY_READ); 368 error = inode_permission(path->dentry->d_inode, MAY_READ);
369 if (error) 369 if (error)
370 path_put(&nd->path); 370 path_put(path);
371 return error; 371 return error;
372} 372}
373 373
@@ -650,11 +650,11 @@ asmlinkage long sys_inotify_init(void)
650 return sys_inotify_init1(0); 650 return sys_inotify_init1(0);
651} 651}
652 652
653asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) 653asmlinkage long sys_inotify_add_watch(int fd, const char __user *pathname, u32 mask)
654{ 654{
655 struct inode *inode; 655 struct inode *inode;
656 struct inotify_device *dev; 656 struct inotify_device *dev;
657 struct nameidata nd; 657 struct path path;
658 struct file *filp; 658 struct file *filp;
659 int ret, fput_needed; 659 int ret, fput_needed;
660 unsigned flags = 0; 660 unsigned flags = 0;
@@ -674,12 +674,12 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
674 if (mask & IN_ONLYDIR) 674 if (mask & IN_ONLYDIR)
675 flags |= LOOKUP_DIRECTORY; 675 flags |= LOOKUP_DIRECTORY;
676 676
677 ret = find_inode(path, &nd, flags); 677 ret = find_inode(pathname, &path, flags);
678 if (unlikely(ret)) 678 if (unlikely(ret))
679 goto fput_and_out; 679 goto fput_and_out;
680 680
681 /* inode held in place by reference to nd; dev by fget on fd */ 681 /* inode held in place by reference to path; dev by fget on fd */
682 inode = nd.path.dentry->d_inode; 682 inode = path.dentry->d_inode;
683 dev = filp->private_data; 683 dev = filp->private_data;
684 684
685 mutex_lock(&dev->up_mutex); 685 mutex_lock(&dev->up_mutex);
@@ -688,7 +688,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
688 ret = create_watch(dev, inode, mask); 688 ret = create_watch(dev, inode, mask);
689 mutex_unlock(&dev->up_mutex); 689 mutex_unlock(&dev->up_mutex);
690 690
691 path_put(&nd.path); 691 path_put(&path);
692fput_and_out: 692fput_and_out:
693 fput_light(filp, fput_needed); 693 fput_light(filp, fput_needed);
694 return ret; 694 return ret;
diff --git a/fs/namei.c b/fs/namei.c
index 5029b93ebbd5..edb5e973f9b3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1334,24 +1334,24 @@ struct dentry *lookup_one_noperm(const char *name, struct dentry *base)
1334 return __lookup_hash(&this, base, NULL); 1334 return __lookup_hash(&this, base, NULL);
1335} 1335}
1336 1336
1337int __user_walk_fd(int dfd, const char __user *name, unsigned flags, 1337int user_path_at(int dfd, const char __user *name, unsigned flags,
1338 struct nameidata *nd) 1338 struct path *path)
1339{ 1339{
1340 struct nameidata nd;
1340 char *tmp = getname(name); 1341 char *tmp = getname(name);
1341 int err = PTR_ERR(tmp); 1342 int err = PTR_ERR(tmp);
1342
1343 if (!IS_ERR(tmp)) { 1343 if (!IS_ERR(tmp)) {
1344 err = do_path_lookup(dfd, tmp, flags, nd); 1344
1345 BUG_ON(flags & LOOKUP_PARENT);
1346
1347 err = do_path_lookup(dfd, tmp, flags, &nd);
1345 putname(tmp); 1348 putname(tmp);
1349 if (!err)
1350 *path = nd.path;
1346 } 1351 }
1347 return err; 1352 return err;
1348} 1353}
1349 1354
1350int __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
1351{
1352 return __user_walk_fd(AT_FDCWD, name, flags, nd);
1353}
1354
1355/* 1355/*
1356 * It's inline, so penalty for filesystems that don't use sticky bit is 1356 * It's inline, so penalty for filesystems that don't use sticky bit is
1357 * minimal. 1357 * minimal.
@@ -2446,7 +2446,8 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
2446 int flags) 2446 int flags)
2447{ 2447{
2448 struct dentry *new_dentry; 2448 struct dentry *new_dentry;
2449 struct nameidata nd, old_nd; 2449 struct nameidata nd;
2450 struct path old_path;
2450 int error; 2451 int error;
2451 char * to; 2452 char * to;
2452 2453
@@ -2457,16 +2458,16 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
2457 if (IS_ERR(to)) 2458 if (IS_ERR(to))
2458 return PTR_ERR(to); 2459 return PTR_ERR(to);
2459 2460
2460 error = __user_walk_fd(olddfd, oldname, 2461 error = user_path_at(olddfd, oldname,
2461 flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0, 2462 flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
2462 &old_nd); 2463 &old_path);
2463 if (error) 2464 if (error)
2464 goto exit; 2465 goto exit;
2465 error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); 2466 error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
2466 if (error) 2467 if (error)
2467 goto out; 2468 goto out;
2468 error = -EXDEV; 2469 error = -EXDEV;
2469 if (old_nd.path.mnt != nd.path.mnt) 2470 if (old_path.mnt != nd.path.mnt)
2470 goto out_release; 2471 goto out_release;
2471 new_dentry = lookup_create(&nd, 0); 2472 new_dentry = lookup_create(&nd, 0);
2472 error = PTR_ERR(new_dentry); 2473 error = PTR_ERR(new_dentry);
@@ -2475,7 +2476,7 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
2475 error = mnt_want_write(nd.path.mnt); 2476 error = mnt_want_write(nd.path.mnt);
2476 if (error) 2477 if (error)
2477 goto out_dput; 2478 goto out_dput;
2478 error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); 2479 error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
2479 mnt_drop_write(nd.path.mnt); 2480 mnt_drop_write(nd.path.mnt);
2480out_dput: 2481out_dput:
2481 dput(new_dentry); 2482 dput(new_dentry);
@@ -2484,7 +2485,7 @@ out_unlock:
2484out_release: 2485out_release:
2485 path_put(&nd.path); 2486 path_put(&nd.path);
2486out: 2487out:
2487 path_put(&old_nd.path); 2488 path_put(&old_path);
2488exit: 2489exit:
2489 putname(to); 2490 putname(to);
2490 2491
@@ -2877,8 +2878,7 @@ const struct inode_operations page_symlink_inode_operations = {
2877 .put_link = page_put_link, 2878 .put_link = page_put_link,
2878}; 2879};
2879 2880
2880EXPORT_SYMBOL(__user_walk); 2881EXPORT_SYMBOL(user_path_at);
2881EXPORT_SYMBOL(__user_walk_fd);
2882EXPORT_SYMBOL(follow_down); 2882EXPORT_SYMBOL(follow_down);
2883EXPORT_SYMBOL(follow_up); 2883EXPORT_SYMBOL(follow_up);
2884EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ 2884EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
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
1131asmlinkage long sys_umount(char __user * name, int flags) 1131asmlinkage 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);
1150dput_and_out: 1150dput_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);
1154out: 1154out:
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(&current->fs->root); 2207 path_get(&current->fs->root);
2210 read_unlock(&current->fs->lock); 2208 read_unlock(&current->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);
2268out2: 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); 2268 up_write(&namespace_sem);
2271 path_put(&root); 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: 2273out0:
2276 return error; 2274 return error;
2277out3: 2275out3:
diff --git a/fs/open.c b/fs/open.c
index e94266700eda..3fe1a6857c75 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -122,37 +122,37 @@ static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
122 return 0; 122 return 0;
123} 123}
124 124
125asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf) 125asmlinkage long sys_statfs(const char __user *pathname, struct statfs __user * buf)
126{ 126{
127 struct nameidata nd; 127 struct path path;
128 int error; 128 int error;
129 129
130 error = user_path_walk(path, &nd); 130 error = user_path(pathname, &path);
131 if (!error) { 131 if (!error) {
132 struct statfs tmp; 132 struct statfs tmp;
133 error = vfs_statfs_native(nd.path.dentry, &tmp); 133 error = vfs_statfs_native(path.dentry, &tmp);
134 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 134 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
135 error = -EFAULT; 135 error = -EFAULT;
136 path_put(&nd.path); 136 path_put(&path);
137 } 137 }
138 return error; 138 return error;
139} 139}
140 140
141 141
142asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf) 142asmlinkage long sys_statfs64(const char __user *pathname, size_t sz, struct statfs64 __user *buf)
143{ 143{
144 struct nameidata nd; 144 struct path path;
145 long error; 145 long error;
146 146
147 if (sz != sizeof(*buf)) 147 if (sz != sizeof(*buf))
148 return -EINVAL; 148 return -EINVAL;
149 error = user_path_walk(path, &nd); 149 error = user_path(pathname, &path);
150 if (!error) { 150 if (!error) {
151 struct statfs64 tmp; 151 struct statfs64 tmp;
152 error = vfs_statfs64(nd.path.dentry, &tmp); 152 error = vfs_statfs64(path.dentry, &tmp);
153 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 153 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
154 error = -EFAULT; 154 error = -EFAULT;
155 path_put(&nd.path); 155 path_put(&path);
156 } 156 }
157 return error; 157 return error;
158} 158}
@@ -223,20 +223,20 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
223 return err; 223 return err;
224} 224}
225 225
226static long do_sys_truncate(const char __user * path, loff_t length) 226static long do_sys_truncate(const char __user *pathname, loff_t length)
227{ 227{
228 struct nameidata nd; 228 struct path path;
229 struct inode * inode; 229 struct inode *inode;
230 int error; 230 int error;
231 231
232 error = -EINVAL; 232 error = -EINVAL;
233 if (length < 0) /* sorry, but loff_t says... */ 233 if (length < 0) /* sorry, but loff_t says... */
234 goto out; 234 goto out;
235 235
236 error = user_path_walk(path, &nd); 236 error = user_path(pathname, &path);
237 if (error) 237 if (error)
238 goto out; 238 goto out;
239 inode = nd.path.dentry->d_inode; 239 inode = path.dentry->d_inode;
240 240
241 /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ 241 /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
242 error = -EISDIR; 242 error = -EISDIR;
@@ -247,7 +247,7 @@ static long do_sys_truncate(const char __user * path, loff_t length)
247 if (!S_ISREG(inode->i_mode)) 247 if (!S_ISREG(inode->i_mode))
248 goto dput_and_out; 248 goto dput_and_out;
249 249
250 error = mnt_want_write(nd.path.mnt); 250 error = mnt_want_write(path.mnt);
251 if (error) 251 if (error)
252 goto dput_and_out; 252 goto dput_and_out;
253 253
@@ -274,15 +274,15 @@ static long do_sys_truncate(const char __user * path, loff_t length)
274 error = locks_verify_truncate(inode, NULL, length); 274 error = locks_verify_truncate(inode, NULL, length);
275 if (!error) { 275 if (!error) {
276 DQUOT_INIT(inode); 276 DQUOT_INIT(inode);
277 error = do_truncate(nd.path.dentry, length, 0, NULL); 277 error = do_truncate(path.dentry, length, 0, NULL);
278 } 278 }
279 279
280put_write_and_out: 280put_write_and_out:
281 put_write_access(inode); 281 put_write_access(inode);
282mnt_drop_write_and_out: 282mnt_drop_write_and_out:
283 mnt_drop_write(nd.path.mnt); 283 mnt_drop_write(path.mnt);
284dput_and_out: 284dput_and_out:
285 path_put(&nd.path); 285 path_put(&path);
286out: 286out:
287 return error; 287 return error;
288} 288}
@@ -425,7 +425,7 @@ out:
425 */ 425 */
426asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) 426asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
427{ 427{
428 struct nameidata nd; 428 struct path path;
429 struct inode *inode; 429 struct inode *inode;
430 int old_fsuid, old_fsgid; 430 int old_fsuid, old_fsgid;
431 kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ 431 kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */
@@ -449,7 +449,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
449 * FIXME: There is a race here against sys_capset. The 449 * FIXME: There is a race here against sys_capset. The
450 * capabilities can change yet we will restore the old 450 * capabilities can change yet we will restore the old
451 * value below. We should hold task_capabilities_lock, 451 * value below. We should hold task_capabilities_lock,
452 * but we cannot because user_path_walk can sleep. 452 * but we cannot because user_path_at can sleep.
453 */ 453 */
454#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ 454#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */
455 if (current->uid) 455 if (current->uid)
@@ -458,11 +458,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
458 old_cap = cap_set_effective(current->cap_permitted); 458 old_cap = cap_set_effective(current->cap_permitted);
459 } 459 }
460 460
461 res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); 461 res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
462 if (res) 462 if (res)
463 goto out; 463 goto out;
464 464
465 inode = nd.path.dentry->d_inode; 465 inode = path.dentry->d_inode;
466 466
467 if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) { 467 if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
468 /* 468 /*
@@ -470,7 +470,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
470 * with the "noexec" flag. 470 * with the "noexec" flag.
471 */ 471 */
472 res = -EACCES; 472 res = -EACCES;
473 if (nd.path.mnt->mnt_flags & MNT_NOEXEC) 473 if (path.mnt->mnt_flags & MNT_NOEXEC)
474 goto out_path_release; 474 goto out_path_release;
475 } 475 }
476 476
@@ -488,11 +488,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
488 * inherently racy and know that the fs may change 488 * inherently racy and know that the fs may change
489 * state before we even see this result. 489 * state before we even see this result.
490 */ 490 */
491 if (__mnt_is_readonly(nd.path.mnt)) 491 if (__mnt_is_readonly(path.mnt))
492 res = -EROFS; 492 res = -EROFS;
493 493
494out_path_release: 494out_path_release:
495 path_put(&nd.path); 495 path_put(&path);
496out: 496out:
497 current->fsuid = old_fsuid; 497 current->fsuid = old_fsuid;
498 current->fsgid = old_fsgid; 498 current->fsgid = old_fsgid;
@@ -510,21 +510,21 @@ asmlinkage long sys_access(const char __user *filename, int mode)
510 510
511asmlinkage long sys_chdir(const char __user * filename) 511asmlinkage long sys_chdir(const char __user * filename)
512{ 512{
513 struct nameidata nd; 513 struct path path;
514 int error; 514 int error;
515 515
516 error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd); 516 error = user_path_dir(filename, &path);
517 if (error) 517 if (error)
518 goto out; 518 goto out;
519 519
520 error = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); 520 error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
521 if (error) 521 if (error)
522 goto dput_and_out; 522 goto dput_and_out;
523 523
524 set_fs_pwd(current->fs, &nd.path); 524 set_fs_pwd(current->fs, &path);
525 525
526dput_and_out: 526dput_and_out:
527 path_put(&nd.path); 527 path_put(&path);
528out: 528out:
529 return error; 529 return error;
530} 530}
@@ -557,14 +557,14 @@ out:
557 557
558asmlinkage long sys_chroot(const char __user * filename) 558asmlinkage long sys_chroot(const char __user * filename)
559{ 559{
560 struct nameidata nd; 560 struct path path;
561 int error; 561 int error;
562 562
563 error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd); 563 error = user_path_dir(filename, &path);
564 if (error) 564 if (error)
565 goto out; 565 goto out;
566 566
567 error = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); 567 error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
568 if (error) 568 if (error)
569 goto dput_and_out; 569 goto dput_and_out;
570 570
@@ -572,10 +572,10 @@ asmlinkage long sys_chroot(const char __user * filename)
572 if (!capable(CAP_SYS_CHROOT)) 572 if (!capable(CAP_SYS_CHROOT))
573 goto dput_and_out; 573 goto dput_and_out;
574 574
575 set_fs_root(current->fs, &nd.path); 575 set_fs_root(current->fs, &path);
576 error = 0; 576 error = 0;
577dput_and_out: 577dput_and_out:
578 path_put(&nd.path); 578 path_put(&path);
579out: 579out:
580 return error; 580 return error;
581} 581}
@@ -617,17 +617,17 @@ out:
617asmlinkage long sys_fchmodat(int dfd, const char __user *filename, 617asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
618 mode_t mode) 618 mode_t mode)
619{ 619{
620 struct nameidata nd; 620 struct path path;
621 struct inode * inode; 621 struct inode *inode;
622 int error; 622 int error;
623 struct iattr newattrs; 623 struct iattr newattrs;
624 624
625 error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); 625 error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
626 if (error) 626 if (error)
627 goto out; 627 goto out;
628 inode = nd.path.dentry->d_inode; 628 inode = path.dentry->d_inode;
629 629
630 error = mnt_want_write(nd.path.mnt); 630 error = mnt_want_write(path.mnt);
631 if (error) 631 if (error)
632 goto dput_and_out; 632 goto dput_and_out;
633 mutex_lock(&inode->i_mutex); 633 mutex_lock(&inode->i_mutex);
@@ -635,11 +635,11 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
635 mode = inode->i_mode; 635 mode = inode->i_mode;
636 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); 636 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
637 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; 637 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
638 error = notify_change(nd.path.dentry, &newattrs); 638 error = notify_change(path.dentry, &newattrs);
639 mutex_unlock(&inode->i_mutex); 639 mutex_unlock(&inode->i_mutex);
640 mnt_drop_write(nd.path.mnt); 640 mnt_drop_write(path.mnt);
641dput_and_out: 641dput_and_out:
642 path_put(&nd.path); 642 path_put(&path);
643out: 643out:
644 return error; 644 return error;
645} 645}
@@ -676,19 +676,19 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
676 676
677asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) 677asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
678{ 678{
679 struct nameidata nd; 679 struct path path;
680 int error; 680 int error;
681 681
682 error = user_path_walk(filename, &nd); 682 error = user_path(filename, &path);
683 if (error) 683 if (error)
684 goto out; 684 goto out;
685 error = mnt_want_write(nd.path.mnt); 685 error = mnt_want_write(path.mnt);
686 if (error) 686 if (error)
687 goto out_release; 687 goto out_release;
688 error = chown_common(nd.path.dentry, user, group); 688 error = chown_common(path.dentry, user, group);
689 mnt_drop_write(nd.path.mnt); 689 mnt_drop_write(path.mnt);
690out_release: 690out_release:
691 path_put(&nd.path); 691 path_put(&path);
692out: 692out:
693 return error; 693 return error;
694} 694}
@@ -696,7 +696,7 @@ out:
696asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, 696asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
697 gid_t group, int flag) 697 gid_t group, int flag)
698{ 698{
699 struct nameidata nd; 699 struct path path;
700 int error = -EINVAL; 700 int error = -EINVAL;
701 int follow; 701 int follow;
702 702
@@ -704,35 +704,35 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
704 goto out; 704 goto out;
705 705
706 follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; 706 follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
707 error = __user_walk_fd(dfd, filename, follow, &nd); 707 error = user_path_at(dfd, filename, follow, &path);
708 if (error) 708 if (error)
709 goto out; 709 goto out;
710 error = mnt_want_write(nd.path.mnt); 710 error = mnt_want_write(path.mnt);
711 if (error) 711 if (error)
712 goto out_release; 712 goto out_release;
713 error = chown_common(nd.path.dentry, user, group); 713 error = chown_common(path.dentry, user, group);
714 mnt_drop_write(nd.path.mnt); 714 mnt_drop_write(path.mnt);
715out_release: 715out_release:
716 path_put(&nd.path); 716 path_put(&path);
717out: 717out:
718 return error; 718 return error;
719} 719}
720 720
721asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) 721asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group)
722{ 722{
723 struct nameidata nd; 723 struct path path;
724 int error; 724 int error;
725 725
726 error = user_path_walk_link(filename, &nd); 726 error = user_lpath(filename, &path);
727 if (error) 727 if (error)
728 goto out; 728 goto out;
729 error = mnt_want_write(nd.path.mnt); 729 error = mnt_want_write(path.mnt);
730 if (error) 730 if (error)
731 goto out_release; 731 goto out_release;
732 error = chown_common(nd.path.dentry, user, group); 732 error = chown_common(path.dentry, user, group);
733 mnt_drop_write(nd.path.mnt); 733 mnt_drop_write(path.mnt);
734out_release: 734out_release:
735 path_put(&nd.path); 735 path_put(&path);
736out: 736out:
737 return error; 737 return error;
738} 738}
diff --git a/fs/stat.c b/fs/stat.c
index 9cf41f719d50..7c46fbeb8b76 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -57,13 +57,13 @@ EXPORT_SYMBOL(vfs_getattr);
57 57
58int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat) 58int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
59{ 59{
60 struct nameidata nd; 60 struct path path;
61 int error; 61 int error;
62 62
63 error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd); 63 error = user_path_at(dfd, name, LOOKUP_FOLLOW, &path);
64 if (!error) { 64 if (!error) {
65 error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat); 65 error = vfs_getattr(path.mnt, path.dentry, stat);
66 path_put(&nd.path); 66 path_put(&path);
67 } 67 }
68 return error; 68 return error;
69} 69}
@@ -77,13 +77,13 @@ EXPORT_SYMBOL(vfs_stat);
77 77
78int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat) 78int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
79{ 79{
80 struct nameidata nd; 80 struct path path;
81 int error; 81 int error;
82 82
83 error = __user_walk_fd(dfd, name, 0, &nd); 83 error = user_path_at(dfd, name, 0, &path);
84 if (!error) { 84 if (!error) {
85 error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat); 85 error = vfs_getattr(path.mnt, path.dentry, stat);
86 path_put(&nd.path); 86 path_put(&path);
87 } 87 }
88 return error; 88 return error;
89} 89}
@@ -291,29 +291,29 @@ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
291 return error; 291 return error;
292} 292}
293 293
294asmlinkage long sys_readlinkat(int dfd, const char __user *path, 294asmlinkage long sys_readlinkat(int dfd, const char __user *pathname,
295 char __user *buf, int bufsiz) 295 char __user *buf, int bufsiz)
296{ 296{
297 struct nameidata nd; 297 struct path path;
298 int error; 298 int error;
299 299
300 if (bufsiz <= 0) 300 if (bufsiz <= 0)
301 return -EINVAL; 301 return -EINVAL;
302 302
303 error = __user_walk_fd(dfd, path, 0, &nd); 303 error = user_path_at(dfd, pathname, 0, &path);
304 if (!error) { 304 if (!error) {
305 struct inode *inode = nd.path.dentry->d_inode; 305 struct inode *inode = path.dentry->d_inode;
306 306
307 error = -EINVAL; 307 error = -EINVAL;
308 if (inode->i_op && inode->i_op->readlink) { 308 if (inode->i_op && inode->i_op->readlink) {
309 error = security_inode_readlink(nd.path.dentry); 309 error = security_inode_readlink(path.dentry);
310 if (!error) { 310 if (!error) {
311 touch_atime(nd.path.mnt, nd.path.dentry); 311 touch_atime(path.mnt, path.dentry);
312 error = inode->i_op->readlink(nd.path.dentry, 312 error = inode->i_op->readlink(path.dentry,
313 buf, bufsiz); 313 buf, bufsiz);
314 } 314 }
315 } 315 }
316 path_put(&nd.path); 316 path_put(&path);
317 } 317 }
318 return error; 318 return error;
319} 319}
diff --git a/fs/utimes.c b/fs/utimes.c
index dc28b7826259..6929e3e91d05 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -152,18 +152,18 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
152 error = utimes_common(&file->f_path, times); 152 error = utimes_common(&file->f_path, times);
153 fput(file); 153 fput(file);
154 } else { 154 } else {
155 struct nameidata nd; 155 struct path path;
156 int lookup_flags = 0; 156 int lookup_flags = 0;
157 157
158 if (!(flags & AT_SYMLINK_NOFOLLOW)) 158 if (!(flags & AT_SYMLINK_NOFOLLOW))
159 lookup_flags |= LOOKUP_FOLLOW; 159 lookup_flags |= LOOKUP_FOLLOW;
160 160
161 error = __user_walk_fd(dfd, filename, lookup_flags, &nd); 161 error = user_path_at(dfd, filename, lookup_flags, &path);
162 if (error) 162 if (error)
163 goto out; 163 goto out;
164 164
165 error = utimes_common(&nd.path, times); 165 error = utimes_common(&path, times);
166 path_put(&nd.path); 166 path_put(&path);
167 } 167 }
168 168
169out: 169out:
diff --git a/fs/xattr.c b/fs/xattr.c
index b96222e05ba0..468377e66531 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -252,40 +252,40 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
252} 252}
253 253
254asmlinkage long 254asmlinkage long
255sys_setxattr(const char __user *path, const char __user *name, 255sys_setxattr(const char __user *pathname, const char __user *name,
256 const void __user *value, size_t size, int flags) 256 const void __user *value, size_t size, int flags)
257{ 257{
258 struct nameidata nd; 258 struct path path;
259 int error; 259 int error;
260 260
261 error = user_path_walk(path, &nd); 261 error = user_path(pathname, &path);
262 if (error) 262 if (error)
263 return error; 263 return error;
264 error = mnt_want_write(nd.path.mnt); 264 error = mnt_want_write(path.mnt);
265 if (!error) { 265 if (!error) {
266 error = setxattr(nd.path.dentry, name, value, size, flags); 266 error = setxattr(path.dentry, name, value, size, flags);
267 mnt_drop_write(nd.path.mnt); 267 mnt_drop_write(path.mnt);
268 } 268 }
269 path_put(&nd.path); 269 path_put(&path);
270 return error; 270 return error;
271} 271}
272 272
273asmlinkage long 273asmlinkage long
274sys_lsetxattr(const char __user *path, const char __user *name, 274sys_lsetxattr(const char __user *pathname, const char __user *name,
275 const void __user *value, size_t size, int flags) 275 const void __user *value, size_t size, int flags)
276{ 276{
277 struct nameidata nd; 277 struct path path;
278 int error; 278 int error;
279 279
280 error = user_path_walk_link(path, &nd); 280 error = user_lpath(pathname, &path);
281 if (error) 281 if (error)
282 return error; 282 return error;
283 error = mnt_want_write(nd.path.mnt); 283 error = mnt_want_write(path.mnt);
284 if (!error) { 284 if (!error) {
285 error = setxattr(nd.path.dentry, name, value, size, flags); 285 error = setxattr(path.dentry, name, value, size, flags);
286 mnt_drop_write(nd.path.mnt); 286 mnt_drop_write(path.mnt);
287 } 287 }
288 path_put(&nd.path); 288 path_put(&path);
289 return error; 289 return error;
290} 290}
291 291
@@ -350,32 +350,32 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
350} 350}
351 351
352asmlinkage ssize_t 352asmlinkage ssize_t
353sys_getxattr(const char __user *path, const char __user *name, 353sys_getxattr(const char __user *pathname, const char __user *name,
354 void __user *value, size_t size) 354 void __user *value, size_t size)
355{ 355{
356 struct nameidata nd; 356 struct path path;
357 ssize_t error; 357 ssize_t error;
358 358
359 error = user_path_walk(path, &nd); 359 error = user_path(pathname, &path);
360 if (error) 360 if (error)
361 return error; 361 return error;
362 error = getxattr(nd.path.dentry, name, value, size); 362 error = getxattr(path.dentry, name, value, size);
363 path_put(&nd.path); 363 path_put(&path);
364 return error; 364 return error;
365} 365}
366 366
367asmlinkage ssize_t 367asmlinkage ssize_t
368sys_lgetxattr(const char __user *path, const char __user *name, void __user *value, 368sys_lgetxattr(const char __user *pathname, const char __user *name, void __user *value,
369 size_t size) 369 size_t size)
370{ 370{
371 struct nameidata nd; 371 struct path path;
372 ssize_t error; 372 ssize_t error;
373 373
374 error = user_path_walk_link(path, &nd); 374 error = user_lpath(pathname, &path);
375 if (error) 375 if (error)
376 return error; 376 return error;
377 error = getxattr(nd.path.dentry, name, value, size); 377 error = getxattr(path.dentry, name, value, size);
378 path_put(&nd.path); 378 path_put(&path);
379 return error; 379 return error;
380} 380}
381 381
@@ -425,30 +425,30 @@ listxattr(struct dentry *d, char __user *list, size_t size)
425} 425}
426 426
427asmlinkage ssize_t 427asmlinkage ssize_t
428sys_listxattr(const char __user *path, char __user *list, size_t size) 428sys_listxattr(const char __user *pathname, char __user *list, size_t size)
429{ 429{
430 struct nameidata nd; 430 struct path path;
431 ssize_t error; 431 ssize_t error;
432 432
433 error = user_path_walk(path, &nd); 433 error = user_path(pathname, &path);
434 if (error) 434 if (error)
435 return error; 435 return error;
436 error = listxattr(nd.path.dentry, list, size); 436 error = listxattr(path.dentry, list, size);
437 path_put(&nd.path); 437 path_put(&path);
438 return error; 438 return error;
439} 439}
440 440
441asmlinkage ssize_t 441asmlinkage ssize_t
442sys_llistxattr(const char __user *path, char __user *list, size_t size) 442sys_llistxattr(const char __user *pathname, char __user *list, size_t size)
443{ 443{
444 struct nameidata nd; 444 struct path path;
445 ssize_t error; 445 ssize_t error;
446 446
447 error = user_path_walk_link(path, &nd); 447 error = user_lpath(pathname, &path);
448 if (error) 448 if (error)
449 return error; 449 return error;
450 error = listxattr(nd.path.dentry, list, size); 450 error = listxattr(path.dentry, list, size);
451 path_put(&nd.path); 451 path_put(&path);
452 return error; 452 return error;
453} 453}
454 454
@@ -486,38 +486,38 @@ removexattr(struct dentry *d, const char __user *name)
486} 486}
487 487
488asmlinkage long 488asmlinkage long
489sys_removexattr(const char __user *path, const char __user *name) 489sys_removexattr(const char __user *pathname, const char __user *name)
490{ 490{
491 struct nameidata nd; 491 struct path path;
492 int error; 492 int error;
493 493
494 error = user_path_walk(path, &nd); 494 error = user_path(pathname, &path);
495 if (error) 495 if (error)
496 return error; 496 return error;
497 error = mnt_want_write(nd.path.mnt); 497 error = mnt_want_write(path.mnt);
498 if (!error) { 498 if (!error) {
499 error = removexattr(nd.path.dentry, name); 499 error = removexattr(path.dentry, name);
500 mnt_drop_write(nd.path.mnt); 500 mnt_drop_write(path.mnt);
501 } 501 }
502 path_put(&nd.path); 502 path_put(&path);
503 return error; 503 return error;
504} 504}
505 505
506asmlinkage long 506asmlinkage long
507sys_lremovexattr(const char __user *path, const char __user *name) 507sys_lremovexattr(const char __user *pathname, const char __user *name)
508{ 508{
509 struct nameidata nd; 509 struct path path;
510 int error; 510 int error;
511 511
512 error = user_path_walk_link(path, &nd); 512 error = user_lpath(pathname, &path);
513 if (error) 513 if (error)
514 return error; 514 return error;
515 error = mnt_want_write(nd.path.mnt); 515 error = mnt_want_write(path.mnt);
516 if (!error) { 516 if (!error) {
517 error = removexattr(nd.path.dentry, name); 517 error = removexattr(path.dentry, name);
518 mnt_drop_write(nd.path.mnt); 518 mnt_drop_write(path.mnt);
519 } 519 }
520 path_put(&nd.path); 520 path_put(&path);
521 return error; 521 return error;
522} 522}
523 523
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index a42ba9d71156..01939ba2d8de 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -84,17 +84,15 @@ xfs_find_handle(
84 switch (cmd) { 84 switch (cmd) {
85 case XFS_IOC_PATH_TO_FSHANDLE: 85 case XFS_IOC_PATH_TO_FSHANDLE:
86 case XFS_IOC_PATH_TO_HANDLE: { 86 case XFS_IOC_PATH_TO_HANDLE: {
87 struct nameidata nd; 87 struct path path;
88 int error; 88 int error = user_lpath((const char __user *)hreq.path, &path);
89
90 error = user_path_walk_link((const char __user *)hreq.path, &nd);
91 if (error) 89 if (error)
92 return error; 90 return error;
93 91
94 ASSERT(nd.path.dentry); 92 ASSERT(path.dentry);
95 ASSERT(nd.path.dentry->d_inode); 93 ASSERT(path.dentry->d_inode);
96 inode = igrab(nd.path.dentry->d_inode); 94 inode = igrab(path.dentry->d_inode);
97 path_put(&nd.path); 95 path_put(&path);
98 break; 96 break;
99 } 97 }
100 98
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 60e35a02f6cb..00888ff69504 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -54,12 +54,13 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
54#define LOOKUP_OPEN (0x0100) 54#define LOOKUP_OPEN (0x0100)
55#define LOOKUP_CREATE (0x0200) 55#define LOOKUP_CREATE (0x0200)
56 56
57extern int __user_walk(const char __user *, unsigned, struct nameidata *); 57extern int user_path_at(int, const char __user *, unsigned, struct path *);
58extern int __user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *); 58
59#define user_path_walk(name,nd) \ 59#define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path)
60 __user_walk_fd(AT_FDCWD, name, LOOKUP_FOLLOW, nd) 60#define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path)
61#define user_path_walk_link(name,nd) \ 61#define user_path_dir(name, path) \
62 __user_walk_fd(AT_FDCWD, name, 0, nd) 62 user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, path)
63
63extern int path_lookup(const char *, unsigned, struct nameidata *); 64extern int path_lookup(const char *, unsigned, struct nameidata *);
64extern int vfs_path_lookup(struct dentry *, struct vfsmount *, 65extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
65 const char *, unsigned int, struct nameidata *); 66 const char *, unsigned int, struct nameidata *);