aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2012-05-09 07:53:23 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-11 18:19:22 -0400
commit6286d85e8efdb59252d1ceb99a56fa6b0b11526c (patch)
tree37b91b39c74370899aedd708921f6774850cd52a /drivers/usb/class
parent6b0b79d38806481c1c8fffa7c5842f3c83679a42 (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>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/cdc-wdm.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 90bc916d7cb..631bb952d0f 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)
309 309
310static void cleanup(struct wdm_device *desc) 310static void cleanup(struct wdm_device *desc)
311{ 311{
312 spin_lock(&wdm_device_list_lock);
313 list_del(&desc->device_list);
314 spin_unlock(&wdm_device_list_lock);
315 kfree(desc->sbuf); 312 kfree(desc->sbuf);
316 kfree(desc->inbuf); 313 kfree(desc->inbuf);
317 kfree(desc->orq); 314 kfree(desc->orq);
@@ -782,6 +779,9 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
782out: 779out:
783 return rv; 780 return rv;
784err: 781err:
782 spin_lock(&wdm_device_list_lock);
783 list_del(&desc->device_list);
784 spin_unlock(&wdm_device_list_lock);
785 cleanup(desc); 785 cleanup(desc);
786 return rv; 786 return rv;
787} 787}
@@ -907,6 +907,12 @@ static void wdm_disconnect(struct usb_interface *intf)
907 cancel_work_sync(&desc->rxwork); 907 cancel_work_sync(&desc->rxwork);
908 mutex_unlock(&desc->wlock); 908 mutex_unlock(&desc->wlock);
909 mutex_unlock(&desc->rlock); 909 mutex_unlock(&desc->rlock);
910
911 /* the desc->intf pointer used as list key is now invalid */
912 spin_lock(&wdm_device_list_lock);
913 list_del(&desc->device_list);
914 spin_unlock(&wdm_device_list_lock);
915
910 if (!desc->count) 916 if (!desc->count)
911 cleanup(desc); 917 cleanup(desc);
912 else 918 else