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 /fs/namei.c | |
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>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 36 |
1 files changed, 18 insertions, 18 deletions
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 */ |