diff options
-rw-r--r-- | fs/compat.c | 21 | ||||
-rw-r--r-- | fs/internal.h | 2 | ||||
-rw-r--r-- | fs/namespace.c | 35 |
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 | */ |
58 | extern int copy_mount_options(const void __user *, unsigned long *); | 58 | extern void *copy_mount_options(const void __user *); |
59 | extern char *copy_mount_string(const void __user *); | 59 | extern char *copy_mount_string(const void __user *); |
60 | 60 | ||
61 | extern struct vfsmount *lookup_mnt(struct path *); | 61 | extern 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 | ||
2604 | int copy_mount_options(const void __user * data, unsigned long *where) | 2604 | void *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 | ||
2637 | char *copy_mount_string(const void __user *data) | 2636 | char *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); |
2919 | out_data: | 2918 | out_data: |
2920 | kfree(kernel_dev); | 2919 | kfree(kernel_dev); |
2921 | out_dev: | 2920 | out_dev: |