aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2017-01-31 11:17:28 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-14 08:00:18 -0400
commit9ca3010675025a512db998b1421ad0b60963c790 (patch)
treefa16a66d8bab1dd6bf62e24ce08f9048ecfac9f2
parent84443215cf54861f3013253817afaf156efb1453 (diff)
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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/serial/digi_acceleport.c38
1 files changed, 23 insertions, 15 deletions
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 30bf0f5db82d..7ab3235febfc 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)
1398{ 1398{
1399 struct usb_serial_port *port = urb->context; 1399 struct usb_serial_port *port = urb->context;
1400 struct digi_port *priv = usb_get_serial_port_data(port); 1400 struct digi_port *priv = usb_get_serial_port_data(port);
1401 int opcode = ((unsigned char *)urb->transfer_buffer)[0]; 1401 unsigned char *buf = urb->transfer_buffer;
1402 int len = ((unsigned char *)urb->transfer_buffer)[1]; 1402 int opcode;
1403 int port_status = ((unsigned char *)urb->transfer_buffer)[2]; 1403 int len;
1404 unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3; 1404 int port_status;
1405 unsigned char *data;
1405 int flag, throttled; 1406 int flag, throttled;
1406 int status = urb->status;
1407
1408 /* do not process callbacks on closed ports */
1409 /* but do continue the read chain */
1410 if (urb->status == -ENOENT)
1411 return 0;
1412 1407
1413 /* short/multiple packet check */ 1408 /* short/multiple packet check */
1409 if (urb->actual_length < 2) {
1410 dev_warn(&port->dev, "short packet received\n");
1411 return -1;
1412 }
1413
1414 opcode = buf[0];
1415 len = buf[1];
1416
1414 if (urb->actual_length != len + 2) { 1417 if (urb->actual_length != len + 2) {
1415 dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, " 1418 dev_err(&port->dev, "malformed packet received: port=%d, opcode=%d, len=%d, actual_length=%u\n",
1416 "status=%d, port=%d, opcode=%d, len=%d, " 1419 priv->dp_port_num, opcode, len, urb->actual_length);
1417 "actual_length=%d, status=%d\n", __func__, status, 1420 return -1;
1418 priv->dp_port_num, opcode, len, urb->actual_length, 1421 }
1419 port_status); 1422
1423 if (opcode == DIGI_CMD_RECEIVE_DATA && len < 1) {
1424 dev_err(&port->dev, "malformed data packet received\n");
1420 return -1; 1425 return -1;
1421 } 1426 }
1422 1427
@@ -1430,6 +1435,9 @@ static int digi_read_inb_callback(struct urb *urb)
1430 1435
1431 /* receive data */ 1436 /* receive data */
1432 if (opcode == DIGI_CMD_RECEIVE_DATA) { 1437 if (opcode == DIGI_CMD_RECEIVE_DATA) {
1438 port_status = buf[2];
1439 data = &buf[3];
1440
1433 /* get flag from port_status */ 1441 /* get flag from port_status */
1434 flag = 0; 1442 flag = 0;
1435 1443