saner calling conventions for copy_mount_options()
let it just return NULL, pointer to kernel copy or ERR_PTR(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
cc4e719e83
commit
b40ef8696f
3 changed files with 28 additions and 30 deletions
21
fs/compat.c
21
fs/compat.c
|
@ -792,7 +792,7 @@ COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
|
|||
const void __user *, data)
|
||||
{
|
||||
char *kernel_type;
|
||||
unsigned long data_page;
|
||||
void *options;
|
||||
char *kernel_dev;
|
||||
int retval;
|
||||
|
||||
|
@ -806,26 +806,25 @@ COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
|
|||
if (IS_ERR(kernel_dev))
|
||||
goto out1;
|
||||
|
||||
retval = copy_mount_options(data, &data_page);
|
||||
if (retval < 0)
|
||||
options = copy_mount_options(data);
|
||||
retval = PTR_ERR(options);
|
||||
if (IS_ERR(options))
|
||||
goto out2;
|
||||
|
||||
retval = -EINVAL;
|
||||
|
||||
if (kernel_type && data_page) {
|
||||
if (kernel_type && options) {
|
||||
if (!strcmp(kernel_type, NCPFS_NAME)) {
|
||||
do_ncp_super_data_conv((void *)data_page);
|
||||
do_ncp_super_data_conv(options);
|
||||
} else if (!strcmp(kernel_type, NFS4_NAME)) {
|
||||
if (do_nfs4_super_data_conv((void *) data_page))
|
||||
retval = -EINVAL;
|
||||
if (do_nfs4_super_data_conv(options))
|
||||
goto out3;
|
||||
}
|
||||
}
|
||||
|
||||
retval = do_mount(kernel_dev, dir_name, kernel_type,
|
||||
flags, (void*)data_page);
|
||||
retval = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
|
||||
|
||||
out3:
|
||||
free_page(data_page);
|
||||
kfree(options);
|
||||
out2:
|
||||
kfree(kernel_dev);
|
||||
out1:
|
||||
|
|
|
@ -55,7 +55,7 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
|
|||
/*
|
||||
* namespace.c
|
||||
*/
|
||||
extern int copy_mount_options(const void __user *, unsigned long *);
|
||||
extern void *copy_mount_options(const void __user *);
|
||||
extern char *copy_mount_string(const void __user *);
|
||||
|
||||
extern struct vfsmount *lookup_mnt(struct path *);
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue