Skip to content

Commit aed9d65

Browse files
AlanSterngregkh
authored andcommitted
USB: validate wMaxPacketValue entries in endpoint descriptors
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 <[email protected]>, an intern working for Rosie Hall. Signed-off-by: Alan Stern <[email protected]> Reported-by: roswest <[email protected]> Tested-by: roswest <[email protected]> CC: <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 9c6256a commit aed9d65

File tree

1 file changed

+63
-3
lines changed

1 file changed

+63
-3
lines changed

drivers/usb/core/config.c

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,31 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
171171
ep, buffer, size);
172172
}
173173

174+
static const unsigned short low_speed_maxpacket_maxes[4] = {
175+
[USB_ENDPOINT_XFER_CONTROL] = 8,
176+
[USB_ENDPOINT_XFER_ISOC] = 0,
177+
[USB_ENDPOINT_XFER_BULK] = 0,
178+
[USB_ENDPOINT_XFER_INT] = 8,
179+
};
180+
static const unsigned short full_speed_maxpacket_maxes[4] = {
181+
[USB_ENDPOINT_XFER_CONTROL] = 64,
182+
[USB_ENDPOINT_XFER_ISOC] = 1023,
183+
[USB_ENDPOINT_XFER_BULK] = 64,
184+
[USB_ENDPOINT_XFER_INT] = 64,
185+
};
186+
static const unsigned short high_speed_maxpacket_maxes[4] = {
187+
[USB_ENDPOINT_XFER_CONTROL] = 64,
188+
[USB_ENDPOINT_XFER_ISOC] = 1024,
189+
[USB_ENDPOINT_XFER_BULK] = 512,
190+
[USB_ENDPOINT_XFER_INT] = 1023,
191+
};
192+
static const unsigned short super_speed_maxpacket_maxes[4] = {
193+
[USB_ENDPOINT_XFER_CONTROL] = 512,
194+
[USB_ENDPOINT_XFER_ISOC] = 1024,
195+
[USB_ENDPOINT_XFER_BULK] = 1024,
196+
[USB_ENDPOINT_XFER_INT] = 1024,
197+
};
198+
174199
static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
175200
int asnum, struct usb_host_interface *ifp, int num_ep,
176201
unsigned char *buffer, int size)
@@ -179,6 +204,8 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
179204
struct usb_endpoint_descriptor *d;
180205
struct usb_host_endpoint *endpoint;
181206
int n, i, j, retval;
207+
unsigned int maxp;
208+
const unsigned short *maxpacket_maxes;
182209

183210
d = (struct usb_endpoint_descriptor *) buffer;
184211
buffer += d->bLength;
@@ -286,16 +313,49 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
286313
endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
287314
}
288315

316+
/* Validate the wMaxPacketSize field */
317+
maxp = usb_endpoint_maxp(&endpoint->desc);
318+
319+
/* Find the highest legal maxpacket size for this endpoint */
320+
i = 0; /* additional transactions per microframe */
321+
switch (to_usb_device(ddev)->speed) {
322+
case USB_SPEED_LOW:
323+
maxpacket_maxes = low_speed_maxpacket_maxes;
324+
break;
325+
case USB_SPEED_FULL:
326+
maxpacket_maxes = full_speed_maxpacket_maxes;
327+
break;
328+
case USB_SPEED_HIGH:
329+
/* Bits 12..11 are allowed only for HS periodic endpoints */
330+
if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) {
331+
i = maxp & (BIT(12) | BIT(11));
332+
maxp &= ~i;
333+
}
334+
/* fallthrough */
335+
default:
336+
maxpacket_maxes = high_speed_maxpacket_maxes;
337+
break;
338+
case USB_SPEED_SUPER:
339+
case USB_SPEED_SUPER_PLUS:
340+
maxpacket_maxes = super_speed_maxpacket_maxes;
341+
break;
342+
}
343+
j = maxpacket_maxes[usb_endpoint_type(&endpoint->desc)];
344+
345+
if (maxp > j) {
346+
dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid maxpacket %d, setting to %d\n",
347+
cfgno, inum, asnum, d->bEndpointAddress, maxp, j);
348+
maxp = j;
349+
endpoint->desc.wMaxPacketSize = cpu_to_le16(i | maxp);
350+
}
351+
289352
/*
290353
* Some buggy high speed devices have bulk endpoints using
291354
* maxpacket sizes other than 512. High speed HCDs may not
292355
* be able to handle that particular bug, so let's warn...
293356
*/
294357
if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
295358
&& usb_endpoint_xfer_bulk(d)) {
296-
unsigned maxp;
297-
298-
maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff;
299359
if (maxp != 512)
300360
dev_warn(ddev, "config %d interface %d altsetting %d "
301361
"bulk endpoint 0x%X has invalid maxpacket %d\n",

0 commit comments

Comments
 (0)