Re: [PATCH] usb: gadget: dummy_hcd: prevent unbind via sysfs

Alan Stern <[email protected]> Wed, 29 Jul 2026 09:54:50 -0400
Newsgroups dev.linux.lists.syzbot,org.kernel.vger.linux-kernel,org.kernel.vger.linux-usb
Message-ID <[email protected]>
On Wed, Jul 29, 2026 at 12:25:27PM +0000, syzbot wrote:
> From: Aleksandr Nogikh <[email protected]>
> 
> The dummy_hcd (Host Controller) and dummy_udc (Device Controller) are
> implemented as two separate platform drivers that share the same underlying
> state (struct dummy). They are designed to be created and destroyed
> together during the module's init and exit phases.
> 
> If userspace forces the dummy_hcd driver to unbind from the device via
> sysfs, dummy_hcd_remove() cleans up the host controllers and sets the
> pointers to NULL (dum->hs_hcd = NULL). However, the dummy_udc driver is
> still bound to its device, meaning the USB gadget is still registered with
> the udc-core subsystem.
> 
> If a new gadget driver is subsequently registered, it binds to the
> still-registered dummy_udc gadget, invoking the dummy_udc_start() callback.
> This callback attempts to retrieve the HCD state using
> gadget_to_dummy_hcd(), which returns NULL because of the unbind. This
> results in a null-pointer dereference:
> 
> Oops: general protection fault, probably for non-canonical address
> 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI
> KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
> ...
> RIP: 0010:dummy_udc_start+0xd0/0x1f0
> drivers/usb/gadget/udc/dummy_hcd.c:1022
> ...
> Call Trace:
>  <TASK>
>  usb_gadget_udc_start_locked drivers/usb/gadget/udc/core.c:1237 [inline]
>  gadget_bind_driver+0x3a8/0x9e0 drivers/usb/gadget/udc/core.c:1667
>  call_driver_probe drivers/base/dd.c:-1 [inline]
>  really_probe+0x254/0xae0 drivers/base/dd.c:706
>  __driver_probe_device+0x1e8/0x360 drivers/base/dd.c:868
>  driver_probe_device+0x4f/0x240 drivers/base/dd.c:898
>  __driver_attach+0x339/0x600 drivers/base/dd.c:1292
>  bus_for_each_dev+0x23b/0x2c0 drivers/base/bus.c:383
>  bus_add_driver+0x345/0x670 drivers/base/bus.c:763
>  driver_register+0x23a/0x320 drivers/base/driver.c:174
>  usb_gadget_register_driver_owner+0xf9/0x270
>  drivers/usb/gadget/udc/core.c:1752
>  raw_ioctl_run drivers/usb/gadget/legacy/raw_gadget.c:596 [inline]
>  raw_ioctl+0x1541/0x41c0 drivers/usb/gadget/legacy/raw_gadget.c:1307
> 
> Adding NULL checks to the UDC callbacks is not a robust solution because
> there is no synchronization between dummy_hcd_remove() and the UDC
> callbacks, which would result in a use-after-free race condition if the HCD
> were unbound concurrently.
> 
> Fix this by setting .suppress_bind_attrs = true in both driver definitions.
> This prevents userspace from unbinding these drivers dynamically, ensuring
> their lifecycles remain strictly synchronized with the module's load/unload
> process.
> 
> Fixes: d9b762510c18 ("[PATCH] USB dummy_hcd: Use separate pdevs for HC and UDC")
> Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
> Reported-by: [email protected]
> Closes: https://syzkaller.appspot.com/bug?extid=d270af829aca04e783fc
> Link: https://syzkaller.appspot.com/ai_job?id=7a763ada-c07c-458f-9fea-f7e913dc1f2f
> Signed-off-by: Aleksandr Nogikh <[email protected]>
> 
> ---

In theory the driver could be rewritten to allow independent unbinding 
and rebinding of the HCD and UDC.  But that would be a much more 
intrusive change, whereas as this is a small and reasonable fix for a 
real problem.

Acked-by: Alan Stern <[email protected]>

Alan Stern

> diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
> index c0e40fa6d..415096835 100644
> --- a/drivers/usb/gadget/udc/dummy_hcd.c
> +++ b/drivers/usb/gadget/udc/dummy_hcd.c
> @@ -1180,6 +1180,7 @@ static struct platform_driver dummy_udc_driver = {
>  	.resume		= dummy_udc_resume,
>  	.driver		= {
>  		.name	= gadget_name,
> +		.suppress_bind_attrs = true,
>  	},
>  };
>  
> @@ -2802,6 +2803,7 @@ static struct platform_driver dummy_hcd_driver = {
>  	.resume		= dummy_hcd_resume,
>  	.driver		= {
>  		.name	= driver_name,
> +		.suppress_bind_attrs = true,
>  	},
>  };
>  
> 
> 
> base-commit: f5098b6bae761e346ebcd9da7f95622c04733cff
> -- 
> See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
> You can comment on the patch as usual, syzbot will try to address
> the comments and send a new version of the patch if necessary.
> syzbot engineers can be reached at [email protected].