commit ab2a4bf83902c170d29ba130a8abb5f9d90559e1
Author: Alan Stern <email address hidden>
Date: Mon Jun 27 10:23:10 2016 -0400
USB: don't free bandwidth_mutex too early
The USB core contains a bug that can show up when a USB-3 host
controller is removed. If the primary (USB-2) hcd structure is
released before the shared (USB-3) hcd, the core will try to do a
double-free of the common bandwidth_mutex.
The problem was described in graphical form by Chung-Geol Kim, who
first reported it:
This happens because hcd_release() frees the bandwidth_mutex whenever
it sees a primary hcd being released (which is not a very good idea
in any case), but in the course of releasing the primary hcd, it
changes the pointers in the shared hcd in such a way that the shared
hcd will appear to be primary when it gets released.
This patch fixes the problem by changing hcd_release() so that it
deallocates the bandwidth_mutex only when the _last_ hcd structure
referencing it is released. The patch also removes an unnecessary
test, so that when an hcd is released, both the shared_hcd and
primary_hcd pointers in the hcd's peer will be cleared.
Signed-off-by: Alan Stern <email address hidden>
Reported-by: Chung-Geol Kim <email address hidden>
Tested-by: Chung-Geol Kim <email address hidden>
CC: <email address hidden>
Signed-off-by: Greg Kroah-Hartman <email address hidden>
This commit can fix this issue
commit ab2a4bf83902c17 0d29ba130a8abb5 f9d90559e1
Author: Alan Stern <email address hidden>
Date: Mon Jun 27 10:23:10 2016 -0400
USB: don't free bandwidth_mutex too early
The USB core contains a bug that can show up when a USB-3 host
controller is removed. If the primary (USB-2) hcd structure is
released before the shared (USB-3) hcd, the core will try to do a
double-free of the common bandwidth_mutex.
The problem was described in graphical form by Chung-Geol Kim, who
first reported it:
=== ======= ======= ======= ======= ======= ======= ==== ======= ======= ======= ======= ======= ======= ====
VOLD ------- ------- ------- ------- -----|- ------- ----
(uevent)
___ _____|_ _______ _
|<1> |
|dwc3_ otg_sm_ work |
|usb_ put_hcd |
|peer_ hcd(kref= 2)|
|___ _______ _______ _|
___ _____|_ _______ _
|<2> |
|New USB BUS #2 |
| |
|peer_ hcd(kref= 1) |
| |
--(Link) -bandXX_ mutex|
| |______ _______ _____|
|
______ _______ ______ |
|dwc3_otg_ sm_work | |
|primary_ hcd(kref= 1)| |
|______ _______ ______| |
______ ___|___ ______ |
|primary_ hcd(kref= 0)| |
|bandXX_ mutex(free) |<-
|______ _______ ______|
(( VOLD ))
___ ___|___ _______ _
|<5> |
| SCSI |
|usb_ put_hcd |
|peer_ hcd(kref= 0) |
|*hcd_ release |
|bandXX_ mutex(free* )|<- double free
|___ _______ _______ _|
At *remove USB(3.0) Storage
sequence <1> --> <5> ((Problem Case))
===
---
|<3> | |
|usb_put_hcd | |
|<4> | |
|New USB BUS #1 | |
|hcd_release | |
| | |
=== ======= ======= ======= ======= ======= ======= ====
This happens because hcd_release() frees the bandwidth_mutex whenever
it sees a primary hcd being released (which is not a very good idea
in any case), but in the course of releasing the primary hcd, it
changes the pointers in the shared hcd in such a way that the shared
hcd will appear to be primary when it gets released.
This patch fixes the problem by changing hcd_release() so that it
deallocates the bandwidth_mutex only when the _last_ hcd structure
referencing it is released. The patch also removes an unnecessary
test, so that when an hcd is released, both the shared_hcd and
primary_hcd pointers in the hcd's peer will be cleared.
Signed-off-by: Alan Stern <email address hidden>
Reported-by: Chung-Geol Kim <email address hidden>
Tested-by: Chung-Geol Kim <email address hidden>
CC: <email address hidden>
Signed-off-by: Greg Kroah-Hartman <email address hidden>