summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/compat.c21
-rw-r--r--fs/internal.h2
-rw-r--r--fs/namespace.c35
3 files changed, 28 insertions, 30 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 6fd272d455e4..a71936a3f4cb 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -792,7 +792,7 @@ COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
792 const void __user *, data) 792 const void __user *, data)
793{ 793{
794 char *kernel_type; 794 char *kernel_type;
795 unsigned long data_page; 795 void *options;
796 char *kernel_dev; 796 char *kernel_dev;
797 int retval; 797 int retval;
798 798
@@ -806,26 +806,25 @@ COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
806 if (IS_ERR(kernel_dev)) 806 if (IS_ERR(kernel_dev))
807 goto out1; 807 goto out1;
808 808
809 retval = copy_mount_options(data, &data_page); 809 options = copy_mount_options(data);
810 if (retval < 0) 810 retval = PTR_ERR(options);
811 if (IS_ERR(options))
811 goto out2; 812 goto out2;
812 813
813 retval = -EINVAL; 814 if (kernel_type && options) {
814
815 if (kernel_type && data_page) {
816 if (!strcmp(kernel_type, NCPFS_NAME)) { 815 if (!strcmp(kernel_type, NCPFS_NAME)) {
817 do_ncp_super_data_conv((void *)data_page); 816 do_ncp_super_data_conv(options);
818 } else if (!strcmp(kernel_type, NFS4_NAME)) { 817 } else if (!strcmp(kernel_type, NFS4_NAME)) {
819 if (do_nfs4_super_data_conv((void *) data_page)) 818 retval = -EINVAL;
819 if (do_nfs4_super_data_conv(options))
820 goto out3; 820 goto out3;
821 } 821 }
822 } 822 }
823 823
824 retval = do_mount(kernel_dev, dir_name, kernel_type, 824 retval = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
825 flags, (void*)data_page);
826 825
827 out3: 826 out3:
828 free_page(data_page); 827 kfree(options);
829 out2: 828 out2:
830 kfree(kernel_dev); 829 kfree(kernel_dev);
831 out1: 830 out1:
diff --git a/fs/internal.h b/fs/internal.h
index 71859c4d0b41..aa81316aaf47 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -55,7 +55,7 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
55/* 55/*
56 * namespace.c 56 * namespace.c
57 */ 57 */
58extern int copy_mount_options(const void __user *, unsigned long *); 58extern void *copy_mount_options(const void __user *);
59extern char *copy_mount_string(const void __user *); 59extern char *copy_mount_string(const void __user *);
60 60
61extern struct vfsmount *lookup_mnt(struct path *); 61extern struct vfsmount *lookup_mnt(struct path *);
diff --git a/fs/namespace.c b/fs/namespace.c
index b27156f2e68b..33a75c8e9fcb 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2601,18 +2601,18 @@ static long exact_copy_from_user(void *to, const void __user * from,
2601 return n; 2601 return n;
2602} 2602}
2603 2603
2604int copy_mount_options(const void __user * data, unsigned long *where) 2604void *copy_mount_options(const void __user * data)
2605{ 2605{
2606 int i; 2606 int i;
2607 unsigned long page;
2608 unsigned long size; 2607 unsigned long size;
2608 char *copy;
2609 2609
2610 *where = 0;
2611 if (!data) 2610 if (!data)
2612 return 0; 2611 return NULL;
2613 2612
2614 if (!(page = __get_free_page(GFP_KERNEL))) 2613 copy = kmalloc(PAGE_SIZE, GFP_KERNEL);
2615 return -ENOMEM; 2614 if (!copy)
2615 return ERR_PTR(-ENOMEM);
2616 2616
2617 /* We only care that *some* data at the address the user 2617 /* We only care that *some* data at the address the user
2618 * gave us is valid. Just in case, we'll zero 2618 * gave us is valid. Just in case, we'll zero
@@ -2623,15 +2623,14 @@ int copy_mount_options(const void __user * data, unsigned long *where)
2623 if (size > PAGE_SIZE) 2623 if (size > PAGE_SIZE)
2624 size = PAGE_SIZE; 2624 size = PAGE_SIZE;
2625 2625
2626 i = size - exact_copy_from_user((void *)page, data, size); 2626 i = size - exact_copy_from_user(copy, data, size);
2627 if (!i) { 2627 if (!i) {
2628 free_page(page); 2628 kfree(copy);
2629 return -EFAULT; 2629 return ERR_PTR(-EFAULT);
2630 } 2630 }
2631 if (i != PAGE_SIZE) 2631 if (i != PAGE_SIZE)
2632 memset((char *)page + i, 0, PAGE_SIZE - i); 2632 memset(copy + i, 0, PAGE_SIZE - i);
2633 *where = page; 2633 return copy;
2634 return 0;
2635} 2634}
2636 2635
2637char *copy_mount_string(const void __user *data) 2636char *copy_mount_string(const void __user *data)
@@ -2896,7 +2895,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
2896 int ret; 2895 int ret;
2897 char *kernel_type; 2896 char *kernel_type;
2898 char *kernel_dev; 2897 char *kernel_dev;
2899 unsigned long data_page; 2898 void *options;
2900 2899
2901 kernel_type = copy_mount_string(type); 2900 kernel_type = copy_mount_string(type);
2902 ret = PTR_ERR(kernel_type); 2901 ret = PTR_ERR(kernel_type);
@@ -2908,14 +2907,14 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
2908 if (IS_ERR(kernel_dev)) 2907 if (IS_ERR(kernel_dev))
2909 goto out_dev; 2908 goto out_dev;
2910 2909
2911 ret = copy_mount_options(data, &data_page); 2910 options = copy_mount_options(data);
2912 if (ret < 0) 2911 ret = PTR_ERR(options);
2912 if (IS_ERR(options))
2913 goto out_data; 2913 goto out_data;
2914 2914
2915 ret = do_mount(kernel_dev, dir_name, kernel_type, flags, 2915 ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
2916 (void *) data_page);
2917 2916
2918 free_page(data_page); 2917 kfree(options);
2919out_data: 2918out_data:
2920 kfree(kernel_dev); 2919 kfree(kernel_dev);
2921out_dev: 2920out_dev: