Re: [PATCH] usb: gadget: f_uvc: fix NULL pointer dereference during unbind race

From: Alan Stern

Date: Tue Feb 24 2026 - 10:47:19 EST


On Tue, Feb 24, 2026 at 04:39:55PM +0800, Jimmy Hu wrote:
> Commit b81ac4395bbe ("usb: gadget: uvc: allow for application to cleanly
> shutdown") introduced two stages of synchronization waits totaling 1500ms
> in uvc_function_unbind() to prevent several types of kernel panics.
> However, this timing-based approach is insufficient during power
> management (PM) transitions.
>
> When the PM subsystem starts freezing user space processes, the
> wait_event_interruptible_timeout() is aborted early, which allows the
> unbind thread to proceed and nullify the gadget pointer
> (cdev->gadget = NULL):
>
> [ 814.123447][ T947] configfs-gadget.g1 gadget.0: uvc: uvc_function_unbind()
> [ 814.178583][ T3173] PM: suspend entry (deep)
> [ 814.192487][ T3173] Freezing user space processes
> [ 814.197668][ T947] configfs-gadget.g1 gadget.0: uvc: uvc_function_unbind no clean disconnect, wait for release
>
> When the PM subsystem resumes or aborts the suspend and tasks are
> restarted, the V4L2 release path is executed and attempts to access the
> already nullified gadget pointer, triggering a kernel panic:
>
> [ 814.292597][ C0] PM: pm_system_irq_wakeup: 479 triggered dhdpcie_host_wake
> [ 814.386727][ T3173] Restarting tasks ...
> [ 814.403522][ T4558] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000030
> [ 814.404021][ T4558] pc : usb_gadget_deactivate+0x14/0xf4
> [ 814.404031][ T4558] lr : usb_function_deactivate+0x54/0x94
> [ 814.404078][ T4558] Call trace:
> [ 814.404080][ T4558] usb_gadget_deactivate+0x14/0xf4
> [ 814.404083][ T4558] usb_function_deactivate+0x54/0x94
> [ 814.404087][ T4558] uvc_function_disconnect+0x1c/0x5c
> [ 814.404092][ T4558] uvc_v4l2_release+0x44/0xac
> [ 814.404095][ T4558] v4l2_release+0xcc/0x130
>
> The fix introduces a 'func_unbinding' flag in struct uvc_device to protect
> critical sections:
> 1. In uvc_function_disconnect(), it prevents accessing the nullified
> cdev->gadget pointer.
> 2. In uvc_v4l2_release(), it ensures uvcg_free_buffers() is skipped
> if unbind is already in progress, avoiding races with concurrent
> bind operations or use-after-free on the video queue memory.

Sorry if the answer to this question is obvious to anybody familiar with
the driver...

The patch adds a flag that can be accessed by two different tasks
(disconnect and release). Is there any synchronization to prevent these
tasks from racing and accessing the new flag concurrently?

Alan Stern