Commit dae6ad8f37529963ae7df52baaccf056b38f210e
1 parent
49084c3bb2
Exists in
master
and in
38 other branches
new helpers: kern_path_create/user_path_create
combination of kern_path_parent() and lookup_create(). Does *not* expose struct nameidata to caller. Syscalls converted to that... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 4 changed files with 106 additions and 137 deletions Side-by-side Diff
fs/namei.c
... | ... | @@ -2311,6 +2311,35 @@ |
2311 | 2311 | } |
2312 | 2312 | EXPORT_SYMBOL_GPL(lookup_create); |
2313 | 2313 | |
2314 | +struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path, int is_dir) | |
2315 | +{ | |
2316 | + struct nameidata nd; | |
2317 | + struct dentry *res; | |
2318 | + int error = do_path_lookup(dfd, pathname, LOOKUP_PARENT, &nd); | |
2319 | + if (error) | |
2320 | + return ERR_PTR(error); | |
2321 | + res = lookup_create(&nd, is_dir); | |
2322 | + if (IS_ERR(res)) { | |
2323 | + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
2324 | + path_put(&nd.path); | |
2325 | + } | |
2326 | + *path = nd.path; | |
2327 | + return res; | |
2328 | +} | |
2329 | +EXPORT_SYMBOL(kern_path_create); | |
2330 | + | |
2331 | +struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir) | |
2332 | +{ | |
2333 | + char *tmp = getname(pathname); | |
2334 | + struct dentry *res; | |
2335 | + if (IS_ERR(tmp)) | |
2336 | + return ERR_CAST(tmp); | |
2337 | + res = kern_path_create(dfd, tmp, path, is_dir); | |
2338 | + putname(tmp); | |
2339 | + return res; | |
2340 | +} | |
2341 | +EXPORT_SYMBOL(user_path_create); | |
2342 | + | |
2314 | 2343 | int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) |
2315 | 2344 | { |
2316 | 2345 | int error = may_create(dir, dentry); |
2317 | 2346 | |
2318 | 2347 | |
2319 | 2348 | |
2320 | 2349 | |
2321 | 2350 | |
2322 | 2351 | |
2323 | 2352 | |
2324 | 2353 | |
2325 | 2354 | |
2326 | 2355 | |
... | ... | @@ -2359,54 +2388,46 @@ |
2359 | 2388 | SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode, |
2360 | 2389 | unsigned, dev) |
2361 | 2390 | { |
2362 | - int error; | |
2363 | - char *tmp; | |
2364 | 2391 | struct dentry *dentry; |
2365 | - struct nameidata nd; | |
2392 | + struct path path; | |
2393 | + int error; | |
2366 | 2394 | |
2367 | 2395 | if (S_ISDIR(mode)) |
2368 | 2396 | return -EPERM; |
2369 | 2397 | |
2370 | - error = user_path_parent(dfd, filename, &nd, &tmp); | |
2371 | - if (error) | |
2372 | - return error; | |
2398 | + dentry = user_path_create(dfd, filename, &path, 0); | |
2399 | + if (IS_ERR(dentry)) | |
2400 | + return PTR_ERR(dentry); | |
2373 | 2401 | |
2374 | - dentry = lookup_create(&nd, 0); | |
2375 | - if (IS_ERR(dentry)) { | |
2376 | - error = PTR_ERR(dentry); | |
2377 | - goto out_unlock; | |
2378 | - } | |
2379 | - if (!IS_POSIXACL(nd.path.dentry->d_inode)) | |
2402 | + if (!IS_POSIXACL(path.dentry->d_inode)) | |
2380 | 2403 | mode &= ~current_umask(); |
2381 | 2404 | error = may_mknod(mode); |
2382 | 2405 | if (error) |
2383 | 2406 | goto out_dput; |
2384 | - error = mnt_want_write(nd.path.mnt); | |
2407 | + error = mnt_want_write(path.mnt); | |
2385 | 2408 | if (error) |
2386 | 2409 | goto out_dput; |
2387 | - error = security_path_mknod(&nd.path, dentry, mode, dev); | |
2410 | + error = security_path_mknod(&path, dentry, mode, dev); | |
2388 | 2411 | if (error) |
2389 | 2412 | goto out_drop_write; |
2390 | 2413 | switch (mode & S_IFMT) { |
2391 | 2414 | case 0: case S_IFREG: |
2392 | - error = vfs_create(nd.path.dentry->d_inode,dentry,mode,NULL); | |
2415 | + error = vfs_create(path.dentry->d_inode,dentry,mode,NULL); | |
2393 | 2416 | break; |
2394 | 2417 | case S_IFCHR: case S_IFBLK: |
2395 | - error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode, | |
2418 | + error = vfs_mknod(path.dentry->d_inode,dentry,mode, | |
2396 | 2419 | new_decode_dev(dev)); |
2397 | 2420 | break; |
2398 | 2421 | case S_IFIFO: case S_IFSOCK: |
2399 | - error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); | |
2422 | + error = vfs_mknod(path.dentry->d_inode,dentry,mode,0); | |
2400 | 2423 | break; |
2401 | 2424 | } |
2402 | 2425 | out_drop_write: |
2403 | - mnt_drop_write(nd.path.mnt); | |
2426 | + mnt_drop_write(path.mnt); | |
2404 | 2427 | out_dput: |
2405 | 2428 | dput(dentry); |
2406 | -out_unlock: | |
2407 | - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
2408 | - path_put(&nd.path); | |
2409 | - putname(tmp); | |
2429 | + mutex_unlock(&path.dentry->d_inode->i_mutex); | |
2430 | + path_put(&path); | |
2410 | 2431 | |
2411 | 2432 | return error; |
2412 | 2433 | } |
2413 | 2434 | |
2414 | 2435 | |
2415 | 2436 | |
2416 | 2437 | |
2417 | 2438 | |
2418 | 2439 | |
2419 | 2440 | |
2420 | 2441 | |
2421 | 2442 | |
... | ... | @@ -2439,38 +2460,29 @@ |
2439 | 2460 | |
2440 | 2461 | SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode) |
2441 | 2462 | { |
2442 | - int error = 0; | |
2443 | - char * tmp; | |
2444 | 2463 | struct dentry *dentry; |
2445 | - struct nameidata nd; | |
2464 | + struct path path; | |
2465 | + int error; | |
2446 | 2466 | |
2447 | - error = user_path_parent(dfd, pathname, &nd, &tmp); | |
2448 | - if (error) | |
2449 | - goto out_err; | |
2450 | - | |
2451 | - dentry = lookup_create(&nd, 1); | |
2452 | - error = PTR_ERR(dentry); | |
2467 | + dentry = user_path_create(dfd, pathname, &path, 1); | |
2453 | 2468 | if (IS_ERR(dentry)) |
2454 | - goto out_unlock; | |
2469 | + return PTR_ERR(dentry); | |
2455 | 2470 | |
2456 | - if (!IS_POSIXACL(nd.path.dentry->d_inode)) | |
2471 | + if (!IS_POSIXACL(path.dentry->d_inode)) | |
2457 | 2472 | mode &= ~current_umask(); |
2458 | - error = mnt_want_write(nd.path.mnt); | |
2473 | + error = mnt_want_write(path.mnt); | |
2459 | 2474 | if (error) |
2460 | 2475 | goto out_dput; |
2461 | - error = security_path_mkdir(&nd.path, dentry, mode); | |
2476 | + error = security_path_mkdir(&path, dentry, mode); | |
2462 | 2477 | if (error) |
2463 | 2478 | goto out_drop_write; |
2464 | - error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); | |
2479 | + error = vfs_mkdir(path.dentry->d_inode, dentry, mode); | |
2465 | 2480 | out_drop_write: |
2466 | - mnt_drop_write(nd.path.mnt); | |
2481 | + mnt_drop_write(path.mnt); | |
2467 | 2482 | out_dput: |
2468 | 2483 | dput(dentry); |
2469 | -out_unlock: | |
2470 | - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
2471 | - path_put(&nd.path); | |
2472 | - putname(tmp); | |
2473 | -out_err: | |
2484 | + mutex_unlock(&path.dentry->d_inode->i_mutex); | |
2485 | + path_put(&path); | |
2474 | 2486 | return error; |
2475 | 2487 | } |
2476 | 2488 | |
2477 | 2489 | |
2478 | 2490 | |
2479 | 2491 | |
2480 | 2492 | |
2481 | 2493 | |
2482 | 2494 | |
2483 | 2495 | |
2484 | 2496 | |
... | ... | @@ -2730,38 +2742,31 @@ |
2730 | 2742 | { |
2731 | 2743 | int error; |
2732 | 2744 | char *from; |
2733 | - char *to; | |
2734 | 2745 | struct dentry *dentry; |
2735 | - struct nameidata nd; | |
2746 | + struct path path; | |
2736 | 2747 | |
2737 | 2748 | from = getname(oldname); |
2738 | 2749 | if (IS_ERR(from)) |
2739 | 2750 | return PTR_ERR(from); |
2740 | 2751 | |
2741 | - error = user_path_parent(newdfd, newname, &nd, &to); | |
2742 | - if (error) | |
2743 | - goto out_putname; | |
2744 | - | |
2745 | - dentry = lookup_create(&nd, 0); | |
2752 | + dentry = user_path_create(newdfd, newname, &path, 0); | |
2746 | 2753 | error = PTR_ERR(dentry); |
2747 | 2754 | if (IS_ERR(dentry)) |
2748 | - goto out_unlock; | |
2755 | + goto out_putname; | |
2749 | 2756 | |
2750 | - error = mnt_want_write(nd.path.mnt); | |
2757 | + error = mnt_want_write(path.mnt); | |
2751 | 2758 | if (error) |
2752 | 2759 | goto out_dput; |
2753 | - error = security_path_symlink(&nd.path, dentry, from); | |
2760 | + error = security_path_symlink(&path, dentry, from); | |
2754 | 2761 | if (error) |
2755 | 2762 | goto out_drop_write; |
2756 | - error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); | |
2763 | + error = vfs_symlink(path.dentry->d_inode, dentry, from); | |
2757 | 2764 | out_drop_write: |
2758 | - mnt_drop_write(nd.path.mnt); | |
2765 | + mnt_drop_write(path.mnt); | |
2759 | 2766 | out_dput: |
2760 | 2767 | dput(dentry); |
2761 | -out_unlock: | |
2762 | - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
2763 | - path_put(&nd.path); | |
2764 | - putname(to); | |
2768 | + mutex_unlock(&path.dentry->d_inode->i_mutex); | |
2769 | + path_put(&path); | |
2765 | 2770 | out_putname: |
2766 | 2771 | putname(from); |
2767 | 2772 | return error; |
2768 | 2773 | |
... | ... | @@ -2826,11 +2831,9 @@ |
2826 | 2831 | int, newdfd, const char __user *, newname, int, flags) |
2827 | 2832 | { |
2828 | 2833 | struct dentry *new_dentry; |
2829 | - struct nameidata nd; | |
2830 | - struct path old_path; | |
2834 | + struct path old_path, new_path; | |
2831 | 2835 | int how = 0; |
2832 | 2836 | int error; |
2833 | - char *to; | |
2834 | 2837 | |
2835 | 2838 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) |
2836 | 2839 | return -EINVAL; |
2837 | 2840 | |
2838 | 2841 | |
2839 | 2842 | |
2840 | 2843 | |
2841 | 2844 | |
... | ... | @@ -2852,32 +2855,27 @@ |
2852 | 2855 | if (error) |
2853 | 2856 | return error; |
2854 | 2857 | |
2855 | - error = user_path_parent(newdfd, newname, &nd, &to); | |
2856 | - if (error) | |
2857 | - goto out; | |
2858 | - error = -EXDEV; | |
2859 | - if (old_path.mnt != nd.path.mnt) | |
2860 | - goto out_release; | |
2861 | - new_dentry = lookup_create(&nd, 0); | |
2858 | + new_dentry = user_path_create(newdfd, newname, &new_path, 0); | |
2862 | 2859 | error = PTR_ERR(new_dentry); |
2863 | 2860 | if (IS_ERR(new_dentry)) |
2864 | - goto out_unlock; | |
2865 | - error = mnt_want_write(nd.path.mnt); | |
2861 | + goto out; | |
2862 | + | |
2863 | + error = -EXDEV; | |
2864 | + if (old_path.mnt != new_path.mnt) | |
2865 | + goto out_dput; | |
2866 | + error = mnt_want_write(new_path.mnt); | |
2866 | 2867 | if (error) |
2867 | 2868 | goto out_dput; |
2868 | - error = security_path_link(old_path.dentry, &nd.path, new_dentry); | |
2869 | + error = security_path_link(old_path.dentry, &new_path, new_dentry); | |
2869 | 2870 | if (error) |
2870 | 2871 | goto out_drop_write; |
2871 | - error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); | |
2872 | + error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry); | |
2872 | 2873 | out_drop_write: |
2873 | - mnt_drop_write(nd.path.mnt); | |
2874 | + mnt_drop_write(new_path.mnt); | |
2874 | 2875 | out_dput: |
2875 | 2876 | dput(new_dentry); |
2876 | -out_unlock: | |
2877 | - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
2878 | -out_release: | |
2879 | - path_put(&nd.path); | |
2880 | - putname(to); | |
2877 | + mutex_unlock(&new_path.dentry->d_inode->i_mutex); | |
2878 | + path_put(&new_path); | |
2881 | 2879 | out: |
2882 | 2880 | path_put(&old_path); |
2883 | 2881 |
fs/ocfs2/refcounttree.c
... | ... | @@ -4368,25 +4368,6 @@ |
4368 | 4368 | return inode_permission(dir, MAY_WRITE | MAY_EXEC); |
4369 | 4369 | } |
4370 | 4370 | |
4371 | -/* copied from user_path_parent. */ | |
4372 | -static int ocfs2_user_path_parent(const char __user *path, | |
4373 | - struct nameidata *nd, char **name) | |
4374 | -{ | |
4375 | - char *s = getname(path); | |
4376 | - int error; | |
4377 | - | |
4378 | - if (IS_ERR(s)) | |
4379 | - return PTR_ERR(s); | |
4380 | - | |
4381 | - error = kern_path_parent(s, nd); | |
4382 | - if (error) | |
4383 | - putname(s); | |
4384 | - else | |
4385 | - *name = s; | |
4386 | - | |
4387 | - return error; | |
4388 | -} | |
4389 | - | |
4390 | 4371 | /** |
4391 | 4372 | * ocfs2_vfs_reflink - Create a reference-counted link |
4392 | 4373 | * |
4393 | 4374 | |
... | ... | @@ -4460,10 +4441,8 @@ |
4460 | 4441 | bool preserve) |
4461 | 4442 | { |
4462 | 4443 | struct dentry *new_dentry; |
4463 | - struct nameidata nd; | |
4464 | - struct path old_path; | |
4444 | + struct path old_path, new_path; | |
4465 | 4445 | int error; |
4466 | - char *to = NULL; | |
4467 | 4446 | |
4468 | 4447 | if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) |
4469 | 4448 | return -EOPNOTSUPP; |
4470 | 4449 | |
4471 | 4450 | |
4472 | 4451 | |
4473 | 4452 | |
4474 | 4453 | |
4475 | 4454 | |
... | ... | @@ -4474,39 +4453,33 @@ |
4474 | 4453 | return error; |
4475 | 4454 | } |
4476 | 4455 | |
4477 | - error = ocfs2_user_path_parent(newname, &nd, &to); | |
4478 | - if (error) { | |
4456 | + new_dentry = user_path_create(AT_FDCWD, newname, &new_path, 0); | |
4457 | + error = PTR_ERR(new_dentry); | |
4458 | + if (IS_ERR(new_dentry)) { | |
4479 | 4459 | mlog_errno(error); |
4480 | 4460 | goto out; |
4481 | 4461 | } |
4482 | 4462 | |
4483 | 4463 | error = -EXDEV; |
4484 | - if (old_path.mnt != nd.path.mnt) | |
4485 | - goto out_release; | |
4486 | - new_dentry = lookup_create(&nd, 0); | |
4487 | - error = PTR_ERR(new_dentry); | |
4488 | - if (IS_ERR(new_dentry)) { | |
4464 | + if (old_path.mnt != new_path.mnt) { | |
4489 | 4465 | mlog_errno(error); |
4490 | - goto out_unlock; | |
4466 | + goto out_dput; | |
4491 | 4467 | } |
4492 | 4468 | |
4493 | - error = mnt_want_write(nd.path.mnt); | |
4469 | + error = mnt_want_write(new_path.mnt); | |
4494 | 4470 | if (error) { |
4495 | 4471 | mlog_errno(error); |
4496 | 4472 | goto out_dput; |
4497 | 4473 | } |
4498 | 4474 | |
4499 | 4475 | error = ocfs2_vfs_reflink(old_path.dentry, |
4500 | - nd.path.dentry->d_inode, | |
4476 | + new_path.dentry->d_inode, | |
4501 | 4477 | new_dentry, preserve); |
4502 | - mnt_drop_write(nd.path.mnt); | |
4478 | + mnt_drop_write(new_path.mnt); | |
4503 | 4479 | out_dput: |
4504 | 4480 | dput(new_dentry); |
4505 | -out_unlock: | |
4506 | - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
4507 | -out_release: | |
4508 | - path_put(&nd.path); | |
4509 | - putname(to); | |
4481 | + mutex_unlock(&new_path.dentry->d_inode->i_mutex); | |
4482 | + path_put(&new_path); | |
4510 | 4483 | out: |
4511 | 4484 | path_put(&old_path); |
4512 | 4485 |
include/linux/namei.h
... | ... | @@ -74,6 +74,8 @@ |
74 | 74 | |
75 | 75 | extern int kern_path(const char *, unsigned, struct path *); |
76 | 76 | |
77 | +extern struct dentry *kern_path_create(int, const char *, struct path *, int); | |
78 | +extern struct dentry *user_path_create(int, const char __user *, struct path *, int); | |
77 | 79 | extern int kern_path_parent(const char *, struct nameidata *); |
78 | 80 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, |
79 | 81 | const char *, unsigned int, struct nameidata *); |
net/unix/af_unix.c
... | ... | @@ -808,8 +808,9 @@ |
808 | 808 | struct net *net = sock_net(sk); |
809 | 809 | struct unix_sock *u = unix_sk(sk); |
810 | 810 | struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
811 | + char *sun_path = sunaddr->sun_path; | |
811 | 812 | struct dentry *dentry = NULL; |
812 | - struct nameidata nd; | |
813 | + struct path path; | |
813 | 814 | int err; |
814 | 815 | unsigned hash; |
815 | 816 | struct unix_address *addr; |
816 | 817 | |
817 | 818 | |
818 | 819 | |
819 | 820 | |
820 | 821 | |
821 | 822 | |
822 | 823 | |
823 | 824 | |
... | ... | @@ -845,48 +846,44 @@ |
845 | 846 | addr->hash = hash ^ sk->sk_type; |
846 | 847 | atomic_set(&addr->refcnt, 1); |
847 | 848 | |
848 | - if (sunaddr->sun_path[0]) { | |
849 | + if (sun_path[0]) { | |
849 | 850 | unsigned int mode; |
850 | 851 | err = 0; |
851 | 852 | /* |
852 | 853 | * Get the parent directory, calculate the hash for last |
853 | 854 | * component. |
854 | 855 | */ |
855 | - err = kern_path_parent(sunaddr->sun_path, &nd); | |
856 | - if (err) | |
857 | - goto out_mknod_parent; | |
858 | - | |
859 | - dentry = lookup_create(&nd, 0); | |
856 | + dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); | |
860 | 857 | err = PTR_ERR(dentry); |
861 | 858 | if (IS_ERR(dentry)) |
862 | - goto out_mknod_unlock; | |
859 | + goto out_mknod_parent; | |
863 | 860 | |
864 | 861 | /* |
865 | 862 | * All right, let's create it. |
866 | 863 | */ |
867 | 864 | mode = S_IFSOCK | |
868 | 865 | (SOCK_INODE(sock)->i_mode & ~current_umask()); |
869 | - err = mnt_want_write(nd.path.mnt); | |
866 | + err = mnt_want_write(path.mnt); | |
870 | 867 | if (err) |
871 | 868 | goto out_mknod_dput; |
872 | - err = security_path_mknod(&nd.path, dentry, mode, 0); | |
869 | + err = security_path_mknod(&path, dentry, mode, 0); | |
873 | 870 | if (err) |
874 | 871 | goto out_mknod_drop_write; |
875 | - err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); | |
872 | + err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0); | |
876 | 873 | out_mknod_drop_write: |
877 | - mnt_drop_write(nd.path.mnt); | |
874 | + mnt_drop_write(path.mnt); | |
878 | 875 | if (err) |
879 | 876 | goto out_mknod_dput; |
880 | - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
881 | - dput(nd.path.dentry); | |
882 | - nd.path.dentry = dentry; | |
877 | + mutex_unlock(&path.dentry->d_inode->i_mutex); | |
878 | + dput(path.dentry); | |
879 | + path.dentry = dentry; | |
883 | 880 | |
884 | 881 | addr->hash = UNIX_HASH_SIZE; |
885 | 882 | } |
886 | 883 | |
887 | 884 | spin_lock(&unix_table_lock); |
888 | 885 | |
889 | - if (!sunaddr->sun_path[0]) { | |
886 | + if (!sun_path[0]) { | |
890 | 887 | err = -EADDRINUSE; |
891 | 888 | if (__unix_find_socket_byname(net, sunaddr, addr_len, |
892 | 889 | sk->sk_type, hash)) { |
... | ... | @@ -897,8 +894,8 @@ |
897 | 894 | list = &unix_socket_table[addr->hash]; |
898 | 895 | } else { |
899 | 896 | list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; |
900 | - u->dentry = nd.path.dentry; | |
901 | - u->mnt = nd.path.mnt; | |
897 | + u->dentry = path.dentry; | |
898 | + u->mnt = path.mnt; | |
902 | 899 | } |
903 | 900 | |
904 | 901 | err = 0; |
... | ... | @@ -915,9 +912,8 @@ |
915 | 912 | |
916 | 913 | out_mknod_dput: |
917 | 914 | dput(dentry); |
918 | -out_mknod_unlock: | |
919 | - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | |
920 | - path_put(&nd.path); | |
915 | + mutex_unlock(&path.dentry->d_inode->i_mutex); | |
916 | + path_put(&path); | |
921 | 917 | out_mknod_parent: |
922 | 918 | if (err == -EEXIST) |
923 | 919 | err = -EADDRINUSE; |