aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/compat.c24
-rw-r--r--fs/internal.h1
-rw-r--r--fs/namespace.c77
3 files changed, 60 insertions, 42 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 3aa48834a222..d576b552e8e2 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -768,13 +768,13 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
768 char __user * type, unsigned long flags, 768 char __user * type, unsigned long flags,
769 void __user * data) 769 void __user * data)
770{ 770{
771 unsigned long type_page; 771 char *kernel_type;
772 unsigned long data_page; 772 unsigned long data_page;
773 unsigned long dev_page; 773 char *kernel_dev;
774 char *dir_page; 774 char *dir_page;
775 int retval; 775 int retval;
776 776
777 retval = copy_mount_options (type, &type_page); 777 retval = copy_mount_string(type, &kernel_type);
778 if (retval < 0) 778 if (retval < 0)
779 goto out; 779 goto out;
780 780
@@ -783,38 +783,38 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
783 if (IS_ERR(dir_page)) 783 if (IS_ERR(dir_page))
784 goto out1; 784 goto out1;
785 785
786 retval = copy_mount_options (dev_name, &dev_page); 786 retval = copy_mount_string(dev_name, &kernel_dev);
787 if (retval < 0) 787 if (retval < 0)
788 goto out2; 788 goto out2;
789 789
790 retval = copy_mount_options (data, &data_page); 790 retval = copy_mount_options(data, &data_page);
791 if (retval < 0) 791 if (retval < 0)
792 goto out3; 792 goto out3;
793 793
794 retval = -EINVAL; 794 retval = -EINVAL;
795 795
796 if (type_page && data_page) { 796 if (kernel_type && data_page) {
797 if (!strcmp((char *)type_page, SMBFS_NAME)) { 797 if (!strcmp(kernel_type, SMBFS_NAME)) {
798 do_smb_super_data_conv((void *)data_page); 798 do_smb_super_data_conv((void *)data_page);
799 } else if (!strcmp((char *)type_page, NCPFS_NAME)) { 799 } else if (!strcmp(kernel_type, NCPFS_NAME)) {
800 do_ncp_super_data_conv((void *)data_page); 800 do_ncp_super_data_conv((void *)data_page);
801 } else if (!strcmp((char *)type_page, NFS4_NAME)) { 801 } else if (!strcmp(kernel_type, NFS4_NAME)) {
802 if (do_nfs4_super_data_conv((void *) data_page)) 802 if (do_nfs4_super_data_conv((void *) data_page))
803 goto out4; 803 goto out4;
804 } 804 }
805 } 805 }
806 806
807 retval = do_mount((char*)dev_page, dir_page, (char*)type_page, 807 retval = do_mount(kernel_dev, dir_page, kernel_type,
808 flags, (void*)data_page); 808 flags, (void*)data_page);
809 809
810 out4: 810 out4:
811 free_page(data_page); 811 free_page(data_page);
812 out3: 812 out3:
813 free_page(dev_page); 813 kfree(kernel_dev);
814 out2: 814 out2:
815 putname(dir_page); 815 putname(dir_page);
816 out1: 816 out1:
817 free_page(type_page); 817 kfree(kernel_type);
818 out: 818 out:
819 return retval; 819 return retval;
820} 820}
diff --git a/fs/internal.h b/fs/internal.h
index d55ef562f0bb..515175b8b72e 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -57,6 +57,7 @@ extern int check_unsafe_exec(struct linux_binprm *);
57 * namespace.c 57 * namespace.c
58 */ 58 */
59extern int copy_mount_options(const void __user *, unsigned long *); 59extern int copy_mount_options(const void __user *, unsigned long *);
60extern int copy_mount_string(const void __user *, char **);
60 61
61extern void free_vfsmnt(struct vfsmount *); 62extern void free_vfsmnt(struct vfsmount *);
62extern struct vfsmount *alloc_vfsmnt(const char *); 63extern struct vfsmount *alloc_vfsmnt(const char *);
diff --git a/fs/namespace.c b/fs/namespace.c
index 7230787d18b0..bdc3cb4fd222 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1640,7 +1640,7 @@ static int do_new_mount(struct path *path, char *type, int flags,
1640{ 1640{
1641 struct vfsmount *mnt; 1641 struct vfsmount *mnt;
1642 1642
1643 if (!type || !memchr(type, 0, PAGE_SIZE)) 1643 if (!type)
1644 return -EINVAL; 1644 return -EINVAL;
1645 1645
1646 /* we need capabilities... */ 1646 /* we need capabilities... */
@@ -1871,6 +1871,23 @@ int copy_mount_options(const void __user * data, unsigned long *where)
1871 return 0; 1871 return 0;
1872} 1872}
1873 1873
1874int copy_mount_string(const void __user *data, char **where)
1875{
1876 char *tmp;
1877
1878 if (!data) {
1879 *where = NULL;
1880 return 0;
1881 }
1882
1883 tmp = strndup_user(data, PAGE_SIZE);
1884 if (IS_ERR(tmp))
1885 return PTR_ERR(tmp);
1886
1887 *where = tmp;
1888 return 0;
1889}
1890
1874/* 1891/*
1875 * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to 1892 * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
1876 * be given to the mount() call (ie: read-only, no-dev, no-suid etc). 1893 * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
@@ -1900,8 +1917,6 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
1900 1917
1901 if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE)) 1918 if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
1902 return -EINVAL; 1919 return -EINVAL;
1903 if (dev_name && !memchr(dev_name, 0, PAGE_SIZE))
1904 return -EINVAL;
1905 1920
1906 if (data_page) 1921 if (data_page)
1907 ((char *)data_page)[PAGE_SIZE - 1] = 0; 1922 ((char *)data_page)[PAGE_SIZE - 1] = 0;
@@ -2070,40 +2085,42 @@ EXPORT_SYMBOL(create_mnt_ns);
2070SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, 2085SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
2071 char __user *, type, unsigned long, flags, void __user *, data) 2086 char __user *, type, unsigned long, flags, void __user *, data)
2072{ 2087{
2073 int retval; 2088 int ret;
2089 char *kernel_type;
2090 char *kernel_dir;
2091 char *kernel_dev;
2074 unsigned long data_page; 2092 unsigned long data_page;
2075 unsigned long type_page;
2076 unsigned long dev_page;
2077 char *dir_page;
2078 2093
2079 retval = copy_mount_options(type, &type_page); 2094 ret = copy_mount_string(type, &kernel_type);
2080 if (retval < 0) 2095 if (ret < 0)
2081 return retval; 2096 goto out_type;
2082 2097
2083 dir_page = getname(dir_name); 2098 kernel_dir = getname(dir_name);
2084 retval = PTR_ERR(dir_page); 2099 if (IS_ERR(kernel_dir)) {
2085 if (IS_ERR(dir_page)) 2100 ret = PTR_ERR(kernel_dir);
2086 goto out1; 2101 goto out_dir;
2102 }
2087 2103
2088 retval = copy_mount_options(dev_name, &dev_page); 2104 ret = copy_mount_string(dev_name, &kernel_dev);
2089 if (retval < 0) 2105 if (ret < 0)
2090 goto out2; 2106 goto out_dev;
2091 2107
2092 retval = copy_mount_options(data, &data_page); 2108 ret = copy_mount_options(data, &data_page);
2093 if (retval < 0) 2109 if (ret < 0)
2094 goto out3; 2110 goto out_data;
2095 2111
2096 retval = do_mount((char *)dev_page, dir_page, (char *)type_page, 2112 ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
2097 flags, (void *)data_page); 2113 (void *) data_page);
2098 free_page(data_page);
2099 2114
2100out3: 2115 free_page(data_page);
2101 free_page(dev_page); 2116out_data:
2102out2: 2117 kfree(kernel_dev);
2103 putname(dir_page); 2118out_dev:
2104out1: 2119 putname(kernel_dir);
2105 free_page(type_page); 2120out_dir:
2106 return retval; 2121 kfree(kernel_type);
2122out_type:
2123 return ret;
2107} 2124}
2108 2125
2109/* 2126/*