|
@@ -2601,18 +2601,18 @@ static long exact_copy_from_user(void *to, const void __user * from,
|
|
|
return n;
|
|
|
}
|
|
|
|
|
|
-int copy_mount_options(const void __user * data, unsigned long *where)
|
|
|
+void *copy_mount_options(const void __user * data)
|
|
|
{
|
|
|
int i;
|
|
|
- unsigned long page;
|
|
|
unsigned long size;
|
|
|
+ char *copy;
|
|
|
|
|
|
- *where = 0;
|
|
|
if (!data)
|
|
|
- return 0;
|
|
|
+ return NULL;
|
|
|
|
|
|
- if (!(page = __get_free_page(GFP_KERNEL)))
|
|
|
- return -ENOMEM;
|
|
|
+ copy = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
|
|
+ if (!copy)
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
/* We only care that *some* data at the address the user
|
|
|
* 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)
|
|
|
if (size > PAGE_SIZE)
|
|
|
size = PAGE_SIZE;
|
|
|
|
|
|
- i = size - exact_copy_from_user((void *)page, data, size);
|
|
|
+ i = size - exact_copy_from_user(copy, data, size);
|
|
|
if (!i) {
|
|
|
- free_page(page);
|
|
|
- return -EFAULT;
|
|
|
+ kfree(copy);
|
|
|
+ return ERR_PTR(-EFAULT);
|
|
|
}
|
|
|
if (i != PAGE_SIZE)
|
|
|
- memset((char *)page + i, 0, PAGE_SIZE - i);
|
|
|
- *where = page;
|
|
|
- return 0;
|
|
|
+ memset(copy + i, 0, PAGE_SIZE - i);
|
|
|
+ return copy;
|
|
|
}
|
|
|
|
|
|
char *copy_mount_string(const void __user *data)
|
|
@@ -2896,7 +2895,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
|
|
|
int ret;
|
|
|
char *kernel_type;
|
|
|
char *kernel_dev;
|
|
|
- unsigned long data_page;
|
|
|
+ void *options;
|
|
|
|
|
|
kernel_type = copy_mount_string(type);
|
|
|
ret = PTR_ERR(kernel_type);
|
|
@@ -2908,14 +2907,14 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
|
|
|
if (IS_ERR(kernel_dev))
|
|
|
goto out_dev;
|
|
|
|
|
|
- ret = copy_mount_options(data, &data_page);
|
|
|
- if (ret < 0)
|
|
|
+ options = copy_mount_options(data);
|
|
|
+ ret = PTR_ERR(options);
|
|
|
+ if (IS_ERR(options))
|
|
|
goto out_data;
|
|
|
|
|
|
- ret = do_mount(kernel_dev, dir_name, kernel_type, flags,
|
|
|
- (void *) data_page);
|
|
|
+ ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
|
|
|
|
|
|
- free_page(data_page);
|
|
|
+ kfree(options);
|
|
|
out_data:
|
|
|
kfree(kernel_dev);
|
|
|
out_dev:
|