| From 3c0e25d883d06a1fbd1ad35257e8abaa57befb37 Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Thu, 12 Jan 2017 14:56:14 +0100 |
| Subject: [PATCH] USB: serial: io_edgeport: fix descriptor error handling |
| |
| commit 3c0e25d883d06a1fbd1ad35257e8abaa57befb37 upstream. |
| |
| Make sure to detect short control-message transfers and log an error |
| when reading incomplete manufacturer and boot descriptors. |
| |
| Note that the default all-zero descriptors will now be used after a |
| short transfer is detected instead of partially initialised ones. |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| 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 993a36a3e557..8ab5f5b49ef3 100644 |
| --- a/drivers/usb/serial/io_edgeport.c |
| +++ b/drivers/usb/serial/io_edgeport.c |
| @@ -2102,8 +2102,7 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, |
| * rom_read |
| * reads a number of bytes from the Edgeport device starting at the given |
| * address. |
| - * If successful returns the number of bytes read, otherwise it returns |
| - * a negative error number of the problem. |
| + * Returns zero on success or a negative error number. |
| ****************************************************************************/ |
| static int rom_read(struct usb_serial *serial, __u16 extAddr, |
| __u16 addr, __u16 length, __u8 *data) |
| @@ -2128,12 +2127,17 @@ static int rom_read(struct usb_serial *serial, __u16 extAddr, |
| USB_REQUEST_ION_READ_ROM, |
| 0xC0, addr, extAddr, transfer_buffer, |
| current_length, 300); |
| - if (result < 0) |
| + if (result < current_length) { |
| + if (result >= 0) |
| + result = -EIO; |
| break; |
| + } |
| memcpy(data, transfer_buffer, current_length); |
| length -= current_length; |
| addr += current_length; |
| data += current_length; |
| + |
| + result = 0; |
| } |
| |
| kfree(transfer_buffer); |
| @@ -2587,9 +2591,10 @@ static void get_manufacturing_desc(struct edgeport_serial *edge_serial) |
| EDGE_MANUF_DESC_LEN, |
| (__u8 *)(&edge_serial->manuf_descriptor)); |
| |
| - if (response < 1) |
| - dev_err(dev, "error in getting manufacturer descriptor\n"); |
| - else { |
| + if (response < 0) { |
| + dev_err(dev, "error in getting manufacturer descriptor: %d\n", |
| + response); |
| + } else { |
| char string[30]; |
| dev_dbg(dev, "**Manufacturer Descriptor\n"); |
| dev_dbg(dev, " RomSize: %dK\n", |
| @@ -2646,9 +2651,10 @@ static void get_boot_desc(struct edgeport_serial *edge_serial) |
| EDGE_BOOT_DESC_LEN, |
| (__u8 *)(&edge_serial->boot_descriptor)); |
| |
| - if (response < 1) |
| - dev_err(dev, "error in getting boot descriptor\n"); |
| - else { |
| + if (response < 0) { |
| + dev_err(dev, "error in getting boot descriptor: %d\n", |
| + response); |
| + } else { |
| dev_dbg(dev, "**Boot Descriptor:\n"); |
| dev_dbg(dev, " BootCodeLength: %d\n", |
| le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); |
| -- |
| 2.12.0 |
| |