diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 39 |
1 files changed, 19 insertions, 20 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 4d2c8f64b7bf..a830e1463704 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -2609,18 +2609,18 @@ static long exact_copy_from_user(void *to, const void __user * from, | |||
2609 | return n; | 2609 | return n; |
2610 | } | 2610 | } |
2611 | 2611 | ||
2612 | int copy_mount_options(const void __user * data, unsigned long *where) | 2612 | void *copy_mount_options(const void __user * data) |
2613 | { | 2613 | { |
2614 | int i; | 2614 | int i; |
2615 | unsigned long page; | ||
2616 | unsigned long size; | 2615 | unsigned long size; |
2616 | char *copy; | ||
2617 | 2617 | ||
2618 | *where = 0; | ||
2619 | if (!data) | 2618 | if (!data) |
2620 | return 0; | 2619 | return NULL; |
2621 | 2620 | ||
2622 | if (!(page = __get_free_page(GFP_KERNEL))) | 2621 | copy = kmalloc(PAGE_SIZE, GFP_KERNEL); |
2623 | return -ENOMEM; | 2622 | if (!copy) |
2623 | return ERR_PTR(-ENOMEM); | ||
2624 | 2624 | ||
2625 | /* We only care that *some* data at the address the user | 2625 | /* We only care that *some* data at the address the user |
2626 | * gave us is valid. Just in case, we'll zero | 2626 | * gave us is valid. Just in case, we'll zero |
@@ -2631,15 +2631,14 @@ int copy_mount_options(const void __user * data, unsigned long *where) | |||
2631 | if (size > PAGE_SIZE) | 2631 | if (size > PAGE_SIZE) |
2632 | size = PAGE_SIZE; | 2632 | size = PAGE_SIZE; |
2633 | 2633 | ||
2634 | i = size - exact_copy_from_user((void *)page, data, size); | 2634 | i = size - exact_copy_from_user(copy, data, size); |
2635 | if (!i) { | 2635 | if (!i) { |
2636 | free_page(page); | 2636 | kfree(copy); |
2637 | return -EFAULT; | 2637 | return ERR_PTR(-EFAULT); |
2638 | } | 2638 | } |
2639 | if (i != PAGE_SIZE) | 2639 | if (i != PAGE_SIZE) |
2640 | memset((char *)page + i, 0, PAGE_SIZE - i); | 2640 | memset(copy + i, 0, PAGE_SIZE - i); |
2641 | *where = page; | 2641 | return copy; |
2642 | return 0; | ||
2643 | } | 2642 | } |
2644 | 2643 | ||
2645 | char *copy_mount_string(const void __user *data) | 2644 | char *copy_mount_string(const void __user *data) |
@@ -2906,7 +2905,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, | |||
2906 | int ret; | 2905 | int ret; |
2907 | char *kernel_type; | 2906 | char *kernel_type; |
2908 | char *kernel_dev; | 2907 | char *kernel_dev; |
2909 | unsigned long data_page; | 2908 | void *options; |
2910 | 2909 | ||
2911 | kernel_type = copy_mount_string(type); | 2910 | kernel_type = copy_mount_string(type); |
2912 | ret = PTR_ERR(kernel_type); | 2911 | ret = PTR_ERR(kernel_type); |
@@ -2918,14 +2917,14 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, | |||
2918 | if (IS_ERR(kernel_dev)) | 2917 | if (IS_ERR(kernel_dev)) |
2919 | goto out_dev; | 2918 | goto out_dev; |
2920 | 2919 | ||
2921 | ret = copy_mount_options(data, &data_page); | 2920 | options = copy_mount_options(data); |
2922 | if (ret < 0) | 2921 | ret = PTR_ERR(options); |
2922 | if (IS_ERR(options)) | ||
2923 | goto out_data; | 2923 | goto out_data; |
2924 | 2924 | ||
2925 | ret = do_mount(kernel_dev, dir_name, kernel_type, flags, | 2925 | ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options); |
2926 | (void *) data_page); | ||
2927 | 2926 | ||
2928 | free_page(data_page); | 2927 | kfree(options); |
2929 | out_data: | 2928 | out_data: |
2930 | kfree(kernel_dev); | 2929 | kfree(kernel_dev); |
2931 | out_dev: | 2930 | out_dev: |
@@ -2949,9 +2948,9 @@ bool is_path_reachable(struct mount *mnt, struct dentry *dentry, | |||
2949 | return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry); | 2948 | return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry); |
2950 | } | 2949 | } |
2951 | 2950 | ||
2952 | int path_is_under(struct path *path1, struct path *path2) | 2951 | bool path_is_under(struct path *path1, struct path *path2) |
2953 | { | 2952 | { |
2954 | int res; | 2953 | bool res; |
2955 | read_seqlock_excl(&mount_lock); | 2954 | read_seqlock_excl(&mount_lock); |
2956 | res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2); | 2955 | res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2); |
2957 | read_sequnlock_excl(&mount_lock); | 2956 | read_sequnlock_excl(&mount_lock); |