Re: [BUG] usb: gadgetfs: KASAN null-ptr-deref and intermittent UAF in ep_aio_cancel()

From: Alan Stern

Date: Fri Sep 18 2026 - 10:39:30 EST


On Fri, Sep 18, 2026 at 10:30:00PM +0900, Minseo Kim wrote:
> Hi Alan,
>
> > I wonder which part of the code was holding udc_usage above 0?
>
> It was the udc_usage increment in ep_aio() during request submission.
> The increment occurs before dev->lock is released to call
> kiocb_set_cancel_fn() and usb_ep_queue(), and the corresponding decrement
> occurs after usb_ep_queue() returns:
>
> ++epdata->dev->udc_usage;
> spin_unlock_irq(&epdata->dev->lock);
>
> kiocb_set_cancel_fn(iocb, ep_aio_cancel);
> value = usb_ep_queue(ep, req, GFP_KERNEL);
>
> spin_lock_irq(&epdata->dev->lock);
> --epdata->dev->udc_usage;
>
> In the matched control, a request with a length of 64 bytes took the
> direct giveback path, where dummy_queue() calls
> usb_gadget_giveback_request() before returning to usb_ep_queue().
> usb_gadget_giveback_request() synchronously invokes the request's
> completion callback, which was ep_aio_complete() in this test. Because I
> held ep_aio_complete() at the diagnostic gate immediately after
> iocb->ki_complete() returned, the nested giveback call could not return.
> Consequently, neither dummy_queue() nor usb_ep_queue() had returned, and
> ep_aio() had not reached the decrement. gadgetfs_unbind() therefore saw
> udc_usage at 1 and waited.

Of course. Now I get it.

> In the normal transfer test, by contrast, usb_ep_queue() returned and
> ep_aio() decremented udc_usage before the later completion callback ran.
> I confirmed this ordering in three runs without enabling a callback
> gate.
>
> I verified the sequence for direct giveback with markers after the
> increment, after usb_ep_queue() returned but before the decrement, after
> the decrement, and immediately before and after the unbind wait. In each
> of three runs, markers with the same dev pointer showed ep_aio()
> incrementing udc_usage to 1 and gadgetfs_unbind() entering the udc_usage
> wait with the count still at 1. After I released the diagnostic gate,
> usb_ep_queue() returned, ep_aio() decremented the count to 0, and
> gadgetfs_unbind() left the wait.
>
> > I will submit the patches, with your Signed-off-by:
> > added to this one also, if that's okay with you.
>
> Yes, that is okay with me. Please add it as:
>
> Minseo Kim <neck3922@xxxxxxxxx>

I will, and I will CC: you on the submissions.

Alan Stern