usb: core: fix a double free in the usb driver
PATCH 1/1 usb: core: fix a double free in the usb driver
There is a double free problem in the usb driver. This is caused by delayed deregister for scsi device. <*> at Insert USB Storage
- USB bus #1 register
usb_create_hcd (primary-kref==1)
* primary-bandwidth_mutex(alloc))usb_get_hcd (primary-kref==2)
- USB bus #2 registerusb_create_hcd (second-kref==1)
* second-bandwidth_mutex==primary-bandwidth_mutex
usb_get_hcd (second-kref==2)
- scsi_device_getusb_get_hcd (second-kref==3)
<*> at remove USB Storage (Normal)
- scsi_device_putusb_put_hcd (second-kref==2)
- USB bus #2 deregister
usb_release_dev(second-kref==1)usb_release_dev(second-kref==0) -> hcd_release()
- USB bus #1 deregister
usb_release_dev(primary-kref==1)
usb_release_dev(primary-kref==0) -> hcd_release()*(primary-bandwidth_mutex free)
at remove USB Storage
- USB bus #2 deregister usb_release_dev(second-kref==2)usb_release_dev(second-kref==1)
- USB bus #1 deregister usb_release_dev(primary-kref==1) usb_release_dev(primary-kref==0) -> hcd_release() *(primary-bandwidth_mutex free)
- scsi_device_put
usb_put_hcd (second-kref==0) -> hcd_release(*)
* at this, second->primary==0 therefore try to
free the primary-bandwidth_mutex.(already freed)
To fix this problem kfree(hcd->bandwidth_mutex);
should be executed at only (hcd->primary_hcd==hcd).---drivers/usb/core/hcd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/core/hcd.c +0 -0
@@ -2608,7 +2608,7 @@ static void hcd_release(struct kref *kref)
struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
mutex_lock(&usb_port_peer_mutex);
- if (usb_hcd_is_primary_hcd(hcd)) {
+ if (hcd == hcd->primary_hcd) {kfree(hcd->address0_mutex);kfree(hcd->bandwidth_mutex);
}
Signature · 1 line
1.7.9.5
[email protected]
maintainerQuoted 1 line · Chung-Geol Kim
There is a double free problem in the usb driver.
Which driver?
Quoted 24 lines
This is caused by delayed deregister for scsi device. <*> at Insert USB Storage
- USB bus #1 register
usb_create_hcd(primary-kref==1)
* primary-bandwidth_mutex(alloc))usb_get_hcd(primary-kref==2)
- USB bus #2 registerusb_create_hcd(second-kref==1)
* second-bandwidth_mutex==primary-bandwidth_mutex
usb_get_hcd(second-kref==2)
-scsi_device_getusb_get_hcd(second-kref==3)<*> at remove USB Storage (Normal)
-scsi_device_putusb_put_hcd(second-kref==2)
- USB bus #2 deregister
usb_release_dev(second-kref==1)usb_release_dev(second-kref==0)->hcd_release()- USB bus #1 deregister usb_release_dev(primary-kref==1) usb_release_dev(primary-kref==0) -> hcd_release()*(primary-bandwidth_mutex free)
Quoted 12 lines
at remove USB Storage
- USB bus #2 deregisterusb_release_dev(second-kref==2)usb_release_dev(second-kref==1)
- USB bus #1 deregisterusb_release_dev(primary-kref==1)usb_release_dev(primary-kref==0)->hcd_release()*(primary-bandwidth_mutex free)
-scsi_device_put
usb_put_hcd(second-kref==0) ->hcd_release(*)
* at this, second->primary==0 therefore try to
free the primary-bandwidth_mutex.(already freed)
The formatting for this is all confused, can you fix it up?
Quoted 5 lines
To fix this problem kfree(hcd->bandwidth_mutex); should be executed at only (hcd->primary_hcd==hcd).Signed-off-by Chunggeol Kim
We need an email address at the end of this line, look at how the commits in the kernel git history look like for examples.
Quoted 9 lines
---
drivers/usb/core/hcd.c| 2 +-1 file changed, 1 insertion(+), 1 deletion(-)drivers/usb/core/hcd.c +0
-0
drivers/usb/core/hcd.c static void hcd_release(struct kref *kref) · line 2611
Quoted 5 lines
drivers/usb/core/hcd.c +1
-1@@ -2608,7 +2608,7 @@ static void hcd_release(struct kref *kref) struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);mutex_lock (&usb_port_peer_mutex); -if (usb_hcd_is_primary_hcd (hcd)) { +if (hcd == hcd->primary_hcd) {
That doesn't make sense, usb_hcd_is_primary_hcd() is the same as this check, what are you changing here?
drivers/usb/core/hcd.c static void hcd_release(struct kref *kref) · line 2614
Quoted 3 lines
drivers/usb/core/hcd.c +0
-0kfree (hcd->address0_mutex);kfree (hcd->bandwidth_mutex); }
Your patch itself is also corrupted, and can't be applied, can you also resolve this and resend?
thanks,
greg k-h