]>
Commit | Line | Data |
---|---|---|
b74db2ac GKH |
1 | From c528fcb116e61afc379a2e0a0f70906b937f1e2c Mon Sep 17 00:00:00 2001 |
2 | From: Johan Hovold <johan@kernel.org> | |
3 | Date: Tue, 31 Jan 2017 17:17:29 +0100 | |
4 | Subject: USB: serial: keyspan_pda: fix receive sanity checks | |
5 | ||
6 | From: Johan Hovold <johan@kernel.org> | |
7 | ||
8 | commit c528fcb116e61afc379a2e0a0f70906b937f1e2c upstream. | |
9 | ||
10 | Make sure to check for short transfers before parsing the receive buffer | |
11 | to avoid acting on stale data. | |
12 | ||
13 | Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") | |
14 | Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
15 | Signed-off-by: Johan Hovold <johan@kernel.org> | |
16 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
17 | ||
18 | --- | |
19 | drivers/usb/serial/keyspan_pda.c | 19 ++++++++++++++----- | |
20 | 1 file changed, 14 insertions(+), 5 deletions(-) | |
21 | ||
22 | --- a/drivers/usb/serial/keyspan_pda.c | |
23 | +++ b/drivers/usb/serial/keyspan_pda.c | |
24 | @@ -139,6 +139,7 @@ static void keyspan_pda_rx_interrupt(str | |
25 | { | |
26 | struct usb_serial_port *port = urb->context; | |
27 | unsigned char *data = urb->transfer_buffer; | |
28 | + unsigned int len = urb->actual_length; | |
29 | int retval; | |
30 | int status = urb->status; | |
31 | struct keyspan_pda_private *priv; | |
32 | @@ -159,18 +160,26 @@ static void keyspan_pda_rx_interrupt(str | |
33 | goto exit; | |
34 | } | |
35 | ||
36 | + if (len < 1) { | |
37 | + dev_warn(&port->dev, "short message received\n"); | |
38 | + goto exit; | |
39 | + } | |
40 | + | |
41 | /* see if the message is data or a status interrupt */ | |
42 | switch (data[0]) { | |
43 | case 0: | |
44 | /* rest of message is rx data */ | |
45 | - if (urb->actual_length) { | |
46 | - tty_insert_flip_string(&port->port, data + 1, | |
47 | - urb->actual_length - 1); | |
48 | - tty_flip_buffer_push(&port->port); | |
49 | - } | |
50 | + if (len < 2) | |
51 | + break; | |
52 | + tty_insert_flip_string(&port->port, data + 1, len - 1); | |
53 | + tty_flip_buffer_push(&port->port); | |
54 | break; | |
55 | case 1: | |
56 | /* status interrupt */ | |
57 | + if (len < 3) { | |
58 | + dev_warn(&port->dev, "short interrupt message received\n"); | |
59 | + break; | |
60 | + } | |
61 | dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]); | |
62 | switch (data[1]) { | |
63 | case 1: /* modemline change */ |