aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2018-09-10 13:59:59 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-20 06:49:12 -0400
commitbd729f9d67aa9a303d8925bb8c4f06af25f407d1 (patch)
treea2e42a2dc0a0c05668c8b6894ec4e1c6d82ffd03
parentc183813fcee44a249339b7c46e1ad271ca1870aa (diff)
USB: fix error handling in usb_driver_claim_interface()
The syzbot fuzzing project found a use-after-free bug in the USB core. The bug was caused by usbfs not unbinding from an interface when the USB device file was closed, which led another process to attempt the unbind later on, after the private data structure had been deallocated. The reason usbfs did not unbind the interface at the appropriate time was because it thought the interface had never been claimed in the first place. This was caused by the fact that usb_driver_claim_interface() does not clean up properly when device_bind_driver() returns an error. Although the error code gets passed back to the caller, the iface->dev.driver pointer remains set and iface->condition remains equal to USB_INTERFACE_BOUND. This patch adds proper error handling to usb_driver_claim_interface(). Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Reported-by: syzbot+f84aa7209ccec829536f@syzkaller.appspotmail.com CC: <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/driver.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 7652dcb57998..a1f225f077cd 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -550,6 +550,21 @@ int usb_driver_claim_interface(struct usb_driver *driver,
550 if (device_is_registered(dev)) 550 if (device_is_registered(dev))
551 retval = device_bind_driver(dev); 551 retval = device_bind_driver(dev);
552 552
553 if (retval) {
554 dev->driver = NULL;
555 usb_set_intfdata(iface, NULL);
556 iface->needs_remote_wakeup = 0;
557 iface->condition = USB_INTERFACE_UNBOUND;
558
559 /*
560 * Unbound interfaces are always runtime-PM-disabled
561 * and runtime-PM-suspended
562 */
563 if (driver->supports_autosuspend)
564 pm_runtime_disable(dev);
565 pm_runtime_set_suspended(dev);
566 }
567
553 return retval; 568 return retval;
554} 569}
555EXPORT_SYMBOL_GPL(usb_driver_claim_interface); 570EXPORT_SYMBOL_GPL(usb_driver_claim_interface);