Skip to content

Commit 52974d9

Browse files
mansrgregkh
authored andcommitted
usb: musb: fix crash with highmen PIO and usbmon
When handling a PIO bulk transfer with highmem buffer, a temporary mapping is assigned to urb->transfer_buffer. After the transfer is complete, an invalid address is left behind in this pointer. This is not ordinarily a problem since nothing touches that buffer before the urb is released. However, when usbmon is active, usbmon_urb_complete() calls (indirectly) mon_bin_get_data() which does access the transfer buffer if it is set. To prevent an invalid memory access here, reset urb->transfer_buffer to NULL when finished (musb_host_rx()), or do not set it at all (musb_host_tx()). Fixes: 8e8a551 ("usb: musb: host: Handle highmem in PIO mode") Signed-off-by: Mans Rullgard <mans@mansr.com> Cc: stable@vger.kernel.org Signed-off-by: Bin Liu <b-liu@ti.com> Link: https://lore.kernel.org/r/20200316211136.2274-8-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent e72838d commit 52974d9

File tree

1 file changed

+5
-12
lines changed

1 file changed

+5
-12
lines changed

drivers/usb/musb/musb_host.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,20 +1436,16 @@ void musb_host_tx(struct musb *musb, u8 epnum)
14361436
* We need to map sg if the transfer_buffer is
14371437
* NULL.
14381438
*/
1439-
if (!urb->transfer_buffer)
1440-
qh->use_sg = true;
1441-
1442-
if (qh->use_sg) {
1439+
if (!urb->transfer_buffer) {
14431440
/* sg_miter_start is already done in musb_ep_program */
14441441
if (!sg_miter_next(&qh->sg_miter)) {
14451442
dev_err(musb->controller, "error: sg list empty\n");
14461443
sg_miter_stop(&qh->sg_miter);
14471444
status = -EINVAL;
14481445
goto done;
14491446
}
1450-
urb->transfer_buffer = qh->sg_miter.addr;
14511447
length = min_t(u32, length, qh->sg_miter.length);
1452-
musb_write_fifo(hw_ep, length, urb->transfer_buffer);
1448+
musb_write_fifo(hw_ep, length, qh->sg_miter.addr);
14531449
qh->sg_miter.consumed = length;
14541450
sg_miter_stop(&qh->sg_miter);
14551451
} else {
@@ -1458,11 +1454,6 @@ void musb_host_tx(struct musb *musb, u8 epnum)
14581454

14591455
qh->segsize = length;
14601456

1461-
if (qh->use_sg) {
1462-
if (offset + length >= urb->transfer_buffer_length)
1463-
qh->use_sg = false;
1464-
}
1465-
14661457
musb_ep_select(mbase, epnum);
14671458
musb_writew(epio, MUSB_TXCSR,
14681459
MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
@@ -1977,8 +1968,10 @@ void musb_host_rx(struct musb *musb, u8 epnum)
19771968
urb->actual_length += xfer_len;
19781969
qh->offset += xfer_len;
19791970
if (done) {
1980-
if (qh->use_sg)
1971+
if (qh->use_sg) {
19811972
qh->use_sg = false;
1973+
urb->transfer_buffer = NULL;
1974+
}
19821975

19831976
if (urb->status == -EINPROGRESS)
19841977
urb->status = status;

0 commit comments

Comments
 (0)