summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-05-16 22:09:58 +0200
committerHans de Goede <hdegoede@redhat.com>2013-05-16 22:26:00 +0200
commit6391d86e818bf4ed63842cad278c2fb2572dc5d8 (patch)
treee5796d9bb1bdd716b24f7920960482a8f0c18b2b
parentc235fa2f9d90b6f65f75c545e90596545879ca4f (diff)
downloadlibusb-6391d86e818bf4ed63842cad278c2fb2572dc5d8.tar.gz
All: ref dev->parent_dev
An app can hold a reference to just a leave device, if then an entire hub goes away, all removed devices will get there final unref, except for the one ref-ed by the app. If the app then tries to use parent_dev in anyway after this, we've a use-after-free bug. This fixes this. Also remove the lets re-enumerate fix for this from libusb_get_port_path, I'm not sure what the exact idea behind this fix was, but after this patch it is no longer needed, and this patch also fixes usage of for example libusb_get_parent(). Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--libusb/core.c11
-rw-r--r--libusb/os/darwin_usb.c2
-rw-r--r--libusb/os/linux_usbfs.c2
-rw-r--r--libusb/os/windows_usb.c2
-rw-r--r--libusb/version_nano.h2
5 files changed, 6 insertions, 13 deletions
diff --git a/libusb/core.c b/libusb/core.c
index c8932c3..95c80b9 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -751,13 +751,6 @@ uint8_t API_EXPORTED libusb_get_port_number(libusb_device *dev)
int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t* path, uint8_t path_len)
{
int i = path_len;
- ssize_t r;
- struct libusb_device **devs = NULL;
-
- /* The device needs to be open, else the parents may have been destroyed */
- r = libusb_get_device_list(ctx, &devs);
- if (r < 0)
- return (int)r;
while(dev) {
// HCDs can be listed as devices and would have port #0
@@ -766,13 +759,11 @@ int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev, u
break;
i--;
if (i < 0) {
- libusb_free_device_list(devs, 1);
return LIBUSB_ERROR_OVERFLOW;
}
path[i] = dev->port_number;
dev = dev->parent_dev;
}
- libusb_free_device_list(devs, 1);
memmove(path, &path[i], path_len-i);
return path_len-i;
}
@@ -969,6 +960,8 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev)
if (refcnt == 0) {
usbi_dbg("destroy device %d.%d", dev->bus_number, dev->device_address);
+ libusb_unref_device(dev->parent_dev);
+
if (usbi_backend->destroy_device)
usbi_backend->destroy_device(dev);
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
index 07d8c5a..74e34cf 100644
--- a/libusb/os/darwin_usb.c
+++ b/libusb/os/darwin_usb.c
@@ -767,7 +767,7 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device
if (ret < 0)
break;
- dev->parent_dev = usbi_get_device_by_session_id (ctx, parent_location);
+ dev->parent_dev = libusb_ref_device (usbi_get_device_by_session_id (ctx, parent_location));
dev->port_number = port;
dev->bus_number = locationID >> 24;
dev->device_address = address;
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index cdafb7b..de4d741 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -1137,7 +1137,7 @@ retry:
list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) {
struct linux_device_priv *priv = _device_priv(it);
if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) {
- dev->parent_dev = it;
+ dev->parent_dev = libusb_ref_device(it);
break;
}
}
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 9c0888a..b07d193 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -1110,7 +1110,7 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
dev->port_number = port_number;
priv->depth = parent_priv->depth + 1;
priv->parent_dev = parent_dev;
- dev->parent_dev = parent_dev;
+ dev->parent_dev = libusb_ref_device(parent_dev);
// If the device address is already set, we can stop here
if (dev->device_address != 0) {
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index b586028..3940d93 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10690
+#define LIBUSB_NANO 10691