Re: [PATCH] usb: gadget: fix refcount underflow in gadgetfs_bind() error path
From: Alan Stern
Date: Tue Aug 11 2026 - 10:26:38 EST
On Tue, Aug 11, 2026 at 02:08:10PM +0800, Nguyen Quang Le Kien wrote:
> gadgetfs_bind() calls get_dev() only on the success path, but
> gadgetfs_unbind() called from the enomem error label unconditionally
> calls put_dev(). When bind fails (e.g. ENOMEM), put_dev() fires
> without a matching get_dev(), leaving the refcount unbalanced.
>
> A subsequent close of the ep0 file descriptor calls dev_release() ->
> put_dev() which hits zero and frees the object; then gadgetfs_kill_sb()
> calls put_dev(the_device) again on the already-freed pointer, triggering
> a refcount underflow and use-after-free.
>
> Fix by calling get_dev() at the start of gadgetfs_bind(), before any
> error path that invokes gadgetfs_unbind(), so the reference is always
> balanced regardless of whether bind succeeds or fails.
>
> Reported-by: syzbot+8496ab5e117502750445@xxxxxxxxxxxxxxxxxxxxxxxxx
> Closes: https://syzkaller.appspot.com/bug?extid=8496ab5e117502750445
> Signed-off-by: Nguyen Quang Le Kien <khiemtranzo532001@xxxxxxxxx>
> ---
Reviewed-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
> drivers/usb/gadget/legacy/inode.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
> index d87a8ab51..d6551a4ce 100644
> --- a/drivers/usb/gadget/legacy/inode.c
> +++ b/drivers/usb/gadget/legacy/inode.c
> @@ -1682,6 +1682,8 @@ static int gadgetfs_bind(struct usb_gadget *gadget,
> dev->gadget = gadget;
> gadget->ep0->driver_data = dev;
>
> + get_dev (dev);
> +
> /* preallocate control response and buffer */
> dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
> if (!dev->req)
> @@ -1696,7 +1698,6 @@ static int gadgetfs_bind(struct usb_gadget *gadget,
> spin_lock_irq(&dev->lock);
> dev->state = STATE_DEV_UNCONNECTED;
> spin_unlock_irq(&dev->lock);
> - get_dev (dev);
> return 0;
>
> enomem:
> --
> 2.34.1
>
>