On Fri, 13 Sep 2013, Bjorn Helgaas wrote:
> On Fri, Sep 13, 2013 at 12:25 PM, Alan Stern <[email protected]>
> wrote:
> > On Fri, 13 Sep 2013, Bjorn Helgaas wrote:
> >
> >> usb_bus_list_lock protects the usb_bus_list, and we don't touch that list
> >> in usb_disconnect(), so there's no reason to hold the lock here.
> >
> > The code says:
> >
> > /* used when updating list of hcds */
> > DEFINE_MUTEX(usb_bus_list_lock); /* exported only for usbfs */
> > EXPORT_SYMBOL_GPL (usb_bus_list_lock);
> >
> > Unforunately, the first comment is incomplete. usb_bus_list_lock
> > protects both the list of buses and also the set of root hubs. That's
> > why it isn't needed in hub_quiesce() and hub_port_connect_change();
> > those routines remove only non-root devices.
> >
> > Removing the usages in usb_add_hcd() and usb_remove_hcd() isn't safe.
> > You can see where this usage is important in
> > devices.c:usb_device_read().
>
> I don't know how the set of root hubs is managed, so I don't see the
> conflict between, e.g., usb_remove_hcd() and usb_device_read(). I'm
> not looking to become a USB expert, so I'll just take your word for it
> -- I don't want to waste more of your time on it.
Very briefly, usb_device_read() dereferences bus->root_hub:
usb_lock_device(bus->root_hub);
On the other hand, usb_remove_hcd() calls both
usb_disconnect(&rhdev);
and
usb_put_dev(hcd->self.root_hub);
(note that rhdev == hcd->self.root_hub == bus->root_hub), which
unregisters and deallocates the root_hub structure. Something has to
prevent usb_device_read() from accessing the structure after it has
been unregistered and freed; that's where usb_bus_list_lock comes in.
Alan Stern
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html