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); }
