I've been seeing these intermittent failures to reclaim an interface after
a device reset. After much debugging and inserting sleeps in strategic
places to make the race window larger I've found the following race:
1) A user is running some software using libusb which will automatically
   detect, and "bind" to, any newly plugged in USB-devices. For example
   a virtual machine viewer with automatic USB-redirection
2) The user plugs in a new usb-storage device
3) The usb-storage driver is not yet loaded, udev spawns
   "modprobe usb-storage", this blocks on disk-io
4) The libusb app opens the device, claims all interfaces, does a device-reset
5) While the IOCTL_USBFS_RESET is running the modprobe completes
6) The driver registration blocks on an USB lock held by the reset code path
7) When the reset finishes the driver registration completes and the driver
   binds itself tp the device, before IOCTL_USBFS_RESET returns to userspace
8) libusb tries to re-claim all interfaces it had claimed before the reset
9) libusb fails as usb-storage is now bound to it

This patch works around this issue by simply unbinding the driver for all
interfaces which were claimed before the reset. Normally this is a no-op as
no driver (other then usbfs) can be bound for claimed interfaces before the
reset.

But as the above example shows, the exception is a driver completing
registration, and as part of this binding to any elegible devices, between
IOCTL_USBFS_RESET and our re-claiming of the interface. The largest part
of the race window here is the time IOCTL_USBFS_RESET takes, as that does a
fair amount of IO with the device. This part of the race window is
worked around by this patch.

This still leaves a theoretical race window where the driver registration
finishes between our driver-unbind and interface-reclaim, I'm afraid there
is nothing we can against this.

This patch also improves the error logging, and makes libusb_device_reset
properly return an error when re-claiming fails.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 libusb/os/linux_usbfs.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 3894554..10d138a 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -108,6 +108,9 @@ static int sysfs_can_relate_devices = 0;
 /* do we have a descriptors file? */
 static int sysfs_has_descriptors = 0;
 
+static int op_detach_kernel_driver(struct libusb_device_handle *handle,
+       int interface);
+
 struct linux_device_priv {
        char *sysfs_dir;
        unsigned char *dev_descriptor;
@@ -1497,11 +1500,20 @@ static int op_reset_device(struct libusb_device_handle 
*handle)
        /* And re-claim any interfaces which were claimed before the reset */
        for (i = 0; i < USB_MAXINTERFACES; i++) {
                if (handle->claimed_interfaces & (1L << i)) {
+                       /*
+                        * A driver may have completed modprobing during
+                        * IOCTL_USBFS_RESET, and bound itself as soon as
+                        * IOCTL_USBFS_RESET released the device lock
+                        */
+                       op_detach_kernel_driver(handle, i);
+
                        r = op_claim_interface(handle, i);
                        if (r) {
                                usbi_warn(HANDLE_CTX(handle),
-                                       "failed to re-claim interface %d after 
reset", i);
+                                       "failed to re-claim interface %d after 
reset: %s",
+                                       i, libusb_error_name(r));
                                handle->claimed_interfaces &= ~(1L << i);
+                               ret = LIBUSB_ERROR_NOT_FOUND;
                        }
                }
        }
-- 
1.7.10.4


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
libusbx-devel mailing list
libusbx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libusbx-devel

Reply via email to