* [PATCH v2 1/6] usb: dwc3: ep0: Fix mem corruption on OUT transfers of more than 512 bytes
2015-07-24 6:47 [PATCH v2 0/6] usb: dwc3: handle non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
@ 2015-07-24 6:47 ` Kishon Vijay Abraham I
2015-07-24 6:47 ` [PATCH v2 2/6] usb: dwc3: ep0: use _roundup_ to calculate the transfer size Kishon Vijay Abraham I
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Kishon Vijay Abraham I @ 2015-07-24 6:47 UTC (permalink / raw)
To: balbi, linux-usb, linux-omap, linux-kernel; +Cc: gregkh, kishon, nsekhar
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.
Cc: <stable <at> vger.kernel.org> #3.4+
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
Steps to see the issue (before this patch)
1) Insert g_zero in DUT
2) run './testusb -t 14 -c 1 -s 520 -v 1' in host (size should be > 512)
The test should FAIL since bounce buffer can handle only 512 bytes, but the
test PASS. There is a WARN dump in DUT but still there will be memory
corruption since the bounce buffer overflows.
After the patch, the tests timeout!
./testusb -t 14 -c 1 -s 514 -v 1
unknown speed /dev/bus/usb/001/018 0
/dev/bus/usb/001/018 test 14 --> 110 (Connection timed out)
Tested this patch using USB3 Gen X CV (ch9 tests: usb2 and usb3, link layer
testing and MSC tests) and using USB2 X CV (ch9 tests, MSC tests).
drivers/usb/dwc3/ep0.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2ef3c8d..8858c60 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -816,6 +816,11 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
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);
@@ -937,11 +942,14 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
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;
/*
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 2/6] usb: dwc3: ep0: use _roundup_ to calculate the transfer size
2015-07-24 6:47 [PATCH v2 0/6] usb: dwc3: handle non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
2015-07-24 6:47 ` [PATCH v2 1/6] usb: dwc3: ep0: Fix mem corruption on OUT transfers of more than 512 bytes Kishon Vijay Abraham I
@ 2015-07-24 6:47 ` Kishon Vijay Abraham I
2015-07-24 6:47 ` [PATCH v2 3/6] usb: dwc3: ep0: preparation for handling non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Kishon Vijay Abraham I @ 2015-07-24 6:47 UTC (permalink / raw)
To: balbi, linux-usb, linux-omap, linux-kernel; +Cc: gregkh, kishon, nsekhar
No functional change. Used _roundup_ macro to calculate the transfer
size aligned to maxpacket in dwc3_ep0_complete_data. It also makes it
similar to how transfer size is calculated in __dwc3_ep0_do_control_data.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/usb/dwc3/ep0.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 8858c60..713e46a 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -812,10 +812,8 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
length = trb->size & DWC3_TRB_SIZE_MASK;
if (dwc->ep0_bounced) {
- unsigned transfer_size = ur->length;
unsigned maxp = ep0->endpoint.maxpacket;
-
- transfer_size += (maxp - (transfer_size % maxp));
+ unsigned transfer_size = roundup(ur->length, maxp);
/* Maximum of DWC3_EP0_BOUNCE_SIZE can only be received */
if (transfer_size > DWC3_EP0_BOUNCE_SIZE)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 3/6] usb: dwc3: ep0: preparation for handling non maxpacket aligned transfers > 512
2015-07-24 6:47 [PATCH v2 0/6] usb: dwc3: handle non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
2015-07-24 6:47 ` [PATCH v2 1/6] usb: dwc3: ep0: Fix mem corruption on OUT transfers of more than 512 bytes Kishon Vijay Abraham I
2015-07-24 6:47 ` [PATCH v2 2/6] usb: dwc3: ep0: use _roundup_ to calculate the transfer size Kishon Vijay Abraham I
@ 2015-07-24 6:47 ` Kishon Vijay Abraham I
2015-07-24 6:47 ` [PATCH v2 4/6] usb: dwc3; ep0: Modify _dwc3_ep0_start_trans_ API to take 'chain' parameter Kishon Vijay Abraham I
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Kishon Vijay Abraham I @ 2015-07-24 6:47 UTC (permalink / raw)
To: balbi, linux-usb, linux-omap, linux-kernel; +Cc: gregkh, kishon, nsekhar
No functional change. This is in preparation for handling non maxpacket
aligned transfers greater than bounce buffer size. This is basically to
avoid code duplication when using chained TRB transfers to handle
non maxpacket aligned transfers greater than bounce buffer size.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/usb/dwc3/ep0.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 713e46a..4998074 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -779,7 +779,11 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
struct usb_request *ur;
struct dwc3_trb *trb;
struct dwc3_ep *ep0;
- u32 transferred;
+ unsigned transfer_size = 0;
+ unsigned maxp;
+ unsigned remaining_ur_length;
+ void *buf;
+ u32 transferred = 0;
u32 status;
u32 length;
u8 epnum;
@@ -808,20 +812,24 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
}
ur = &r->request;
+ buf = ur->buf;
+ remaining_ur_length = ur->length;
length = trb->size & DWC3_TRB_SIZE_MASK;
+ maxp = ep0->endpoint.maxpacket;
+
if (dwc->ep0_bounced) {
- unsigned maxp = ep0->endpoint.maxpacket;
- unsigned transfer_size = roundup(ur->length, maxp);
+ transfer_size = roundup((ur->length - 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);
+ transferred = min_t(u32, remaining_ur_length,
+ transfer_size - length);
+ memcpy(buf, dwc->ep0_bounce, transferred);
} else {
transferred = ur->length - length;
}
@@ -930,7 +938,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
DWC3_TRBCTL_CONTROL_DATA);
} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
&& (dep->number == 0)) {
- u32 transfer_size;
+ u32 transfer_size = 0;
u32 maxpacket;
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
@@ -941,7 +949,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
}
maxpacket = dep->endpoint.maxpacket;
- transfer_size = roundup(req->request.length, maxpacket);
+ transfer_size = roundup((req->request.length - transfer_size),
+ maxpacket);
if (transfer_size > DWC3_EP0_BOUNCE_SIZE) {
dev_WARN(dwc->dev, "bounce buf can't handle req len\n");
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 4/6] usb: dwc3; ep0: Modify _dwc3_ep0_start_trans_ API to take 'chain' parameter
2015-07-24 6:47 [PATCH v2 0/6] usb: dwc3: handle non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
` (2 preceding siblings ...)
2015-07-24 6:47 ` [PATCH v2 3/6] usb: dwc3: ep0: preparation for handling non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
@ 2015-07-24 6:47 ` Kishon Vijay Abraham I
[not found] ` <1437720436-4261-5-git-send-email-kishon-l0cyMroinI0@public.gmane.org>
2015-07-24 6:47 ` [PATCH v2 5/6] usb: dwc3: ep0: Add chained TRB support Kishon Vijay Abraham I
` (2 subsequent siblings)
6 siblings, 1 reply; 9+ messages in thread
From: Kishon Vijay Abraham I @ 2015-07-24 6:47 UTC (permalink / raw)
To: balbi, linux-usb, linux-omap, linux-kernel; +Cc: gregkh, kishon, nsekhar
No functional change. Added a new parameter in _dwc3_ep0_start_trans_ to
indicate whether the TRB is a chained TRB or last TRB. This is in
preparation for adding chained TRB support for ep0.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/usb/dwc3/ep0.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 4998074..d1a2be1 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -56,7 +56,7 @@ static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
}
static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
- u32 len, u32 type)
+ u32 len, u32 type, unsigned chain)
{
struct dwc3_gadget_ep_cmd_params params;
struct dwc3_trb *trb;
@@ -302,7 +302,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
int ret;
ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
- DWC3_TRBCTL_CONTROL_SETUP);
+ DWC3_TRBCTL_CONTROL_SETUP, false);
WARN_ON(ret < 0);
}
@@ -851,7 +851,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
ret = dwc3_ep0_start_trans(dwc, epnum,
dwc->ctrl_req_addr, 0,
- DWC3_TRBCTL_CONTROL_DATA);
+ DWC3_TRBCTL_CONTROL_DATA, false);
WARN_ON(ret < 0);
}
}
@@ -935,7 +935,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
if (req->request.length == 0) {
ret = dwc3_ep0_start_trans(dwc, dep->number,
dwc->ctrl_req_addr, 0,
- DWC3_TRBCTL_CONTROL_DATA);
+ DWC3_TRBCTL_CONTROL_DATA, false);
} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
&& (dep->number == 0)) {
u32 transfer_size = 0;
@@ -966,7 +966,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
*/
ret = dwc3_ep0_start_trans(dwc, dep->number,
dwc->ep0_bounce_addr, transfer_size,
- DWC3_TRBCTL_CONTROL_DATA);
+ DWC3_TRBCTL_CONTROL_DATA, false);
} else {
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
@@ -976,7 +976,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
}
ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
- req->request.length, DWC3_TRBCTL_CONTROL_DATA);
+ req->request.length, DWC3_TRBCTL_CONTROL_DATA,
+ false);
}
WARN_ON(ret < 0);
@@ -991,7 +992,7 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
: DWC3_TRBCTL_CONTROL_STATUS2;
return dwc3_ep0_start_trans(dwc, dep->number,
- dwc->ctrl_req_addr, 0, type);
+ dwc->ctrl_req_addr, 0, type, false);
}
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 5/6] usb: dwc3: ep0: Add chained TRB support
2015-07-24 6:47 [PATCH v2 0/6] usb: dwc3: handle non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
` (3 preceding siblings ...)
2015-07-24 6:47 ` [PATCH v2 4/6] usb: dwc3; ep0: Modify _dwc3_ep0_start_trans_ API to take 'chain' parameter Kishon Vijay Abraham I
@ 2015-07-24 6:47 ` Kishon Vijay Abraham I
2015-07-24 6:47 ` [PATCH v2 6/6] usb: dwc3: ep0: handle non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
2015-07-24 6:49 ` [RESEND PATCH v2 1/6] usb: dwc3: ep0: Fix mem corruption on OUT transfers of more than 512 bytes Kishon Vijay Abraham I
6 siblings, 0 replies; 9+ messages in thread
From: Kishon Vijay Abraham I @ 2015-07-24 6:47 UTC (permalink / raw)
To: balbi, linux-usb, linux-omap, linux-kernel; +Cc: gregkh, kishon, nsekhar
Add chained TRB support to ep0. Now TRB's can be chained just by
invoking _dwc3_ep0_start_trans_ with 'chain' parameter set to true.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/usb/dwc3/ep0.c | 16 +++++++++++++---
drivers/usb/dwc3/gadget.c | 2 +-
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index d1a2be1..6847afe 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -70,7 +70,10 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
return 0;
}
- trb = dwc->ep0_trb;
+ trb = &dwc->ep0_trb[dep->free_slot];
+
+ if (chain)
+ dep->free_slot++;
trb->bpl = lower_32_bits(buf_dma);
trb->bph = upper_32_bits(buf_dma);
@@ -78,10 +81,17 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
trb->ctrl = type;
trb->ctrl |= (DWC3_TRB_CTRL_HWO
- | DWC3_TRB_CTRL_LST
- | DWC3_TRB_CTRL_IOC
| DWC3_TRB_CTRL_ISP_IMI);
+ if (chain)
+ trb->ctrl |= DWC3_TRB_CTRL_CHN;
+ else
+ trb->ctrl |= (DWC3_TRB_CTRL_IOC
+ | DWC3_TRB_CTRL_LST);
+
+ if (chain)
+ return 0;
+
memset(¶ms, 0, sizeof(params));
params.param0 = upper_32_bits(dwc->ep0_trb_addr);
params.param1 = lower_32_bits(dwc->ep0_trb_addr);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index d97fcfa..2feed9e 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2687,7 +2687,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err0;
}
- dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+ dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
&dwc->ep0_trb_addr, GFP_KERNEL);
if (!dwc->ep0_trb) {
dev_err(dwc->dev, "failed to allocate ep0 trb\n");
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 6/6] usb: dwc3: ep0: handle non maxpacket aligned transfers > 512
2015-07-24 6:47 [PATCH v2 0/6] usb: dwc3: handle non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
` (4 preceding siblings ...)
2015-07-24 6:47 ` [PATCH v2 5/6] usb: dwc3: ep0: Add chained TRB support Kishon Vijay Abraham I
@ 2015-07-24 6:47 ` Kishon Vijay Abraham I
2015-07-24 6:49 ` [RESEND PATCH v2 1/6] usb: dwc3: ep0: Fix mem corruption on OUT transfers of more than 512 bytes Kishon Vijay Abraham I
6 siblings, 0 replies; 9+ messages in thread
From: Kishon Vijay Abraham I @ 2015-07-24 6:47 UTC (permalink / raw)
To: balbi, linux-usb, linux-omap, linux-kernel; +Cc: gregkh, kishon, nsekhar
Use chained TRB mechanism to handle non maxpacket aligned transfers
greater than bounce buffer size. With this the first TRB will be programmed
to receive 'ALIGN(ur->length - maxp, maxp)' data and the second TRB
will be programmed to receive the remaining data using bounce buffer.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/usb/dwc3/ep0.c | 42 ++++++++++++++++++++++++++++--------------
1 file changed, 28 insertions(+), 14 deletions(-)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 6847afe..0dbc0c4 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -830,13 +830,26 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
maxp = ep0->endpoint.maxpacket;
if (dwc->ep0_bounced) {
+ /*
+ * Handle the first TRB before handling the bounce buffer if
+ * the request length is greater than the bounce buffer size
+ */
+ if (ur->length > DWC3_EP0_BOUNCE_SIZE) {
+ transfer_size = ALIGN(ur->length - maxp, maxp);
+ transferred = transfer_size - length;
+ buf = (u8 *)buf + transferred;
+ ur->actual += transferred;
+ remaining_ur_length -= transferred;
+
+ trb++;
+ length = trb->size & DWC3_TRB_SIZE_MASK;
+
+ ep0->free_slot = 0;
+ }
+
transfer_size = roundup((ur->length - 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, remaining_ur_length,
transfer_size - length);
memcpy(buf, dwc->ep0_bounce, transferred);
@@ -959,21 +972,22 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
}
maxpacket = dep->endpoint.maxpacket;
- transfer_size = roundup((req->request.length - transfer_size),
- 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;
+ if (req->request.length > DWC3_EP0_BOUNCE_SIZE) {
+ transfer_size = ALIGN(req->request.length - maxpacket,
+ maxpacket);
+ ret = dwc3_ep0_start_trans(dwc, dep->number,
+ req->request.dma,
+ transfer_size,
+ DWC3_TRBCTL_CONTROL_DATA,
+ true);
}
+ transfer_size = roundup((req->request.length - transfer_size),
+ maxpacket);
+
dwc->ep0_bounced = true;
- /*
- * REVISIT in case request length is bigger than
- * DWC3_EP0_BOUNCE_SIZE we will need two chained
- * TRBs to handle the transfer.
- */
ret = dwc3_ep0_start_trans(dwc, dep->number,
dwc->ep0_bounce_addr, transfer_size,
DWC3_TRBCTL_CONTROL_DATA, false);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* [RESEND PATCH v2 1/6] usb: dwc3: ep0: Fix mem corruption on OUT transfers of more than 512 bytes
2015-07-24 6:47 [PATCH v2 0/6] usb: dwc3: handle non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
` (5 preceding siblings ...)
2015-07-24 6:47 ` [PATCH v2 6/6] usb: dwc3: ep0: handle non maxpacket aligned transfers > 512 Kishon Vijay Abraham I
@ 2015-07-24 6:49 ` Kishon Vijay Abraham I
6 siblings, 0 replies; 9+ messages in thread
From: Kishon Vijay Abraham I @ 2015-07-24 6:49 UTC (permalink / raw)
To: balbi, linux-usb, linux-omap, linux-kernel; +Cc: gregkh, kishon, nsekhar
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.
Cc: stable@vger.kernel.org #3.4+
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
Fixed stable mail address now!
Steps to see the issue (before this patch)
1) Insert g_zero in DUT
2) run './testusb -t 14 -c 1 -s 520 -v 1' in host (size should be > 512)
The test should FAIL since bounce buffer can handle only 512 bytes, but the
test PASS. There is a WARN dump in DUT but still there will be memory
corruption since the bounce buffer overflows.
After the patch, the tests timeout!
./testusb -t 14 -c 1 -s 514 -v 1
unknown speed /dev/bus/usb/001/018 0
/dev/bus/usb/001/018 test 14 --> 110 (Connection timed out)
Tested this patch using USB3 Gen X CV (ch9 tests: usb2 and usb3, link layer
testing and MSC tests) and using USB2 X CV (ch9 tests, MSC tests).
drivers/usb/dwc3/ep0.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2ef3c8d..8858c60 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -816,6 +816,11 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
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);
@@ -937,11 +942,14 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
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;
/*
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread