diff options
author | Dan Carpenter <dan.carpenter@oracle.com> | 2014-12-22 10:52:39 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-01-17 15:46:22 -0800 |
commit | 3b66ea435234aab8fd8f389e929baedb556726c4 (patch) | |
tree | acdaffe2b8d8f46d6ba11f62d25102de2cbe479d /drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | |
parent | staging: lustre: lustre: obdclass: lprocfs_status.c: Tidied up some code in a case statement (diff) | |
download | linux-dev-3b66ea435234aab8fd8f389e929baedb556726c4.tar.xz linux-dev-3b66ea435234aab8fd8f389e929baedb556726c4.zip |
Staging: lustre: error handling tweaks in obd_ioctl_getdata()
1) The places which called copy_from_user() were returning the number
of bytes not copied instead of -EFAULT.
2) The user could trigger a memory leak if the condition
"(hdr.ioc_len != data->ioc_len)" was true. Instead of adding a new call
to OBD_FREE_LARGE(), I created a free_buf label and changed everything
to use that label.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/lustre/lustre/obdclass/linux/linux-module.c')
-rw-r--r-- | drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index b5007b8cbe34..b94aeac18a37 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -83,9 +83,8 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) int err; int offset = 0; - err = copy_from_user(&hdr, (void *)arg, sizeof(hdr)); - if (err) - return err; + if (copy_from_user(&hdr, (void *)arg, sizeof(hdr))) + return -EFAULT; if (hdr.ioc_version != OBD_IOCTL_VERSION) { CERROR("Version mismatch kernel (%x) vs application (%x)\n", @@ -117,18 +116,19 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) *len = hdr.ioc_len; data = (struct obd_ioctl_data *)*buf; - err = copy_from_user(*buf, (void *)arg, hdr.ioc_len); - if (err) { - OBD_FREE_LARGE(*buf, hdr.ioc_len); - return err; + if (copy_from_user(*buf, (void *)arg, hdr.ioc_len)) { + err = -EFAULT; + goto free_buf; + } + if (hdr.ioc_len != data->ioc_len) { + err = -EINVAL; + goto free_buf; } - if (hdr.ioc_len != data->ioc_len) - return -EINVAL; if (obd_ioctl_is_invalid(data)) { CERROR("ioctl not correctly formatted\n"); - OBD_FREE_LARGE(*buf, hdr.ioc_len); - return -EINVAL; + err = -EINVAL; + goto free_buf; } if (data->ioc_inllen1) { @@ -151,6 +151,10 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) } return 0; + +free_buf: + OBD_FREE_LARGE(*buf, hdr.ioc_len); + return err; } EXPORT_SYMBOL(obd_ioctl_getdata); |