| From c409ca3be3c6ff3a1eeb303b191184e80d412862 Mon Sep 17 00:00:00 2001 |
| From: Malte Leip <malte@leip.net> |
| Date: Sun, 14 Apr 2019 12:00:12 +0200 |
| Subject: usb: usbip: fix isoc packet num validation in get_pipe |
| |
| From: Malte Leip <malte@leip.net> |
| |
| commit c409ca3be3c6ff3a1eeb303b191184e80d412862 upstream. |
| |
| Change the validation of number_of_packets in get_pipe to compare the |
| number of packets to a fixed maximum number of packets allowed, set to |
| be 1024. This number was chosen due to it being used by other drivers as |
| well, for example drivers/usb/host/uhci-q.c |
| |
| Background/reason: |
| The get_pipe function in stub_rx.c validates the number of packets in |
| isochronous mode and aborts with an error if that number is too large, |
| in order to prevent malicious input from possibly triggering large |
| memory allocations. This was previously done by checking whether |
| pdu->u.cmd_submit.number_of_packets is bigger than the number of packets |
| that would be needed for pdu->u.cmd_submit.transfer_buffer_length bytes |
| if all except possibly the last packet had maximum length, given by |
| usb_endpoint_maxp(epd) * usb_endpoint_maxp_mult(epd). This leads to an |
| error if URBs with packets shorter than the maximum possible length are |
| submitted, which is allowed according to |
| Documentation/driver-api/usb/URB.rst and occurs for example with the |
| snd-usb-audio driver. |
| |
| Fixes: c6688ef9f297 ("usbip: fix stub_rx: harden CMD_SUBMIT path to handle malicious input") |
| Signed-off-by: Malte Leip <malte@leip.net> |
| Cc: stable <stable@vger.kernel.org> |
| Acked-by: Shuah Khan <skhan@linuxfoundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/usbip/stub_rx.c | 12 +++--------- |
| drivers/usb/usbip/usbip_common.h | 7 +++++++ |
| 2 files changed, 10 insertions(+), 9 deletions(-) |
| |
| --- a/drivers/usb/usbip/stub_rx.c |
| +++ b/drivers/usb/usbip/stub_rx.c |
| @@ -361,16 +361,10 @@ static int get_pipe(struct stub_device * |
| } |
| |
| if (usb_endpoint_xfer_isoc(epd)) { |
| - /* validate packet size and number of packets */ |
| - unsigned int maxp, packets, bytes; |
| - |
| - maxp = usb_endpoint_maxp(epd); |
| - maxp *= usb_endpoint_maxp_mult(epd); |
| - bytes = pdu->u.cmd_submit.transfer_buffer_length; |
| - packets = DIV_ROUND_UP(bytes, maxp); |
| - |
| + /* validate number of packets */ |
| if (pdu->u.cmd_submit.number_of_packets < 0 || |
| - pdu->u.cmd_submit.number_of_packets > packets) { |
| + pdu->u.cmd_submit.number_of_packets > |
| + USBIP_MAX_ISO_PACKETS) { |
| dev_err(&sdev->udev->dev, |
| "CMD_SUBMIT: isoc invalid num packets %d\n", |
| pdu->u.cmd_submit.number_of_packets); |
| --- a/drivers/usb/usbip/usbip_common.h |
| +++ b/drivers/usb/usbip/usbip_common.h |
| @@ -121,6 +121,13 @@ extern struct device_attribute dev_attr_ |
| #define USBIP_DIR_OUT 0x00 |
| #define USBIP_DIR_IN 0x01 |
| |
| +/* |
| + * Arbitrary limit for the maximum number of isochronous packets in an URB, |
| + * compare for example the uhci_submit_isochronous function in |
| + * drivers/usb/host/uhci-q.c |
| + */ |
| +#define USBIP_MAX_ISO_PACKETS 1024 |
| + |
| /** |
| * struct usbip_header_basic - data pertinent to every request |
| * @command: the usbip request type |