git: 1c2263b68397 - main - libusb: Validate arguments before dereferencing the hotplug context

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

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

commit 1c2263b683977ebab3d9a6448268ad810ceeec70
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: Validate arguments before dereferencing the hotplug context
    
    libusb_hotplug_register_callback() resolves its context with
    GET_CONTEXT() and then immediately reads ctx->no_discovery and
    ctx->usb_event_mode, but only checks "ctx == NULL" afterwards.
    
    GET_CONTEXT() falls back to usbi_default_context, which is NULL before
    libusb_init() and is reset to NULL by libusb_exit().  An application
    that calls libusb_hotplug_register_callback(NULL, ...) without an
    initialised default context therefore crashes on the ctx->no_discovery
    read, instead of getting the LIBUSB_ERROR_INVALID_PARAM the existing
    guard was clearly written to return.
    
    Move the argument validation ahead of the first dereference.  None of
    the validated arguments depend on the context, so no other ordering
    constraint is affected.
    
    Signed-off-by: yuvrajnode <yuvrajsinghrock1221@gmail.com>
    Reviewed by:    aokblast
    MFC after:      2 weeks
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/2384
    Closes:         https://github.com/freebsd/freebsd-src/pull/2384
---
 lib/libusb/libusb10_hotplug.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/lib/libusb/libusb10_hotplug.c b/lib/libusb/libusb10_hotplug.c
index cf8eeafabc52..f03c1b48b8dc 100644
--- a/lib/libusb/libusb10_hotplug.c
+++ b/lib/libusb/libusb10_hotplug.c
@@ -348,6 +348,12 @@ int libusb_hotplug_register_callback(libusb_context *ctx,
 
 	ctx = GET_CONTEXT(ctx);
 
+	if (ctx == NULL || cb_fn == NULL || events == 0 ||
+	    vendor_id < -1 || vendor_id > 0xffff ||
+	    product_id < -1 || product_id > 0xffff ||
+	    dev_class < -1 || dev_class > 0xff)
+		return (LIBUSB_ERROR_INVALID_PARAM);
+
 	if (ctx->no_discovery)
 		return (LIBUSB_SUCCESS);
 
@@ -358,12 +364,6 @@ int libusb_hotplug_register_callback(libusb_context *ctx,
 		HOTPLUG_UNLOCK(ctx);
 	}
 
-	if (ctx == NULL || cb_fn == NULL || events == 0 ||
-	    vendor_id < -1 || vendor_id > 0xffff ||
-	    product_id < -1 || product_id > 0xffff ||
-	    dev_class < -1 || dev_class > 0xff)
-		return (LIBUSB_ERROR_INVALID_PARAM);
-
 	handle = malloc(sizeof(*handle));
 	if (handle == NULL)
 		return (LIBUSB_ERROR_NO_MEM);