darwin: fix SEGV on libusb_close after failed re-enumeration
authorNathan Hjelm <hjelmn@google.com>
Fri, 9 Jul 2021 04:43:28 +0000 (22:43 -0600)
committerNathan Hjelm <hjelmn@google.com>
Fri, 9 Jul 2021 04:45:07 +0000 (22:45 -0600)
This commit fixes an issue that can occur if the user calls libusb_close after a failed attempt
of libusb_reset (re-enumerate). This can lead to an attempt to dereference dpriv->device which
was set to NULL during the re-enumeration.

Signed-off-by: Nathan Hjelm <hjelmn@google.com>
libusb/os/darwin_usb.c
libusb/version_nano.h

index bad0d8e..5faf18a 100644 (file)
@@ -364,7 +364,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
   struct darwin_cached_device *old_device;
 
   io_service_t device;
-  UInt64 session;
+  UInt64 session, locationID;
   int ret;
 
   usbi_mutex_lock(&active_contexts_lock);
@@ -374,6 +374,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
 
     /* get the location from the i/o registry */
     ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
+    (void) get_ioregistry_value_number (device, CFSTR("locationID"), kCFNumberSInt32Type, &locationID);
     IOObjectRelease (device);
     if (!ret)
       continue;
@@ -386,7 +387,8 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
         if (old_device->in_reenumerate) {
           /* device is re-enumerating. do not dereference the device at this time. libusb_reset_device()
            * will deref if needed. */
-          usbi_dbg ("detected device detached due to re-enumeration");
+          usbi_dbg ("detected device detached due to re-enumeration. sessionID: 0x%" PRIx64 ", locationID: 0x%" PRIx64,
+                    session, locationID);
 
           /* the device object is no longer usable so go ahead and release it */
           if (old_device->device) {
@@ -1264,6 +1266,10 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
   }
 
   dpriv->open_count--;
+  if (NULL == dpriv->device) {
+    usbi_warn (HANDLE_CTX (dev_handle), "darwin_close device missing IOService");
+    return;
+  }
 
   /* make sure all interfaces are released */
   for (i = 0 ; i < USB_MAXINTERFACES ; i++)
index d91ea7a..9064596 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 11634
+#define LIBUSB_NANO 11635