aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c39
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
2612int copy_mount_options(const void __user * data, unsigned long *where) 2612void *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
2645char *copy_mount_string(const void __user *data) 2644char *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);
2929out_data: 2928out_data:
2930 kfree(kernel_dev); 2929 kfree(kernel_dev);
2931out_dev: 2930out_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
2952int path_is_under(struct path *path1, struct path *path2) 2951bool 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);