diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-07-22 09:59:21 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-07-26 20:53:34 -0400 |
commit | 2d8f30380ab8c706f4e0a8f1aaa22b5886e9ac8a (patch) | |
tree | b798097fd831eab39f35c8c2e5a8ccfd7a850ef5 | |
parent | 256984a83880ff7ac78055cb87baea48137f0b77 (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.c | 10 | ||||
-rw-r--r-- | arch/parisc/hpux/sys_hpux.c | 10 | ||||
-rw-r--r-- | fs/coda/pioctl.c | 14 | ||||
-rw-r--r-- | fs/compat.c | 20 | ||||
-rw-r--r-- | fs/inotify_user.c | 22 | ||||
-rw-r--r-- | fs/namei.c | 36 | ||||
-rw-r--r-- | fs/namespace.c | 74 | ||||
-rw-r--r-- | fs/open.c | 124 | ||||
-rw-r--r-- | fs/stat.c | 32 | ||||
-rw-r--r-- | fs/utimes.c | 8 | ||||
-rw-r--r-- | fs/xattr.c | 96 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 14 | ||||
-rw-r--r-- | include/linux/namei.h | 13 |
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 | ||
255 | asmlinkage int | 255 | asmlinkage int |
256 | osf_statfs(char __user *path, struct osf_statfs __user *buffer, unsigned long bufsiz) | 256 | osf_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 */ |
213 | asmlinkage long hpux_statfs(const char __user *path, | 213 | asmlinkage 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) | |||
49 | static int coda_pioctl(struct inode * inode, struct file * filp, | 49 | static 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 | */ |
237 | asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs __user *buf) | 237 | asmlinkage 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 | ||
302 | asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf) | 302 | asmlinkage 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 | */ |
359 | static int find_inode(const char __user *dirname, struct nameidata *nd, | 359 | static 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 | ||
653 | asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | 653 | asmlinkage 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); |
692 | fput_and_out: | 692 | fput_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 | ||
1337 | int __user_walk_fd(int dfd, const char __user *name, unsigned flags, | 1337 | int 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 | ||
1350 | int __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); |
2480 | out_dput: | 2481 | out_dput: |
2481 | dput(new_dentry); | 2482 | dput(new_dentry); |
@@ -2484,7 +2485,7 @@ out_unlock: | |||
2484 | out_release: | 2485 | out_release: |
2485 | path_put(&nd.path); | 2486 | path_put(&nd.path); |
2486 | out: | 2487 | out: |
2487 | path_put(&old_nd.path); | 2488 | path_put(&old_path); |
2488 | exit: | 2489 | exit: |
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 | ||
2880 | EXPORT_SYMBOL(__user_walk); | 2881 | EXPORT_SYMBOL(user_path_at); |
2881 | EXPORT_SYMBOL(__user_walk_fd); | ||
2882 | EXPORT_SYMBOL(follow_down); | 2882 | EXPORT_SYMBOL(follow_down); |
2883 | EXPORT_SYMBOL(follow_up); | 2883 | EXPORT_SYMBOL(follow_up); |
2884 | EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ | 2884 | EXPORT_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 | ||
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: |
@@ -122,37 +122,37 @@ static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf) | |||
122 | return 0; | 122 | return 0; |
123 | } | 123 | } |
124 | 124 | ||
125 | asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf) | 125 | asmlinkage 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 | ||
142 | asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf) | 142 | asmlinkage 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 | ||
226 | static long do_sys_truncate(const char __user * path, loff_t length) | 226 | static 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 | ||
280 | put_write_and_out: | 280 | put_write_and_out: |
281 | put_write_access(inode); | 281 | put_write_access(inode); |
282 | mnt_drop_write_and_out: | 282 | mnt_drop_write_and_out: |
283 | mnt_drop_write(nd.path.mnt); | 283 | mnt_drop_write(path.mnt); |
284 | dput_and_out: | 284 | dput_and_out: |
285 | path_put(&nd.path); | 285 | path_put(&path); |
286 | out: | 286 | out: |
287 | return error; | 287 | return error; |
288 | } | 288 | } |
@@ -425,7 +425,7 @@ out: | |||
425 | */ | 425 | */ |
426 | asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | 426 | asmlinkage 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 | ||
494 | out_path_release: | 494 | out_path_release: |
495 | path_put(&nd.path); | 495 | path_put(&path); |
496 | out: | 496 | out: |
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 | ||
511 | asmlinkage long sys_chdir(const char __user * filename) | 511 | asmlinkage 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 | ||
526 | dput_and_out: | 526 | dput_and_out: |
527 | path_put(&nd.path); | 527 | path_put(&path); |
528 | out: | 528 | out: |
529 | return error; | 529 | return error; |
530 | } | 530 | } |
@@ -557,14 +557,14 @@ out: | |||
557 | 557 | ||
558 | asmlinkage long sys_chroot(const char __user * filename) | 558 | asmlinkage 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; |
577 | dput_and_out: | 577 | dput_and_out: |
578 | path_put(&nd.path); | 578 | path_put(&path); |
579 | out: | 579 | out: |
580 | return error; | 580 | return error; |
581 | } | 581 | } |
@@ -617,17 +617,17 @@ out: | |||
617 | asmlinkage long sys_fchmodat(int dfd, const char __user *filename, | 617 | asmlinkage 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); |
641 | dput_and_out: | 641 | dput_and_out: |
642 | path_put(&nd.path); | 642 | path_put(&path); |
643 | out: | 643 | out: |
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 | ||
677 | asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) | 677 | asmlinkage 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); |
690 | out_release: | 690 | out_release: |
691 | path_put(&nd.path); | 691 | path_put(&path); |
692 | out: | 692 | out: |
693 | return error; | 693 | return error; |
694 | } | 694 | } |
@@ -696,7 +696,7 @@ out: | |||
696 | asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, | 696 | asmlinkage 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); |
715 | out_release: | 715 | out_release: |
716 | path_put(&nd.path); | 716 | path_put(&path); |
717 | out: | 717 | out: |
718 | return error; | 718 | return error; |
719 | } | 719 | } |
720 | 720 | ||
721 | asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) | 721 | asmlinkage 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); |
734 | out_release: | 734 | out_release: |
735 | path_put(&nd.path); | 735 | path_put(&path); |
736 | out: | 736 | out: |
737 | return error; | 737 | return error; |
738 | } | 738 | } |
@@ -57,13 +57,13 @@ EXPORT_SYMBOL(vfs_getattr); | |||
57 | 57 | ||
58 | int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat) | 58 | int 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 | ||
78 | int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat) | 78 | int 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 | ||
294 | asmlinkage long sys_readlinkat(int dfd, const char __user *path, | 294 | asmlinkage 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 | ||
169 | out: | 169 | out: |
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 | ||
254 | asmlinkage long | 254 | asmlinkage long |
255 | sys_setxattr(const char __user *path, const char __user *name, | 255 | sys_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 | ||
273 | asmlinkage long | 273 | asmlinkage long |
274 | sys_lsetxattr(const char __user *path, const char __user *name, | 274 | sys_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 | ||
352 | asmlinkage ssize_t | 352 | asmlinkage ssize_t |
353 | sys_getxattr(const char __user *path, const char __user *name, | 353 | sys_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 | ||
367 | asmlinkage ssize_t | 367 | asmlinkage ssize_t |
368 | sys_lgetxattr(const char __user *path, const char __user *name, void __user *value, | 368 | sys_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 | ||
427 | asmlinkage ssize_t | 427 | asmlinkage ssize_t |
428 | sys_listxattr(const char __user *path, char __user *list, size_t size) | 428 | sys_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 | ||
441 | asmlinkage ssize_t | 441 | asmlinkage ssize_t |
442 | sys_llistxattr(const char __user *path, char __user *list, size_t size) | 442 | sys_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 | ||
488 | asmlinkage long | 488 | asmlinkage long |
489 | sys_removexattr(const char __user *path, const char __user *name) | 489 | sys_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 | ||
506 | asmlinkage long | 506 | asmlinkage long |
507 | sys_lremovexattr(const char __user *path, const char __user *name) | 507 | sys_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 | ||
57 | extern int __user_walk(const char __user *, unsigned, struct nameidata *); | 57 | extern int user_path_at(int, const char __user *, unsigned, struct path *); |
58 | extern 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 | |||
63 | extern int path_lookup(const char *, unsigned, struct nameidata *); | 64 | extern int path_lookup(const char *, unsigned, struct nameidata *); |
64 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, | 65 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, |
65 | const char *, unsigned int, struct nameidata *); | 66 | const char *, unsigned int, struct nameidata *); |