| From 1b0aed2b1600f6e5c7b9acfbd610a4e351ef5232 Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Tue, 31 Jan 2017 17:17:28 +0100 |
| Subject: [PATCH] USB: serial: digi_acceleport: fix incomplete rx sanity check |
| |
| commit 1b0aed2b1600f6e5c7b9acfbd610a4e351ef5232 upstream. |
| |
| Make sure the received data has the required headers before parsing it. |
| |
| Also drop the redundant urb-status check, which has already been handled |
| by the caller. |
| |
| 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/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c |
| index 3b610f1e3f7c..eb433922598c 100644 |
| --- a/drivers/usb/serial/digi_acceleport.c |
| +++ b/drivers/usb/serial/digi_acceleport.c |
| @@ -1398,25 +1398,30 @@ static int digi_read_inb_callback(struct urb *urb) |
| { |
| struct usb_serial_port *port = urb->context; |
| struct digi_port *priv = usb_get_serial_port_data(port); |
| - int opcode = ((unsigned char *)urb->transfer_buffer)[0]; |
| - int len = ((unsigned char *)urb->transfer_buffer)[1]; |
| - int port_status = ((unsigned char *)urb->transfer_buffer)[2]; |
| - unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3; |
| + unsigned char *buf = urb->transfer_buffer; |
| + int opcode; |
| + int len; |
| + int port_status; |
| + unsigned char *data; |
| int flag, throttled; |
| - int status = urb->status; |
| - |
| - /* do not process callbacks on closed ports */ |
| - /* but do continue the read chain */ |
| - if (urb->status == -ENOENT) |
| - return 0; |
| |
| /* short/multiple packet check */ |
| + if (urb->actual_length < 2) { |
| + dev_warn(&port->dev, "short packet received\n"); |
| + return -1; |
| + } |
| + |
| + opcode = buf[0]; |
| + len = buf[1]; |
| + |
| if (urb->actual_length != len + 2) { |
| - dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, " |
| - "status=%d, port=%d, opcode=%d, len=%d, " |
| - "actual_length=%d, status=%d\n", __func__, status, |
| - priv->dp_port_num, opcode, len, urb->actual_length, |
| - port_status); |
| + dev_err(&port->dev, "malformed packet received: port=%d, opcode=%d, len=%d, actual_length=%u\n", |
| + priv->dp_port_num, opcode, len, urb->actual_length); |
| + return -1; |
| + } |
| + |
| + if (opcode == DIGI_CMD_RECEIVE_DATA && len < 1) { |
| + dev_err(&port->dev, "malformed data packet received\n"); |
| return -1; |
| } |
| |
| @@ -1430,6 +1435,9 @@ static int digi_read_inb_callback(struct urb *urb) |
| |
| /* receive data */ |
| if (opcode == DIGI_CMD_RECEIVE_DATA) { |
| + port_status = buf[2]; |
| + data = &buf[3]; |
| + |
| /* get flag from port_status */ |
| flag = 0; |
| |
| -- |
| 2.12.0 |
| |