usb_deauthorize_device() tries to unset the configuration of a USB device and then unconditionally blows away the configuration descriptors with usb_destroy_configuration(). This is bad if the usb_set_configuration() call failed before the configuration could be correctly unset, since pointers like udev->actconfig can keep pointing to the now invalid memory. We have encountered hard to reproduce crashes from devices disconnected during suspend due to this, where khubd's disconnect handling races with userspace tools that change authorization on resume. This patch ensures that usb_deauthorize_device() aborts when usb_set_configuration() fails, and the underlying status code (such as ENODEV) is returned to userspace. Signed-off-by: Julius Werner <jwerner@xxxxxxxxxxxx> --- drivers/usb/core/hub.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a7c04e2..ade315f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2420,13 +2420,17 @@ fail: */ int usb_deauthorize_device(struct usb_device *usb_dev) { + int result = 0; + usb_lock_device(usb_dev); if (usb_dev->authorized == 0) goto out_unauthorized; - usb_dev->authorized = 0; - usb_set_configuration(usb_dev, -1); + result = usb_set_configuration(usb_dev, -1); + if (result) + goto error_deconfigure; + usb_dev->authorized = 0; kfree(usb_dev->product); usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); kfree(usb_dev->manufacturer); @@ -2437,9 +2441,10 @@ int usb_deauthorize_device(struct usb_device *usb_dev) usb_destroy_configuration(usb_dev); usb_dev->descriptor.bNumConfigurations = 0; +error_deconfigure: out_unauthorized: usb_unlock_device(usb_dev); - return 0; + return result; } -- 1.7.12.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html