git: fc3e8434a61f - main - libusb: Fix NULL dereference when a hotplug callback deregisters itself

From: ShengYi Hung <aokblast_at_FreeBSD.org>
Date: Mon, 24 Aug 2026 01:30:02 UTC
The branch main has been updated by aokblast:

URL: https://cgit.FreeBSD.org/src/commit/?id=fc3e8434a61f372b4d6ec6bd8910ac8cd54b9b37

commit fc3e8434a61f372b4d6ec6bd8910ac8cd54b9b37
Author:     yuvrajnode <yuvrajsinghrock1221@gmail.com>
AuthorDate: 2026-08-23 07:15:49 +0000
Commit:     ShengYi Hung <aokblast@FreeBSD.org>
CommitDate: 2026-08-24 01:29:52 +0000

    libusb: Fix NULL dereference when a hotplug callback deregisters itself
    
    libusb_hotplug_register_callback() runs the newly registered callback
    over the already-enumerated device list when LIBUSB_HOTPLUG_ENUMERATE
    is set.  A hotplug callback returning non-zero means "deregister me",
    and the enumerate loop honours that by freeing the handle and setting
    it to NULL.
    
    Since commit 6bda9f26d2ed changed libusb_hotplug_callback_handle from a
    pointer to an int, the tail of the function unconditionally dereferences
    that handle, so any caller that passes LIBUSB_HOTPLUG_ENUMERATE, a
    non-NULL handle pointer, and a callback that returns non-zero on a
    matching device crashes inside libusb.  This is a normal usage pattern
    and it was safe before the conversion, when the equivalent line simply
    stored NULL.
    
    Report the reserved id 0 instead.  The allocator hands out ids starting
    at 1, and libusb_hotplug_deregister_callback() already ignores 0, so
    this restores the pre-conversion behaviour.
    
    Signed-off-by: yuvrajnode <yuvrajsinghrock1221@gmail.com>
    Reviewed by:    aokblast
    Fixes:  6bda9f26d2ed ("libusb: change callback register handler to int")
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/2383
    Closes:         https://github.com/freebsd/freebsd-src/pull/2383
---
 lib/libusb/libusb10_hotplug.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/lib/libusb/libusb10_hotplug.c b/lib/libusb/libusb10_hotplug.c
index 5def972c5ab5..cf8eeafabc52 100644
--- a/lib/libusb/libusb10_hotplug.c
+++ b/lib/libusb/libusb10_hotplug.c
@@ -408,8 +408,15 @@ int libusb_hotplug_register_callback(libusb_context *ctx,
 		TAILQ_INSERT_TAIL(&ctx->hotplug_cbh, handle, entry);
 	HOTPLUG_UNLOCK(ctx);
 
+	/*
+	 * The callback may have deregistered itself during the
+	 * LIBUSB_HOTPLUG_ENUMERATE pass above, in which case handle is
+	 * already freed.  Report the reserved id 0, which is never handed
+	 * out by the allocator above and which
+	 * libusb_hotplug_deregister_callback() treats as a no-op.
+	 */
 	if (phandle != NULL)
-		*phandle = handle->id;
+		*phandle = (handle != NULL) ? handle->id : 0;
 	return (LIBUSB_SUCCESS);
 }