diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 154 |
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 | } |
2312 | EXPORT_SYMBOL_GPL(lookup_create); | 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 | int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | 2343 | int 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) | |||
2359 | SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode, | 2388 | SYSCALL_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 | } |
2402 | out_drop_write: | 2425 | out_drop_write: |
2403 | mnt_drop_write(nd.path.mnt); | 2426 | mnt_drop_write(path.mnt); |
2404 | out_dput: | 2427 | out_dput: |
2405 | dput(dentry); | 2428 | dput(dentry); |
2406 | out_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 | ||
2440 | SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode) | 2461 | SYSCALL_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); |
2465 | out_drop_write: | 2480 | out_drop_write: |
2466 | mnt_drop_write(nd.path.mnt); | 2481 | mnt_drop_write(path.mnt); |
2467 | out_dput: | 2482 | out_dput: |
2468 | dput(dentry); | 2483 | dput(dentry); |
2469 | out_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); | ||
2473 | out_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); |
2757 | out_drop_write: | 2764 | out_drop_write: |
2758 | mnt_drop_write(nd.path.mnt); | 2765 | mnt_drop_write(path.mnt); |
2759 | out_dput: | 2766 | out_dput: |
2760 | dput(dentry); | 2767 | dput(dentry); |
2761 | out_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); | ||
2765 | out_putname: | 2770 | out_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); |
2872 | out_drop_write: | 2873 | out_drop_write: |
2873 | mnt_drop_write(nd.path.mnt); | 2874 | mnt_drop_write(new_path.mnt); |
2874 | out_dput: | 2875 | out_dput: |
2875 | dput(new_dentry); | 2876 | dput(new_dentry); |
2876 | out_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); |
2878 | out_release: | ||
2879 | path_put(&nd.path); | ||
2880 | putname(to); | ||
2881 | out: | 2879 | out: |
2882 | path_put(&old_path); | 2880 | path_put(&old_path); |
2883 | 2881 | ||