From 1f2235b8e79bd276f19809f7f2a270f55909d695 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 12 Sep 2012 14:48:31 +0300 Subject: [PATCH] usb: move children deallocation after quiescing the hub Commit ff823c79a5c33194c2e5594f7c4686ea3547910c ("usb: move children to struct usb_port") forgot to consider the hub_disconnect sequence, which releases ports before quiescing the hub, which will lead to a use-after-free, since hub_quiesce() will try to disconnect ports' children, which are already deallocated. Simple modprobe dummy_hcd && rmmod dummy_hcd will illustrate the problem. This patch moves deallocation of hub's ports after hub_quiesce() call in hub_disconnect(). Cc: Lan Tianyu Signed-off-by: Alexander Shishkin Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index aa45e43..6dc41c6 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1584,9 +1584,6 @@ static void hub_disconnect(struct usb_interface *intf) struct usb_device *hdev = interface_to_usbdev(intf); int i; - for (i = 0; i < hdev->maxchild; i++) - usb_hub_remove_port_device(hub, i + 1); - /* Take the hub off the event list and don't let it be added again */ spin_lock_irq(&hub_event_lock); if (!list_empty(&hub->event_list)) { @@ -1601,6 +1598,9 @@ static void hub_disconnect(struct usb_interface *intf) hub_quiesce(hub, HUB_DISCONNECT); usb_set_intfdata (intf, NULL); + + for (i = 0; i < hdev->maxchild; i++) + usb_hub_remove_port_device(hub, i + 1); hub->hdev->maxchild = 0; if (hub->hdev->speed == USB_SPEED_HIGH) -- 2.7.4