aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2017-01-31 11:17:29 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-14 08:00:18 -0400
commit84443215cf54861f3013253817afaf156efb1453 (patch)
treeb3a92b5fa54d8d86892282f60faf45758dc192f9
parentb6c17077e05673b9f4f59b682dd3c48394b415fd (diff)
USB: serial: keyspan_pda: fix receive sanity checks
commit c528fcb116e61afc379a2e0a0f70906b937f1e2c upstream. Make sure to check for short transfers before parsing the receive buffer to avoid acting on stale data. 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/keyspan_pda.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 83523fcf6fb9..d2dab2a341b8 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -139,6 +139,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
139{ 139{
140 struct usb_serial_port *port = urb->context; 140 struct usb_serial_port *port = urb->context;
141 unsigned char *data = urb->transfer_buffer; 141 unsigned char *data = urb->transfer_buffer;
142 unsigned int len = urb->actual_length;
142 int retval; 143 int retval;
143 int status = urb->status; 144 int status = urb->status;
144 struct keyspan_pda_private *priv; 145 struct keyspan_pda_private *priv;
@@ -159,18 +160,26 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
159 goto exit; 160 goto exit;
160 } 161 }
161 162
163 if (len < 1) {
164 dev_warn(&port->dev, "short message received\n");
165 goto exit;
166 }
167
162 /* see if the message is data or a status interrupt */ 168 /* see if the message is data or a status interrupt */
163 switch (data[0]) { 169 switch (data[0]) {
164 case 0: 170 case 0:
165 /* rest of message is rx data */ 171 /* rest of message is rx data */
166 if (urb->actual_length) { 172 if (len < 2)
167 tty_insert_flip_string(&port->port, data + 1, 173 break;
168 urb->actual_length - 1); 174 tty_insert_flip_string(&port->port, data + 1, len - 1);
169 tty_flip_buffer_push(&port->port); 175 tty_flip_buffer_push(&port->port);
170 }
171 break; 176 break;
172 case 1: 177 case 1:
173 /* status interrupt */ 178 /* status interrupt */
179 if (len < 3) {
180 dev_warn(&port->dev, "short interrupt message received\n");
181 break;
182 }
174 dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]); 183 dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]);
175 switch (data[1]) { 184 switch (data[1]) {
176 case 1: /* modemline change */ 185 case 1: /* modemline change */