aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c154
1 files changed, 76 insertions, 78 deletions
diff --git a/fs/namei.c b/fs/namei.c
index f49d6abfa799..b292eb03d9d2 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2311,6 +2311,35 @@ fail:
2311} 2311}
2312EXPORT_SYMBOL_GPL(lookup_create); 2312EXPORT_SYMBOL_GPL(lookup_create);
2313 2313
2314struct 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}
2329EXPORT_SYMBOL(kern_path_create);
2330
2331struct 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}
2341EXPORT_SYMBOL(user_path_create);
2342
2314int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) 2343int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2315{ 2344{
2316 int error = may_create(dir, dentry); 2345 int error = may_create(dir, dentry);
@@ -2359,54 +2388,46 @@ static int may_mknod(mode_t mode)
2359SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode, 2388SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode,
2360 unsigned, dev) 2389 unsigned, dev)
2361{ 2390{
2362 int error;
2363 char *tmp;
2364 struct dentry *dentry; 2391 struct dentry *dentry;
2365 struct nameidata nd; 2392 struct path path;
2393 int error;
2366 2394
2367 if (S_ISDIR(mode)) 2395 if (S_ISDIR(mode))
2368 return -EPERM; 2396 return -EPERM;
2369 2397
2370 error = user_path_parent(dfd, filename, &nd, &tmp); 2398 dentry = user_path_create(dfd, filename, &path, 0);
2371 if (error) 2399 if (IS_ERR(dentry))
2372 return error; 2400 return PTR_ERR(dentry);
2373 2401
2374 dentry = lookup_create(&nd, 0); 2402 if (!IS_POSIXACL(path.dentry->d_inode))
2375 if (IS_ERR(dentry)) {
2376 error = PTR_ERR(dentry);
2377 goto out_unlock;
2378 }
2379 if (!IS_POSIXACL(nd.path.dentry->d_inode))
2380 mode &= ~current_umask(); 2403 mode &= ~current_umask();
2381 error = may_mknod(mode); 2404 error = may_mknod(mode);
2382 if (error) 2405 if (error)
2383 goto out_dput; 2406 goto out_dput;
2384 error = mnt_want_write(nd.path.mnt); 2407 error = mnt_want_write(path.mnt);
2385 if (error) 2408 if (error)
2386 goto out_dput; 2409 goto out_dput;
2387 error = security_path_mknod(&nd.path, dentry, mode, dev); 2410 error = security_path_mknod(&path, dentry, mode, dev);
2388 if (error) 2411 if (error)
2389 goto out_drop_write; 2412 goto out_drop_write;
2390 switch (mode & S_IFMT) { 2413 switch (mode & S_IFMT) {
2391 case 0: case S_IFREG: 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 break; 2416 break;
2394 case S_IFCHR: case S_IFBLK: 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 new_decode_dev(dev)); 2419 new_decode_dev(dev));
2397 break; 2420 break;
2398 case S_IFIFO: case S_IFSOCK: 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 break; 2423 break;
2401 } 2424 }
2402out_drop_write: 2425out_drop_write:
2403 mnt_drop_write(nd.path.mnt); 2426 mnt_drop_write(path.mnt);
2404out_dput: 2427out_dput:
2405 dput(dentry); 2428 dput(dentry);
2406out_unlock: 2429 mutex_unlock(&path.dentry->d_inode->i_mutex);
2407 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2430 path_put(&path);
2408 path_put(&nd.path);
2409 putname(tmp);
2410 2431
2411 return error; 2432 return error;
2412} 2433}
@@ -2439,38 +2460,29 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
2439 2460
2440SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode) 2461SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode)
2441{ 2462{
2442 int error = 0;
2443 char * tmp;
2444 struct dentry *dentry; 2463 struct dentry *dentry;
2445 struct nameidata nd; 2464 struct path path;
2446 2465 int error;
2447 error = user_path_parent(dfd, pathname, &nd, &tmp);
2448 if (error)
2449 goto out_err;
2450 2466
2451 dentry = lookup_create(&nd, 1); 2467 dentry = user_path_create(dfd, pathname, &path, 1);
2452 error = PTR_ERR(dentry);
2453 if (IS_ERR(dentry)) 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 mode &= ~current_umask(); 2472 mode &= ~current_umask();
2458 error = mnt_want_write(nd.path.mnt); 2473 error = mnt_want_write(path.mnt);
2459 if (error) 2474 if (error)
2460 goto out_dput; 2475 goto out_dput;
2461 error = security_path_mkdir(&nd.path, dentry, mode); 2476 error = security_path_mkdir(&path, dentry, mode);
2462 if (error) 2477 if (error)
2463 goto out_drop_write; 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);
2465out_drop_write: 2480out_drop_write:
2466 mnt_drop_write(nd.path.mnt); 2481 mnt_drop_write(path.mnt);
2467out_dput: 2482out_dput:
2468 dput(dentry); 2483 dput(dentry);
2469out_unlock: 2484 mutex_unlock(&path.dentry->d_inode->i_mutex);
2470 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2485 path_put(&path);
2471 path_put(&nd.path);
2472 putname(tmp);
2473out_err:
2474 return error; 2486 return error;
2475} 2487}
2476 2488
@@ -2730,38 +2742,31 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
2730{ 2742{
2731 int error; 2743 int error;
2732 char *from; 2744 char *from;
2733 char *to;
2734 struct dentry *dentry; 2745 struct dentry *dentry;
2735 struct nameidata nd; 2746 struct path path;
2736 2747
2737 from = getname(oldname); 2748 from = getname(oldname);
2738 if (IS_ERR(from)) 2749 if (IS_ERR(from))
2739 return PTR_ERR(from); 2750 return PTR_ERR(from);
2740 2751
2741 error = user_path_parent(newdfd, newname, &nd, &to); 2752 dentry = user_path_create(newdfd, newname, &path, 0);
2742 if (error)
2743 goto out_putname;
2744
2745 dentry = lookup_create(&nd, 0);
2746 error = PTR_ERR(dentry); 2753 error = PTR_ERR(dentry);
2747 if (IS_ERR(dentry)) 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 if (error) 2758 if (error)
2752 goto out_dput; 2759 goto out_dput;
2753 error = security_path_symlink(&nd.path, dentry, from); 2760 error = security_path_symlink(&path, dentry, from);
2754 if (error) 2761 if (error)
2755 goto out_drop_write; 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);
2757out_drop_write: 2764out_drop_write:
2758 mnt_drop_write(nd.path.mnt); 2765 mnt_drop_write(path.mnt);
2759out_dput: 2766out_dput:
2760 dput(dentry); 2767 dput(dentry);
2761out_unlock: 2768 mutex_unlock(&path.dentry->d_inode->i_mutex);
2762 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2769 path_put(&path);
2763 path_put(&nd.path);
2764 putname(to);
2765out_putname: 2770out_putname:
2766 putname(from); 2771 putname(from);
2767 return error; 2772 return error;
@@ -2826,11 +2831,9 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
2826 int, newdfd, const char __user *, newname, int, flags) 2831 int, newdfd, const char __user *, newname, int, flags)
2827{ 2832{
2828 struct dentry *new_dentry; 2833 struct dentry *new_dentry;
2829 struct nameidata nd; 2834 struct path old_path, new_path;
2830 struct path old_path;
2831 int how = 0; 2835 int how = 0;
2832 int error; 2836 int error;
2833 char *to;
2834 2837
2835 if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) 2838 if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
2836 return -EINVAL; 2839 return -EINVAL;
@@ -2852,32 +2855,27 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
2852 if (error) 2855 if (error)
2853 return error; 2856 return error;
2854 2857
2855 error = user_path_parent(newdfd, newname, &nd, &to); 2858 new_dentry = user_path_create(newdfd, newname, &new_path, 0);
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);
2862 error = PTR_ERR(new_dentry); 2859 error = PTR_ERR(new_dentry);
2863 if (IS_ERR(new_dentry)) 2860 if (IS_ERR(new_dentry))
2864 goto out_unlock; 2861 goto out;
2865 error = mnt_want_write(nd.path.mnt); 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 if (error) 2867 if (error)
2867 goto out_dput; 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 if (error) 2870 if (error)
2870 goto out_drop_write; 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);
2872out_drop_write: 2873out_drop_write:
2873 mnt_drop_write(nd.path.mnt); 2874 mnt_drop_write(new_path.mnt);
2874out_dput: 2875out_dput:
2875 dput(new_dentry); 2876 dput(new_dentry);
2876out_unlock: 2877 mutex_unlock(&new_path.dentry->d_inode->i_mutex);
2877 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2878 path_put(&new_path);
2878out_release:
2879 path_put(&nd.path);
2880 putname(to);
2881out: 2879out:
2882 path_put(&old_path); 2880 path_put(&old_path);
2883 2881