From: Alexander Shishkin Date: Wed, 12 Sep 2012 11:48:31 +0000 (+0300) Subject: usb: move children deallocation after quiescing the hub X-Git-Tag: firefly_0821_release~3680^2~1975^2~136 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=1f2235b8e79bd276f19809f7f2a270f55909d695;p=firefly-linux-kernel-4.4.55.git 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 --- diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index aa45e43e0ca9..6dc41c6399de 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)