The branch main has been updated by aokblast:

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

commit fc3e8434a61f372b4d6ec6bd8910ac8cd54b9b37
Author:     yuvrajnode <[email protected]>
AuthorDate: 2026-08-23 07:15:49 +0000
Commit:     ShengYi Hung <[email protected]>
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 <[email protected]>
    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);
 }
 

Reply via email to