From b40ef8696fbbb1107fbe5f4afc21c357f16e5ffc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 14 Dec 2015 18:44:44 -0500 Subject: saner calling conventions for copy_mount_options() let it just return NULL, pointer to kernel copy or ERR_PTR(). Signed-off-by: Al Viro --- fs/compat.c | 21 ++++++++++----------- fs/internal.h | 2 +- fs/namespace.c | 35 +++++++++++++++++------------------ 3 files changed, 28 insertions(+), 30 deletions(-) (limited to 'fs') 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, 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: 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 *, /* * 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 *); 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, 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: -- cgit v1.2.3