linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eli Billauer <eli.billauer@gmail.com>
To: linux-usb@vger.kernel.org,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Hans de Goede <hdegoede@redhat.com>,
	Ming Lei <ming.lei@canonical.com>,
	Alan Stern <stern@rowland.harvard.edu>,
	Oliver Neukum <oliver@neukum.org>
Subject: usb: core: URB completer callback possibly called after usb_kill_anchored_urbs() returns
Date: Fri, 24 Jul 2020 15:46:40 +0300	[thread overview]
Message-ID: <5F1AD830.7050406@gmail.com> (raw)

Hello,

My understanding is it should be OK to assume that no calls to completer 
callbacks will be made after usb_kill_anchored_urbs() returns (for that 
anchor, of course). However __usb_hcd_giveback_urb() in 
drivers/usb/core/hcd.c doesn't seem to work that way. It unanchors 
first, then calls the complete method:

     usb_unanchor_urb(urb);
     if (likely(status == 0))
         usb_led_activity(USB_LED_EVENT_HOST);

     /* pass ownership to the completion handler */
     urb->status = status;
     kcov_remote_start_usb((u64)urb->dev->bus->busnum);
     urb->complete(urb);

So if usb_kill_anchored_urbs() is called while __usb_hcd_giveback_urb() 
is in the middle of this code passage, it will miss the URB that is 
being finished, and possibly return before the completer has been called.

It might sound like a theoretic race condition, but I actually got a 
kernel panic after yanking the USB plug in the middle of heavy traffic. 
The panic's call trace indicated that the driver's completer callback 
function attempted to access memory that had been freed previously. As 
this happened within an IRQ, it was a fullblown computer freeze.

The same driver's memory freeing mechanism indeed calls 
usb_kill_anchored_urbs() first, then frees the URBs' related data 
structure. So it seems like it freed the memory just before the 
completer callback was invoked.

I would love to submit a patch that moves the usb_unanchor_urb() call a 
few rows down, but something tells me it's not that simple.

As a side note, the comment along with commit 6ec4147, which added 
usb_anchor_{suspend,resume}_wakeups calls, said among others: "But 
__usb_hcd_giveback_urb() calls usb_unanchor_urb before calling the 
completion handler. This is necessary as the completion handler may 
re-submit and re-anchor the urb". Not sure I understood this part, though.

Any insights?

Thanks,
    Eli


             reply	other threads:[~2020-07-24 12:47 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-24 12:46 Eli Billauer [this message]
2020-07-24 15:51 ` usb: core: URB completer callback possibly called after usb_kill_anchored_urbs() returns Alan Stern
2020-07-25 16:44   ` Eli Billauer
2020-07-25 19:53     ` 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=5F1AD830.7050406@gmail.com \
    --to=eli.billauer@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=hdegoede@redhat.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=ming.lei@canonical.com \
    --cc=oliver@neukum.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).