diff options
author | Mayank Rana <mrana@codeaurora.org> | 2015-09-02 16:25:31 -0700 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 19:58:21 -0700 |
commit | 4687a02e767fc1cc2f9275d6b7e3cb681a0d9945 (patch) | |
tree | 3993790d0cfa1fc055963bc57a182d960a04ea29 /drivers/usb/gadget/function | |
parent | df2968af9f8c4d3f784bd7a66a1adcfe9c9f743c (diff) |
usb: u_data_bridge: Check allowable size with gbridge_port_write()
Currently gbridge_port_write() is not checking size of user space
provided data and directly copies buffer into USB request buffer
which is having size as 2KB. If user space application writes data
bigger than 2KB, copy_from_user() tries to copy data beyond allocated
USB request buffer size which results into memory corruption. Fix
this issue by checking allowable size with gbridge_port_write() and
making sure that it doesn't copy data beyond allocated buffer size.
Change-Id: I7a34e37f5d1609792374f07b70542b80edbe6944
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
Diffstat (limited to 'drivers/usb/gadget/function')
-rw-r--r-- | drivers/usb/gadget/function/u_data_bridge.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/usb/gadget/function/u_data_bridge.c b/drivers/usb/gadget/function/u_data_bridge.c index 578c34e6687b..8a0ac837d66b 100644 --- a/drivers/usb/gadget/function/u_data_bridge.c +++ b/drivers/usb/gadget/function/u_data_bridge.c @@ -507,6 +507,7 @@ ssize_t gbridge_port_write(struct file *file, struct gbridge_port *port; struct usb_request *req; struct list_head *pool; + unsigned xfer_size; port = file->private_data; if (!port) { @@ -528,12 +529,17 @@ ssize_t gbridge_port_write(struct file *file, spin_unlock_irqrestore(&port->port_lock, flags); pr_debug("%s: write buf size:%zu\n", __func__, count); - ret = copy_from_user(req->buf, buf, count); + if (count > BRIDGE_TX_BUF_SIZE) + xfer_size = BRIDGE_TX_BUF_SIZE; + else + xfer_size = count; + + ret = copy_from_user(req->buf, buf, xfer_size); if (ret) { pr_err("copy_from_user failed: err %d\n", ret); ret = -EFAULT; } else { - req->length = count; + req->length = xfer_size; ret = usb_ep_queue(port->port_usb->in, req, GFP_KERNEL); if (ret) { pr_err("EP QUEUE failed:%d\n", ret); @@ -552,7 +558,7 @@ err_exit: if (ret) return ret; else - return count; + return xfer_size; } static unsigned int gbridge_port_poll(struct file *file, poll_table *wait) |