Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

Al Viro dae6ad8f 49084c3b

+106 -137
+76 -78
fs/namei.c
··· 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); ··· 2388 2359 SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode, 2389 2360 unsigned, dev) 2390 2361 { 2391 - int error; 2392 - char *tmp; 2393 2362 struct dentry *dentry; 2394 - struct nameidata nd; 2363 + struct path path; 2364 + int error; 2395 2365 2396 2366 if (S_ISDIR(mode)) 2397 2367 return -EPERM; 2398 2368 2399 - error = user_path_parent(dfd, filename, &nd, &tmp); 2400 - if (error) 2401 - return error; 2369 + dentry = user_path_create(dfd, filename, &path, 0); 2370 + if (IS_ERR(dentry)) 2371 + return PTR_ERR(dentry); 2402 2372 2403 - dentry = lookup_create(&nd, 0); 2404 - if (IS_ERR(dentry)) { 2405 - error = PTR_ERR(dentry); 2406 - goto out_unlock; 2407 - } 2408 - if (!IS_POSIXACL(nd.path.dentry->d_inode)) 2373 + if (!IS_POSIXACL(path.dentry->d_inode)) 2409 2374 mode &= ~current_umask(); 2410 2375 error = may_mknod(mode); 2411 2376 if (error) 2412 2377 goto out_dput; 2413 - error = mnt_want_write(nd.path.mnt); 2378 + error = mnt_want_write(path.mnt); 2414 2379 if (error) 2415 2380 goto out_dput; 2416 - error = security_path_mknod(&nd.path, dentry, mode, dev); 2381 + error = security_path_mknod(&path, dentry, mode, dev); 2417 2382 if (error) 2418 2383 goto out_drop_write; 2419 2384 switch (mode & S_IFMT) { 2420 2385 case 0: case S_IFREG: 2421 - error = vfs_create(nd.path.dentry->d_inode,dentry,mode,NULL); 2386 + error = vfs_create(path.dentry->d_inode,dentry,mode,NULL); 2422 2387 break; 2423 2388 case S_IFCHR: case S_IFBLK: 2424 - error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode, 2389 + error = vfs_mknod(path.dentry->d_inode,dentry,mode, 2425 2390 new_decode_dev(dev)); 2426 2391 break; 2427 2392 case S_IFIFO: case S_IFSOCK: 2428 - error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); 2393 + error = vfs_mknod(path.dentry->d_inode,dentry,mode,0); 2429 2394 break; 2430 2395 } 2431 2396 out_drop_write: 2432 - mnt_drop_write(nd.path.mnt); 2397 + mnt_drop_write(path.mnt); 2433 2398 out_dput: 2434 2399 dput(dentry); 2435 - out_unlock: 2436 - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2437 - path_put(&nd.path); 2438 - putname(tmp); 2400 + mutex_unlock(&path.dentry->d_inode->i_mutex); 2401 + path_put(&path); 2439 2402 2440 2403 return error; 2441 2404 } ··· 2460 2439 2461 2440 SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode) 2462 2441 { 2463 - int error = 0; 2464 - char * tmp; 2465 2442 struct dentry *dentry; 2466 - struct nameidata nd; 2443 + struct path path; 2444 + int error; 2467 2445 2468 - error = user_path_parent(dfd, pathname, &nd, &tmp); 2469 - if (error) 2470 - goto out_err; 2471 - 2472 - dentry = lookup_create(&nd, 1); 2473 - error = PTR_ERR(dentry); 2446 + dentry = user_path_create(dfd, pathname, &path, 1); 2474 2447 if (IS_ERR(dentry)) 2475 - goto out_unlock; 2448 + return PTR_ERR(dentry); 2476 2449 2477 - if (!IS_POSIXACL(nd.path.dentry->d_inode)) 2450 + if (!IS_POSIXACL(path.dentry->d_inode)) 2478 2451 mode &= ~current_umask(); 2479 - error = mnt_want_write(nd.path.mnt); 2452 + error = mnt_want_write(path.mnt); 2480 2453 if (error) 2481 2454 goto out_dput; 2482 - error = security_path_mkdir(&nd.path, dentry, mode); 2455 + error = security_path_mkdir(&path, dentry, mode); 2483 2456 if (error) 2484 2457 goto out_drop_write; 2485 - error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); 2458 + error = vfs_mkdir(path.dentry->d_inode, dentry, mode); 2486 2459 out_drop_write: 2487 - mnt_drop_write(nd.path.mnt); 2460 + mnt_drop_write(path.mnt); 2488 2461 out_dput: 2489 2462 dput(dentry); 2490 - out_unlock: 2491 - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2492 - path_put(&nd.path); 2493 - putname(tmp); 2494 - out_err: 2463 + mutex_unlock(&path.dentry->d_inode->i_mutex); 2464 + path_put(&path); 2495 2465 return error; 2496 2466 } 2497 2467 ··· 2742 2730 { 2743 2731 int error; 2744 2732 char *from; 2745 - char *to; 2746 2733 struct dentry *dentry; 2747 - struct nameidata nd; 2734 + struct path path; 2748 2735 2749 2736 from = getname(oldname); 2750 2737 if (IS_ERR(from)) 2751 2738 return PTR_ERR(from); 2752 2739 2753 - error = user_path_parent(newdfd, newname, &nd, &to); 2754 - if (error) 2755 - goto out_putname; 2756 - 2757 - dentry = lookup_create(&nd, 0); 2740 + dentry = user_path_create(newdfd, newname, &path, 0); 2758 2741 error = PTR_ERR(dentry); 2759 2742 if (IS_ERR(dentry)) 2760 - goto out_unlock; 2743 + goto out_putname; 2761 2744 2762 - error = mnt_want_write(nd.path.mnt); 2745 + error = mnt_want_write(path.mnt); 2763 2746 if (error) 2764 2747 goto out_dput; 2765 - error = security_path_symlink(&nd.path, dentry, from); 2748 + error = security_path_symlink(&path, dentry, from); 2766 2749 if (error) 2767 2750 goto out_drop_write; 2768 - error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); 2751 + error = vfs_symlink(path.dentry->d_inode, dentry, from); 2769 2752 out_drop_write: 2770 - mnt_drop_write(nd.path.mnt); 2753 + mnt_drop_write(path.mnt); 2771 2754 out_dput: 2772 2755 dput(dentry); 2773 - out_unlock: 2774 - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2775 - path_put(&nd.path); 2776 - putname(to); 2756 + mutex_unlock(&path.dentry->d_inode->i_mutex); 2757 + path_put(&path); 2777 2758 out_putname: 2778 2759 putname(from); 2779 2760 return error; ··· 2831 2826 int, newdfd, const char __user *, newname, int, flags) 2832 2827 { 2833 2828 struct dentry *new_dentry; 2834 - struct nameidata nd; 2835 - struct path old_path; 2829 + struct path old_path, new_path; 2836 2830 int how = 0; 2837 2831 int error; 2838 - char *to; 2839 2832 2840 2833 if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) 2841 2834 return -EINVAL; ··· 2855 2852 if (error) 2856 2853 return error; 2857 2854 2858 - error = user_path_parent(newdfd, newname, &nd, &to); 2859 - if (error) 2860 - goto out; 2861 - error = -EXDEV; 2862 - if (old_path.mnt != nd.path.mnt) 2863 - goto out_release; 2864 - new_dentry = lookup_create(&nd, 0); 2855 + new_dentry = user_path_create(newdfd, newname, &new_path, 0); 2865 2856 error = PTR_ERR(new_dentry); 2866 2857 if (IS_ERR(new_dentry)) 2867 - goto out_unlock; 2868 - error = mnt_want_write(nd.path.mnt); 2858 + goto out; 2859 + 2860 + error = -EXDEV; 2861 + if (old_path.mnt != new_path.mnt) 2862 + goto out_dput; 2863 + error = mnt_want_write(new_path.mnt); 2869 2864 if (error) 2870 2865 goto out_dput; 2871 - error = security_path_link(old_path.dentry, &nd.path, new_dentry); 2866 + error = security_path_link(old_path.dentry, &new_path, new_dentry); 2872 2867 if (error) 2873 2868 goto out_drop_write; 2874 - error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); 2869 + error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry); 2875 2870 out_drop_write: 2876 - mnt_drop_write(nd.path.mnt); 2871 + mnt_drop_write(new_path.mnt); 2877 2872 out_dput: 2878 2873 dput(new_dentry); 2879 - out_unlock: 2880 - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2881 - out_release: 2882 - path_put(&nd.path); 2883 - putname(to); 2874 + mutex_unlock(&new_path.dentry->d_inode->i_mutex); 2875 + path_put(&new_path); 2884 2876 out: 2885 2877 path_put(&old_path); 2886 2878
+11 -38
fs/ocfs2/refcounttree.c
··· 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 * ··· 4441 4460 bool preserve) 4442 4461 { 4443 4462 struct dentry *new_dentry; 4444 - struct nameidata nd; 4445 - struct path old_path; 4463 + struct path old_path, new_path; 4446 4464 int error; 4447 - char *to = NULL; 4448 4465 4449 4466 if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) 4450 4467 return -EOPNOTSUPP; ··· 4453 4474 return error; 4454 4475 } 4455 4476 4456 - error = ocfs2_user_path_parent(newname, &nd, &to); 4457 - if (error) { 4477 + new_dentry = user_path_create(AT_FDCWD, newname, &new_path, 0); 4478 + error = PTR_ERR(new_dentry); 4479 + if (IS_ERR(new_dentry)) { 4458 4480 mlog_errno(error); 4459 4481 goto out; 4460 4482 } 4461 4483 4462 4484 error = -EXDEV; 4463 - if (old_path.mnt != nd.path.mnt) 4464 - goto out_release; 4465 - new_dentry = lookup_create(&nd, 0); 4466 - error = PTR_ERR(new_dentry); 4467 - if (IS_ERR(new_dentry)) { 4485 + if (old_path.mnt != new_path.mnt) { 4468 4486 mlog_errno(error); 4469 - goto out_unlock; 4487 + goto out_dput; 4470 4488 } 4471 4489 4472 - error = mnt_want_write(nd.path.mnt); 4490 + error = mnt_want_write(new_path.mnt); 4473 4491 if (error) { 4474 4492 mlog_errno(error); 4475 4493 goto out_dput; 4476 4494 } 4477 4495 4478 4496 error = ocfs2_vfs_reflink(old_path.dentry, 4479 - nd.path.dentry->d_inode, 4497 + new_path.dentry->d_inode, 4480 4498 new_dentry, preserve); 4481 - mnt_drop_write(nd.path.mnt); 4499 + mnt_drop_write(new_path.mnt); 4482 4500 out_dput: 4483 4501 dput(new_dentry); 4484 - out_unlock: 4485 - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 4486 - out_release: 4487 - path_put(&nd.path); 4488 - putname(to); 4502 + mutex_unlock(&new_path.dentry->d_inode->i_mutex); 4503 + path_put(&new_path); 4489 4504 out: 4490 4505 path_put(&old_path); 4491 4506
+2
include/linux/namei.h
··· 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 *);
+17 -21
net/unix/af_unix.c
··· 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; ··· 846 845 addr->hash = hash ^ sk->sk_type; 847 846 atomic_set(&addr->refcnt, 1); 848 847 849 - if (sunaddr->sun_path[0]) { 848 + if (sun_path[0]) { 850 849 unsigned int mode; 851 850 err = 0; 852 851 /* 853 852 * Get the parent directory, calculate the hash for last 854 853 * component. 855 854 */ 856 - err = kern_path_parent(sunaddr->sun_path, &nd); 857 - if (err) 858 - goto out_mknod_parent; 859 - 860 - dentry = lookup_create(&nd, 0); 855 + dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); 861 856 err = PTR_ERR(dentry); 862 857 if (IS_ERR(dentry)) 863 - goto out_mknod_unlock; 858 + goto out_mknod_parent; 864 859 865 860 /* 866 861 * All right, let's create it. 867 862 */ 868 863 mode = S_IFSOCK | 869 864 (SOCK_INODE(sock)->i_mode & ~current_umask()); 870 - err = mnt_want_write(nd.path.mnt); 865 + err = mnt_want_write(path.mnt); 871 866 if (err) 872 867 goto out_mknod_dput; 873 - err = security_path_mknod(&nd.path, dentry, mode, 0); 868 + err = security_path_mknod(&path, dentry, mode, 0); 874 869 if (err) 875 870 goto out_mknod_drop_write; 876 - err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); 871 + err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0); 877 872 out_mknod_drop_write: 878 - mnt_drop_write(nd.path.mnt); 873 + mnt_drop_write(path.mnt); 879 874 if (err) 880 875 goto out_mknod_dput; 881 - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 882 - dput(nd.path.dentry); 883 - nd.path.dentry = dentry; 876 + mutex_unlock(&path.dentry->d_inode->i_mutex); 877 + dput(path.dentry); 878 + path.dentry = dentry; 884 879 885 880 addr->hash = UNIX_HASH_SIZE; 886 881 } 887 882 888 883 spin_lock(&unix_table_lock); 889 884 890 - if (!sunaddr->sun_path[0]) { 885 + if (!sun_path[0]) { 891 886 err = -EADDRINUSE; 892 887 if (__unix_find_socket_byname(net, sunaddr, addr_len, 893 888 sk->sk_type, hash)) { ··· 894 897 list = &unix_socket_table[addr->hash]; 895 898 } else { 896 899 list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; 897 - u->dentry = nd.path.dentry; 898 - u->mnt = nd.path.mnt; 900 + u->dentry = path.dentry; 901 + u->mnt = path.mnt; 899 902 } 900 903 901 904 err = 0; ··· 912 915 913 916 out_mknod_dput: 914 917 dput(dentry); 915 - out_mknod_unlock: 916 - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 917 - path_put(&nd.path); 918 + mutex_unlock(&path.dentry->d_inode->i_mutex); 919 + path_put(&path); 918 920 out_mknod_parent: 919 921 if (err == -EEXIST) 920 922 err = -EADDRINUSE;