[RFC option 2] usb: rh_call_control tbuf overflow fix

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch modifies the buffer tbuf in the rh_call_control()
function to allow for larger USB descriptors to be passed.

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, however, is statically allocated on the stack with a size
of 15 bytes, regardless of the size specified in the URB.
When this buffer is passed to the hcd via the hub_control() call,
it is advertized as being as large as the URB buffer ( via
wLength ).

when the 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 ) causes tbuf to overflow
onto the stack.

Signed-off-by: Sean O. Stalley <sean.stalley@xxxxxxxxx>
---
 drivers/usb/core/hcd.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 014dc99..000f1e3 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -464,11 +464,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
 	struct usb_ctrlrequest *cmd;
  	u16		typeReq, wValue, wIndex, wLength;
 	u8		*ubuf = urb->transfer_buffer;
-	/*
-	 * tbuf should be as big as the BOS descriptor and
-	 * the USB hub descriptor.
-	 */
-	u8		tbuf[USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE]
+	u8		tbuf[sizeof(struct usb_hub_descriptor)]
 		__attribute__((aligned(4)));
 	const u8	*bufp = tbuf;
 	unsigned	len = 0;
@@ -644,7 +640,8 @@ nongeneric:
 		}
 		status = hcd->driver->hub_control (hcd,
 			typeReq, wValue, wIndex,
-			tbuf, wLength);
+			ubuf, wLength);
+		bufp = ubuf;
 
 		if (typeReq == GetHubDescriptor)
 			usb_hub_adjust_deviceremovable(hcd->self.root_hub,
@@ -674,7 +671,8 @@ error:
 			len = urb->transfer_buffer_length;
 		urb->actual_length = len;
 		// always USB_DIR_IN, toward host
-		memcpy (ubuf, bufp, len);
+		if (ubuf != bufp)
+			memcpy(ubuf, bufp, len);
 
 		/* report whether RH hardware supports remote wakeup */
 		if (patch_wakeup &&
-- 
1.8.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux