Commit dae6ad8f37529963ae7df52baaccf056b38f210e

Authored by Al Viro
1 parent 49084c3bb2

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

... ... @@ -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 *);
... ... @@ -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;