aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hcd.c
diff options
context:
space:
mode:
authorSean O. Stalley <sean.stalley@intel.com>2013-08-13 13:36:12 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-14 15:18:26 -0400
commite57e780b346a7277fdd3bde765d9d8728b99bfa1 (patch)
treecf70344525eaab31cc6798d61da2f9c4ea3ee785 /drivers/usb/core/hcd.c
parent726a85caa30201eaadb993397a3e8ec23949c608 (diff)
usb: rh_call_control tbuf overflow fix
rh_call_control() contains a buffer, tbuf, which it uses to hold USB descriptors. These discriptors are eventually copied into the transfer_buffer in the URB. The buffer in the URB is dynamically defined and is always large enough to hold the amount of data it requests. tbuf is currently statically allocated on the stack with a size of 15 bytes, regardless of the size specified in the URB. This patch dynamically allocates tbuf, and ensures that tbuf is at least as big as the buffer in the URB. If an hcd attempts to write a descriptor containing more than 15 bytes ( such as the Standard BOS Descriptor for hubs, defined in the USB3.0 Spec, section 10.13.1 ) the write would overflow the buffer and corrupt the stack. This patch addresses this behavior. Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Sean O. Stalley <sean.stalley@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r--drivers/usb/core/hcd.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 5aa1d133eaf9..19ad3d2f8a24 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -466,17 +466,13 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
466 struct usb_ctrlrequest *cmd; 466 struct usb_ctrlrequest *cmd;
467 u16 typeReq, wValue, wIndex, wLength; 467 u16 typeReq, wValue, wIndex, wLength;
468 u8 *ubuf = urb->transfer_buffer; 468 u8 *ubuf = urb->transfer_buffer;
469 /*
470 * tbuf should be as big as the BOS descriptor and
471 * the USB hub descriptor.
472 */
473 u8 tbuf[USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE]
474 __attribute__((aligned(4)));
475 const u8 *bufp = tbuf;
476 unsigned len = 0; 469 unsigned len = 0;
477 int status; 470 int status;
478 u8 patch_wakeup = 0; 471 u8 patch_wakeup = 0;
479 u8 patch_protocol = 0; 472 u8 patch_protocol = 0;
473 u16 tbuf_size;
474 u8 *tbuf = NULL;
475 const u8 *bufp;
480 476
481 might_sleep(); 477 might_sleep();
482 478
@@ -496,6 +492,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
496 if (wLength > urb->transfer_buffer_length) 492 if (wLength > urb->transfer_buffer_length)
497 goto error; 493 goto error;
498 494
495 /*
496 * tbuf should be at least as big as the
497 * USB hub descriptor.
498 */
499 tbuf_size = max_t(u16, sizeof(struct usb_hub_descriptor), wLength);
500 tbuf = kzalloc(tbuf_size, GFP_KERNEL);
501 if (!tbuf)
502 return -ENOMEM;
503
504 bufp = tbuf;
505
506
499 urb->actual_length = 0; 507 urb->actual_length = 0;
500 switch (typeReq) { 508 switch (typeReq) {
501 509
@@ -693,6 +701,8 @@ error:
693 bDeviceProtocol = USB_HUB_PR_HS_SINGLE_TT; 701 bDeviceProtocol = USB_HUB_PR_HS_SINGLE_TT;
694 } 702 }
695 703
704 kfree(tbuf);
705
696 /* any errors get returned through the urb completion */ 706 /* any errors get returned through the urb completion */
697 spin_lock_irq(&hcd_root_hub_lock); 707 spin_lock_irq(&hcd_root_hub_lock);
698 usb_hcd_unlink_urb_from_ep(hcd, urb); 708 usb_hcd_unlink_urb_from_ep(hcd, urb);