diff options
author | Bjørn Mork <bjorn@mork.no> | 2012-05-09 13:53:23 +0200 |
---|---|---|
committer | Bjørn Mork <bjorn@mork.no> | 2012-06-04 21:58:17 +0200 |
commit | 95ad527ab831fb084c45489166119baeb2910103 (patch) | |
tree | 4b6022b3bea5202ea5e98ec85e921ab95e603608 | |
parent | de2be7a8b4eefbb63d0e60568771a6a91624a10f (diff) |
USB: cdc-wdm: remove from device list on disconnect
Prevents dereferencing an invalid struct usb_interface
pointer.
Always delete entry from device list whether or not the
rest of the device state cleanup is postponed. The device
list uses desc->intf as key, and wdm_open will dereference
this key while searching for a matching device. A device
should not appear in the list unless probe() has succeeded
and disconnect() has not finished.
Cc: Oliver Neukum <oliver@neukum.org>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 6286d85e8efdb59252d1ceb99a56fa6b0b11526c)
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 441287e8f39..2236fe763fc 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -309,9 +309,6 @@ static void free_urbs(struct wdm_device *desc) static void cleanup(struct wdm_device *desc) { - spin_lock(&wdm_device_list_lock); - list_del(&desc->device_list); - spin_unlock(&wdm_device_list_lock); kfree(desc->sbuf); kfree(desc->inbuf); kfree(desc->orq); @@ -782,6 +779,9 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor out: return rv; err: + spin_lock(&wdm_device_list_lock); + list_del(&desc->device_list); + spin_unlock(&wdm_device_list_lock); cleanup(desc); return rv; } @@ -907,6 +907,12 @@ static void wdm_disconnect(struct usb_interface *intf) cancel_work_sync(&desc->rxwork); mutex_unlock(&desc->wlock); mutex_unlock(&desc->rlock); + + /* the desc->intf pointer used as list key is now invalid */ + spin_lock(&wdm_device_list_lock); + list_del(&desc->device_list); + spin_unlock(&wdm_device_list_lock); + if (!desc->count) cleanup(desc); else |