From: "Måns Rullgård" <mans@mansr.com>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: linux-usb@vger.kernel.org
Subject: Re: Crash while capturing with usbmon
Date: Fri, 06 Mar 2020 17:48:48 +0000 [thread overview]
Message-ID: <yw1xy2sdidbz.fsf@mansr.com> (raw)
In-Reply-To: <Pine.LNX.4.44L0.2003061211340.1480-100000@iolanthe.rowland.org> (Alan Stern's message of "Fri, 6 Mar 2020 12:27:25 -0500 (EST)")
Alan Stern <stern@rowland.harvard.edu> writes:
> On Fri, 6 Mar 2020, Måns Rullgård wrote:
>
>> Alan Stern <stern@rowland.harvard.edu> writes:
>>
>> > On Thu, 5 Mar 2020, Måns Rullgård wrote:
>> >
>> >> While trying to capture some USB traffic, this happened:
>> >>
>> >> 8<--- cut here ---
>> >> Unable to handle kernel paging request at virtual address ffeff000
>> > ...
>> >> [<c069e0a8>] (memcpy) from [<c050c88c>] (mon_copy_to_buff+0x4c/0x6c)
>> >> [<c050c88c>] (mon_copy_to_buff) from [<c050cd2c>] (mon_bin_event+0x480/0x7b8)
>> >> [<c050cd2c>] (mon_bin_event) from [<c050ade4>] (mon_bus_complete+0x50/0x6c)
>> > ...
>> >
>> >> It is easily reproducible. What can I do to narrow down the cause?
>> >
>> > What kind of USB traffic were you monitoring? Isochronous?
>> > Scatter-gather?
>> >
>> > Can you add printk statements in drivers/usb/mon/mon_bin.c:
>> > mon_bin_get_data() to determine which of the pathways was used for
>> > calling mon_copy_buff() and what the values of the arguments were?
>>
>> OK, I added a printk to mon_bin_get_data(), and the bad call has
>> offset=4736, length=4096 urb->num_sgs=0 urb->transfer_flags=0x281,
>> urb->transfer_buffer=0xffefee00.
>
> The values seem reasonable enough, except for transfer_buffer.
>
>> I guess the question now is how transfer_buffer got assigned that value.
>
> Depending on how your kernel is configured (in particular, whether
> CONFIG_MUSB_PIO_ONLY is enabled), it might be assigned in
> musb_alloc_temp_buffer() (in drivers/usb/musb/musb_host.c) or
> usb_sg_init() (in drivers/usb/core/message.c).
>
> With a little more detective work you ought to be to determine which
> pathway is being used and what its important values are. I wouldn't be
> surprised to learn that 0xffefee0 was the value from sg_virt(sg) in
> usb_sg_init().
I found the problem. Initially, usb_sg_init() sets transfer_buffer to
NULL like this:
if (!PageHighMem(sg_page(sg)))
urb->transfer_buffer = sg_virt(sg);
else
urb->transfer_buffer = NULL;
Later, musb_host_rx() uses sg_miter_next() to assign a temporary
address:
/*
* We need to map sg if the transfer_buffer is
* NULL.
*/
if (!urb->transfer_buffer) {
qh->use_sg = true;
sg_miter_start(&qh->sg_miter, urb->sg, 1,
sg_flags);
}
if (qh->use_sg) {
if (!sg_miter_next(&qh->sg_miter)) {
dev_err(musb->controller, "error: sg list empty\n");
sg_miter_stop(&qh->sg_miter);
status = -EINVAL;
done = true;
goto finish;
}
urb->transfer_buffer = qh->sg_miter.addr;
received_len = urb->actual_length;
qh->offset = 0x0;
done = musb_host_packet_rx(musb, urb, epnum,
iso_err);
/* Calculate the number of bytes received */
received_len = urb->actual_length -
received_len;
qh->sg_miter.consumed = received_len;
sg_miter_stop(&qh->sg_miter);
} else {
done = musb_host_packet_rx(musb, urb,
epnum, iso_err);
}
When the transfer has completed, a bogus value is left behind in
urb->transfer_buffer, and this trips up usbmon. Apparently nothing else
uses that value before the urb is released.
This patch makes it not crash:
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 1c813c37462a..b67b40de1947 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1459,8 +1459,10 @@ void musb_host_tx(struct musb *musb, u8 epnum)
qh->segsize = length;
if (qh->use_sg) {
- if (offset + length >= urb->transfer_buffer_length)
+ if (offset + length >= urb->transfer_buffer_length) {
qh->use_sg = false;
+ urb->transfer_buffer = NULL;
+ }
}
musb_ep_select(mbase, epnum);
@@ -1977,8 +1979,10 @@ void musb_host_rx(struct musb *musb, u8 epnum)
urb->actual_length += xfer_len;
qh->offset += xfer_len;
if (done) {
- if (qh->use_sg)
+ if (qh->use_sg) {
qh->use_sg = false;
+ urb->transfer_buffer = NULL;
+ }
if (urb->status == -EINPROGRESS)
urb->status = status;
--
Måns Rullgård
next prev parent reply other threads:[~2020-03-06 17:48 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-05 19:26 Crash while capturing with usbmon Måns Rullgård
2020-03-05 21:09 ` Alan Stern
2020-03-05 21:53 ` Måns Rullgård
2020-03-06 12:38 ` Måns Rullgård
2020-03-06 17:27 ` Alan Stern
2020-03-06 17:48 ` Måns Rullgård [this message]
2020-03-06 18:18 ` Alan Stern
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=yw1xy2sdidbz.fsf@mansr.com \
--to=mans@mansr.com \
--cc=linux-usb@vger.kernel.org \
--cc=stern@rowland.harvard.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).