Re: [BUG] usb: gadgetfs: KASAN null-ptr-deref and intermittent UAF in ep_aio_cancel()
From: Alan Stern
Date: Thu Sep 10 2026 - 12:05:59 EST
On Thu, Sep 10, 2026 at 11:00:00PM +0900, Minseo Kim wrote:
> Hi Alan,
>
> Thank you for the second patch.
>
> > In your earlier testing, didn't you find that with the unpatched driver,
> > the driver module's usage count remained elevated as long as the
> > ep_user_copy_worker() was pending on the workqueue? And therefore it
> > was impossible to unload the module while a work item was still queued
> > or running?
>
> To check that point directly, I tested the unpatched upstream copy-work
> path using diagnostic gates at two points in ep_user_copy_worker(). The
> module usage count remained elevated when I held the worker at entry,
> before iocb->ki_complete(). When I held the worker after that call, the
> usage count reached zero and the module was unloaded before the worker
> finished; the kernel then warned and panicked. This suggests that
> AIO may not retain the file reference throughout the worker tail after
> ki_complete().
Okay, it's good to know that.
> > Could you test it and verify that it prevents the problem you observed
> > with only the first patch installed?
>
> Yes. I applied your first patch and then your second patch to upstream
> v7.2-rc1, commit dc59e4fea9d83f03bad6bddf3fa2e52491777482.
>
> With the first patch alone, I reproduced the earlier module-unload
> failure with ep_unlink_worker() held at entry. With both patches applied
> using the same reproducer and ep_unlink_worker() entry gate,
> gadgetfs_unbind() reached the flush point and the ep0 close remained
> blocked, while unmount and rmmod attempts were rejected. After I released
> the worker, the close completed and subsequent unmount and rmmod attempts
> succeeded. Holding ep_user_copy_worker() at entry with both patches
> applied produced the same result.
>
> I also tested the boundary where gadgetfs_unbind() reached the flush
> point before the completion callback queued copy_work.
I didn't think this was possible. gadgetfs_unbind() calls
destroy_ep_files() before doing the flush, and destroy_ep_files() calls
usb_ep_disable() for each active endpoint. usb_ep_disable() doesn't
return until the completion handlers for all the outstanding requests on
the endpoint have finished. This means no copy_work items should have
been left to queue when the flush occurred.
> After the
> callback queued the work, I held the worker tail immediately after
> iocb->ki_complete(). In this ordering, rmmod did not complete while the
> worker was held; after I released the worker, rmmod completed cleanly.
What prevented rmmod from completing after iocb->ki_complete() had
finished? Was it waiting for the flush to finish? If any additional
work items were added to the queue after the flush started, they should
not have blocked the flush.
> I reran the exact pre-queue cancellation matrix, the original
> null-ptr-deref reproducer, the directed cross-CPU UAF reproducer,
> deferred giveback, forced dequeue failure, the earlier NULL-endpoint
> case, payload checks, and CPU hotplug. With both patches applied, all
> produced the expected results without a KASAN report, Oops, or LOCKDEP
> warning. Strict KCSAN did not report a race involving GadgetFS or its AIO
> work functions.
>
> In my x86-64 QEMU and dummy_hcd tests, the second patch prevented the
> module-unload problem that remained with the first patch alone. I did not
> find a new failure attributable to the second patch in these tests.
All right. So once these last few questions have been resolved, I will
submit both of the patches (with your Tested-by: added to the second as
well as the first).
Thanks again for all your hard work running multiple tests.
Alan Stern