CVE-2026-90044: usb: gadget: f_fs: Fix Use-After-Free in AIO error path
In the Linux kernel, the following vulnerability has been resolved:
usb: gadget: ffs: Fix Use-After-Free in AIO error path
In ffsepfilewriteiter() and ffsepfilereaditer(), when ffsepfileio() fails with an error other than -EIOCBQUEUED, the iodata structure (p) is freed. However, for AIO operations, the kiocb cancel function was already armed and kiocb->private was set to p.
If a concurrent cancel operation (such as sysiocancel()) executes after ffsepfileio() fails but before the function frees p, a Use-After-Free can occur when the cancellation handler accesses the freed pointer.
To securely fix this race condition, we must properly un-arm the cancellation. Invoking kiocb->kicomplete() does exactly this by acquiring ctx->ctxlock and safely removing the kiocb from the active sequence. In doing so, it ensures that a parallel iocancel can no longer discover the kiocb, effectively closing the race window.
We then return -EIOCBQUEUED to notify the VFS layer that the kiocb has been consumed and it should avoid attempting to complete the request again or triggering subsequent completion handlers.
Event History
Frequently Asked Questions
What conditions are required to trigger the race?
The affected code path requires an asynchronous I/O operation through the FunctionFS endpoint-file read or write handlers to fail with an error other than -EIOCBQUEUED. A concurrent cancellation operation, such as sys_io_cancel(), must then run in the window after cancellation has been armed but while the failed operation's io_data is being freed.
What component is affected?
The issue is in the Linux kernel USB gadget FunctionFS implementation, specifically the AIO error paths in ffs_epfile_write_iter() and ffs_epfile_read_iter().
How does the fix prevent use-after-free?
The fix invokes kiocb->ki_complete() before releasing the I/O data in the affected error path. This acquires the AIO context lock and removes the kiocb from the active sequence, preventing a parallel cancellation from finding and dereferencing the stale private pointer.