| From d979e9f9ecab04c1ecca741370e30a8a498893f5 Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Wed, 27 Aug 2014 11:55:18 +0200 |
| Subject: USB: serial: fix potential stack buffer overflow |
| |
| From: Johan Hovold <johan@kernel.org> |
| |
| commit d979e9f9ecab04c1ecca741370e30a8a498893f5 upstream. |
| |
| Make sure to verify the maximum number of endpoints per type to avoid |
| writing beyond the end of a stack-allocated array. |
| |
| The current usb-serial implementation is limited to eight ports per |
| interface but failed to verify that the number of endpoints of a certain |
| type reported by a device did not exceed this limit. |
| |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/serial/usb-serial.c | 32 ++++++++++++++++++++++---------- |
| 1 file changed, 22 insertions(+), 10 deletions(-) |
| |
| --- a/drivers/usb/serial/usb-serial.c |
| +++ b/drivers/usb/serial/usb-serial.c |
| @@ -764,29 +764,39 @@ static int usb_serial_probe(struct usb_i |
| if (usb_endpoint_is_bulk_in(endpoint)) { |
| /* we found a bulk in endpoint */ |
| dev_dbg(ddev, "found bulk in on endpoint %d\n", i); |
| - bulk_in_endpoint[num_bulk_in] = endpoint; |
| - ++num_bulk_in; |
| + if (num_bulk_in < MAX_NUM_PORTS) { |
| + bulk_in_endpoint[num_bulk_in] = endpoint; |
| + ++num_bulk_in; |
| + } |
| } |
| |
| if (usb_endpoint_is_bulk_out(endpoint)) { |
| /* we found a bulk out endpoint */ |
| dev_dbg(ddev, "found bulk out on endpoint %d\n", i); |
| - bulk_out_endpoint[num_bulk_out] = endpoint; |
| - ++num_bulk_out; |
| + if (num_bulk_out < MAX_NUM_PORTS) { |
| + bulk_out_endpoint[num_bulk_out] = endpoint; |
| + ++num_bulk_out; |
| + } |
| } |
| |
| if (usb_endpoint_is_int_in(endpoint)) { |
| /* we found a interrupt in endpoint */ |
| dev_dbg(ddev, "found interrupt in on endpoint %d\n", i); |
| - interrupt_in_endpoint[num_interrupt_in] = endpoint; |
| - ++num_interrupt_in; |
| + if (num_interrupt_in < MAX_NUM_PORTS) { |
| + interrupt_in_endpoint[num_interrupt_in] = |
| + endpoint; |
| + ++num_interrupt_in; |
| + } |
| } |
| |
| if (usb_endpoint_is_int_out(endpoint)) { |
| /* we found an interrupt out endpoint */ |
| dev_dbg(ddev, "found interrupt out on endpoint %d\n", i); |
| - interrupt_out_endpoint[num_interrupt_out] = endpoint; |
| - ++num_interrupt_out; |
| + if (num_interrupt_out < MAX_NUM_PORTS) { |
| + interrupt_out_endpoint[num_interrupt_out] = |
| + endpoint; |
| + ++num_interrupt_out; |
| + } |
| } |
| } |
| |
| @@ -809,8 +819,10 @@ static int usb_serial_probe(struct usb_i |
| if (usb_endpoint_is_int_in(endpoint)) { |
| /* we found a interrupt in endpoint */ |
| dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n"); |
| - interrupt_in_endpoint[num_interrupt_in] = endpoint; |
| - ++num_interrupt_in; |
| + if (num_interrupt_in < MAX_NUM_PORTS) { |
| + interrupt_in_endpoint[num_interrupt_in] = endpoint; |
| + ++num_interrupt_in; |
| + } |
| } |
| } |
| } |