| From b2fb5b1a0f50d3ebc12342c8d8dead245e9c9d4e Mon Sep 17 00:00:00 2001 |
| From: Kishon Vijay Abraham I <kishon@ti.com> |
| Date: Mon, 27 Jul 2015 12:25:27 +0530 |
| Subject: usb: dwc3: ep0: Fix mem corruption on OUT transfers of more than 512 bytes |
| |
| From: Kishon Vijay Abraham I <kishon@ti.com> |
| |
| commit b2fb5b1a0f50d3ebc12342c8d8dead245e9c9d4e upstream. |
| |
| DWC3 uses bounce buffer to handle non max packet aligned OUT transfers and |
| the size of bounce buffer is 512 bytes. However if the host initiates OUT |
| transfers of size more than 512 bytes (and non max packet aligned), the |
| driver throws a WARN dump but still programs the TRB to receive more than |
| 512 bytes. This will cause bounce buffer to overflow and corrupt the |
| adjacent memory locations which can be fatal. |
| |
| Fix it by programming the TRB to receive a maximum of DWC3_EP0_BOUNCE_SIZE |
| (512) bytes. |
| |
| Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> |
| Signed-off-by: Felipe Balbi <balbi@ti.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/dwc3/ep0.c | 12 ++++++++++-- |
| 1 file changed, 10 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/usb/dwc3/ep0.c |
| +++ b/drivers/usb/dwc3/ep0.c |
| @@ -804,6 +804,11 @@ static void dwc3_ep0_complete_data(struc |
| unsigned maxp = ep0->endpoint.maxpacket; |
| |
| transfer_size += (maxp - (transfer_size % maxp)); |
| + |
| + /* Maximum of DWC3_EP0_BOUNCE_SIZE can only be received */ |
| + if (transfer_size > DWC3_EP0_BOUNCE_SIZE) |
| + transfer_size = DWC3_EP0_BOUNCE_SIZE; |
| + |
| transferred = min_t(u32, ur->length, |
| transfer_size - length); |
| memcpy(ur->buf, dwc->ep0_bounce, transferred); |
| @@ -916,11 +921,14 @@ static void __dwc3_ep0_do_control_data(s |
| return; |
| } |
| |
| - WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); |
| - |
| maxpacket = dep->endpoint.maxpacket; |
| transfer_size = roundup(req->request.length, maxpacket); |
| |
| + if (transfer_size > DWC3_EP0_BOUNCE_SIZE) { |
| + dev_WARN(dwc->dev, "bounce buf can't handle req len\n"); |
| + transfer_size = DWC3_EP0_BOUNCE_SIZE; |
| + } |
| + |
| dwc->ep0_bounced = true; |
| |
| /* |