usb: usbip: fix isoc packet num validation in get_pipe [Linux 5.1]

usb: usbip: fix isoc packet num validation in get_pipe [Linux 5.1]

This Linux kernel change "usb: usbip: fix isoc packet num validation in get_pipe" is included in the Linux 5.1 release. This change is authored by Malte Leip <malte [at] leip.net> on Sun Apr 14 12:00:12 2019 +0200. The commit for this change in Linux stable tree is c409ca3 (patch).

usb: usbip: fix isoc packet num validation in get_pipe

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 <[email protected]>
Cc: stable <[email protected]>
Acked-by: Shuah Khan <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

There are 19 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/usb/usbip/stub_rx.c      | 12 +++---------
 drivers/usb/usbip/usbip_common.h |  7 +++++++
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c
index 97b09a4..dbfb2f2 100644
--- 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 *sdev, struct usbip_header *pdu)
    }

    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);
diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h
index bf8afe9..8be857a 100644
--- a/drivers/usb/usbip/usbip_common.h
+++ b/drivers/usb/usbip/usbip_common.h
@@ -121,6 +121,13 @@ enum {
 #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

Leave a Reply

Your email address will not be published. Required fields are marked *