lkml.org 
[lkml]   [2016]   [Nov]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 165/346] USB: validate wMaxPacketValue entries in endpoint descriptors
    3.16.39-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Alan Stern <stern@rowland.harvard.edu>

    commit aed9d65ac3278d4febd8665bd7db59ef53e825fe upstream.

    Erroneous or malicious endpoint descriptors may have non-zero bits in
    reserved positions, or out-of-bounds values. This patch helps prevent
    these from causing problems by bounds-checking the wMaxPacketValue
    entries in endpoint descriptors and capping the values at the maximum
    allowed.

    This issue was first discovered and tests were conducted by Jake Lamberson
    <jake.lamberson1@gmail.com>, an intern working for Rosie Hall.

    Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
    Reported-by: roswest <roswest@cisco.com>
    Tested-by: roswest <roswest@cisco.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    [bwh: Backported to 3.16: drop the USB_SPEED_SUPER_PLUS case]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/usb/core/config.c | 66 ++++++++++++++++++++++++++++++++++++++++++++---
    1 file changed, 63 insertions(+), 3 deletions(-)

    --- a/drivers/usb/core/config.c
    +++ b/drivers/usb/core/config.c
    @@ -142,6 +142,31 @@ static void usb_parse_ss_endpoint_compan
    }
    }

    +static const unsigned short low_speed_maxpacket_maxes[4] = {
    + [USB_ENDPOINT_XFER_CONTROL] = 8,
    + [USB_ENDPOINT_XFER_ISOC] = 0,
    + [USB_ENDPOINT_XFER_BULK] = 0,
    + [USB_ENDPOINT_XFER_INT] = 8,
    +};
    +static const unsigned short full_speed_maxpacket_maxes[4] = {
    + [USB_ENDPOINT_XFER_CONTROL] = 64,
    + [USB_ENDPOINT_XFER_ISOC] = 1023,
    + [USB_ENDPOINT_XFER_BULK] = 64,
    + [USB_ENDPOINT_XFER_INT] = 64,
    +};
    +static const unsigned short high_speed_maxpacket_maxes[4] = {
    + [USB_ENDPOINT_XFER_CONTROL] = 64,
    + [USB_ENDPOINT_XFER_ISOC] = 1024,
    + [USB_ENDPOINT_XFER_BULK] = 512,
    + [USB_ENDPOINT_XFER_INT] = 1023,
    +};
    +static const unsigned short super_speed_maxpacket_maxes[4] = {
    + [USB_ENDPOINT_XFER_CONTROL] = 512,
    + [USB_ENDPOINT_XFER_ISOC] = 1024,
    + [USB_ENDPOINT_XFER_BULK] = 1024,
    + [USB_ENDPOINT_XFER_INT] = 1024,
    +};
    +
    static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
    int asnum, struct usb_host_interface *ifp, int num_ep,
    unsigned char *buffer, int size)
    @@ -150,6 +175,8 @@ static int usb_parse_endpoint(struct dev
    struct usb_endpoint_descriptor *d;
    struct usb_host_endpoint *endpoint;
    int n, i, j, retval;
    + unsigned int maxp;
    + const unsigned short *maxpacket_maxes;

    d = (struct usb_endpoint_descriptor *) buffer;
    buffer += d->bLength;
    @@ -256,6 +283,41 @@ static int usb_parse_endpoint(struct dev
    endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
    }

    + /* Validate the wMaxPacketSize field */
    + maxp = usb_endpoint_maxp(&endpoint->desc);
    +
    + /* Find the highest legal maxpacket size for this endpoint */
    + i = 0; /* additional transactions per microframe */
    + switch (to_usb_device(ddev)->speed) {
    + case USB_SPEED_LOW:
    + maxpacket_maxes = low_speed_maxpacket_maxes;
    + break;
    + case USB_SPEED_FULL:
    + maxpacket_maxes = full_speed_maxpacket_maxes;
    + break;
    + case USB_SPEED_HIGH:
    + /* Bits 12..11 are allowed only for HS periodic endpoints */
    + if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) {
    + i = maxp & (BIT(12) | BIT(11));
    + maxp &= ~i;
    + }
    + /* fallthrough */
    + default:
    + maxpacket_maxes = high_speed_maxpacket_maxes;
    + break;
    + case USB_SPEED_SUPER:
    + maxpacket_maxes = super_speed_maxpacket_maxes;
    + break;
    + }
    + j = maxpacket_maxes[usb_endpoint_type(&endpoint->desc)];
    +
    + if (maxp > j) {
    + dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid maxpacket %d, setting to %d\n",
    + cfgno, inum, asnum, d->bEndpointAddress, maxp, j);
    + maxp = j;
    + endpoint->desc.wMaxPacketSize = cpu_to_le16(i | maxp);
    + }
    +
    /*
    * Some buggy high speed devices have bulk endpoints using
    * maxpacket sizes other than 512. High speed HCDs may not
    @@ -263,9 +325,6 @@ static int usb_parse_endpoint(struct dev
    */
    if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
    && usb_endpoint_xfer_bulk(d)) {
    - unsigned maxp;
    -
    - maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff;
    if (maxp != 512)
    dev_warn(ddev, "config %d interface %d altsetting %d "
    "bulk endpoint 0x%X has invalid maxpacket %d\n",
    \
     
     \ /
      Last update: 2016-11-14 03:35    [W:4.114 / U:0.208 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site