summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2016-06-06 17:43:23 +0200
committerNathan Hjelm <hjelmn@me.com>2016-08-17 12:52:40 -0600
commitce59e6ea12852f25025fef5ef42da9e271049a59 (patch)
tree1bc1df42be82856d2a6d7e5ebb752a092f9db841
parentefcfe05a2a572b67a5fbacdc855ac678b2ce8380 (diff)
downloadlibusb-ce59e6ea12852f25025fef5ef42da9e271049a59.tar.gz
core: Fix unlocked access to timeout_flags
There is a race between handle_timeout() and the completion functions. When one thread is in handle_timeout() and another thread wakes up from a poll(), there exists a window where the transfer has been cancelled, but USBI_TRANSFER_TIMED_OUT is not yet set in timeout_flags. Therefore, usbi_handle_transfer_completion() is sometimes called with LIBUSB_TRANSFER_CANCELLED instead of the expected LIBUSB_TRANSFER_TIMED_OUT. timeout_flags is protected by the flying_transfers_lock, this commit makes usbi_handle_transfer_cancellation() take that lock before checking for USBI_TRANSFER_TIMED_OUT in timeout_flags, fixing this. Reported-by: Joost Muller <joostmuller@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--libusb/io.c9
-rw-r--r--libusb/version_nano.h2
2 files changed, 9 insertions, 2 deletions
diff --git a/libusb/io.c b/libusb/io.c
index aa6cfca..b3f7df0 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1684,8 +1684,15 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
* will attempt to take the lock. */
int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer)
{
+ struct libusb_context *ctx = ITRANSFER_CTX(transfer);
+ uint8_t timed_out;
+
+ usbi_mutex_lock(&ctx->flying_transfers_lock);
+ timed_out = transfer->timeout_flags & USBI_TRANSFER_TIMED_OUT;
+ usbi_mutex_unlock(&ctx->flying_transfers_lock);
+
/* if the URB was cancelled due to timeout, report timeout to the user */
- if (transfer->timeout_flags & USBI_TRANSFER_TIMED_OUT) {
+ if (timed_out) {
usbi_dbg("detected timeout cancellation");
return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT);
}
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 6995b33..bb7624f 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11135
+#define LIBUSB_NANO 11137