| From e4457d9798adb96272468e93da663de9bd0a4198 Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Thu, 12 Jan 2017 14:56:13 +0100 |
| Subject: [PATCH] USB: serial: io_edgeport: fix epic-descriptor handling |
| |
| commit e4457d9798adb96272468e93da663de9bd0a4198 upstream. |
| |
| Use a dedicated buffer for the DMA transfer and make sure to detect |
| short transfers to avoid parsing a corrupt descriptor. |
| |
| Fixes: 6e8cf7751f9f ("USB: add EPIC support to the io_edgeport driver") |
| Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| |
| diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c |
| index d50e5773483f..993a36a3e557 100644 |
| --- a/drivers/usb/serial/io_edgeport.c |
| +++ b/drivers/usb/serial/io_edgeport.c |
| @@ -492,20 +492,24 @@ static int get_epic_descriptor(struct edgeport_serial *ep) |
| int result; |
| struct usb_serial *serial = ep->serial; |
| struct edgeport_product_info *product_info = &ep->product_info; |
| - struct edge_compatibility_descriptor *epic = &ep->epic_descriptor; |
| + struct edge_compatibility_descriptor *epic; |
| struct edge_compatibility_bits *bits; |
| struct device *dev = &serial->dev->dev; |
| |
| ep->is_epic = 0; |
| + |
| + epic = kmalloc(sizeof(*epic), GFP_KERNEL); |
| + if (!epic) |
| + return -ENOMEM; |
| + |
| result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
| USB_REQUEST_ION_GET_EPIC_DESC, |
| 0xC0, 0x00, 0x00, |
| - &ep->epic_descriptor, |
| - sizeof(struct edge_compatibility_descriptor), |
| + epic, sizeof(*epic), |
| 300); |
| - |
| - if (result > 0) { |
| + if (result == sizeof(*epic)) { |
| ep->is_epic = 1; |
| + memcpy(&ep->epic_descriptor, epic, sizeof(*epic)); |
| memset(product_info, 0, sizeof(struct edgeport_product_info)); |
| |
| product_info->NumPorts = epic->NumPorts; |
| @@ -534,8 +538,16 @@ static int get_epic_descriptor(struct edgeport_serial *ep) |
| dev_dbg(dev, " IOSPWriteLCR : %s\n", bits->IOSPWriteLCR ? "TRUE": "FALSE"); |
| dev_dbg(dev, " IOSPSetBaudRate : %s\n", bits->IOSPSetBaudRate ? "TRUE": "FALSE"); |
| dev_dbg(dev, " TrueEdgeport : %s\n", bits->TrueEdgeport ? "TRUE": "FALSE"); |
| + |
| + result = 0; |
| + } else if (result >= 0) { |
| + dev_warn(&serial->interface->dev, "short epic descriptor received: %d\n", |
| + result); |
| + result = -EIO; |
| } |
| |
| + kfree(epic); |
| + |
| return result; |
| } |
| |
| @@ -2779,7 +2791,7 @@ static int edge_startup(struct usb_serial *serial) |
| dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); |
| |
| /* Read the epic descriptor */ |
| - if (get_epic_descriptor(edge_serial) <= 0) { |
| + if (get_epic_descriptor(edge_serial) < 0) { |
| /* memcpy descriptor to Supports structures */ |
| memcpy(&edge_serial->epic_descriptor.Supports, descriptor, |
| sizeof(struct edge_compatibility_bits)); |
| -- |
| 2.12.0 |
| |