diff options
author | Johan Hovold <johan@kernel.org> | 2017-01-31 11:17:27 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-18 07:14:26 -0400 |
commit | e1533c46151cedb8904f3f88d6c2fc0753e46c0f (patch) | |
tree | d2a6eb1880535b393075ff5356456a0c04265997 /drivers/usb | |
parent | d962bf8dd954db6db513b42cc484a9528df3e5a3 (diff) |
USB: serial: digi_acceleport: fix OOB data sanity check
commit 2d380889215fe20b8523345649dee0579821800c upstream.
Make sure to check for short transfers to avoid underflow in a loop
condition when parsing the receive buffer.
Also fix an off-by-one error in the incomplete sanity check which could
lead to invalid data being parsed.
Fixes: 8c209e6782ca ("USB: make actual_length in struct urb field u32")
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/digi_acceleport.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 6a1df9e824ca..3b610f1e3f7c 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -1482,16 +1482,20 @@ static int digi_read_oob_callback(struct urb *urb) | |||
1482 | struct usb_serial *serial = port->serial; | 1482 | struct usb_serial *serial = port->serial; |
1483 | struct tty_struct *tty; | 1483 | struct tty_struct *tty; |
1484 | struct digi_port *priv = usb_get_serial_port_data(port); | 1484 | struct digi_port *priv = usb_get_serial_port_data(port); |
1485 | unsigned char *buf = urb->transfer_buffer; | ||
1485 | int opcode, line, status, val; | 1486 | int opcode, line, status, val; |
1486 | int i; | 1487 | int i; |
1487 | unsigned int rts; | 1488 | unsigned int rts; |
1488 | 1489 | ||
1490 | if (urb->actual_length < 4) | ||
1491 | return -1; | ||
1492 | |||
1489 | /* handle each oob command */ | 1493 | /* handle each oob command */ |
1490 | for (i = 0; i < urb->actual_length - 3;) { | 1494 | for (i = 0; i < urb->actual_length - 4; i += 4) { |
1491 | opcode = ((unsigned char *)urb->transfer_buffer)[i++]; | 1495 | opcode = buf[i]; |
1492 | line = ((unsigned char *)urb->transfer_buffer)[i++]; | 1496 | line = buf[i + 1]; |
1493 | status = ((unsigned char *)urb->transfer_buffer)[i++]; | 1497 | status = buf[i + 2]; |
1494 | val = ((unsigned char *)urb->transfer_buffer)[i++]; | 1498 | val = buf[i + 3]; |
1495 | 1499 | ||
1496 | dev_dbg(&port->dev, "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d\n", | 1500 | dev_dbg(&port->dev, "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d\n", |
1497 | opcode, line, status, val); | 1501 | opcode, line, status, val); |