mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
usb: gadget: f_fs: Fix Use-After-Free in AIO error path
In ffs_epfile_write_iter() and ffs_epfile_read_iter(), when ffs_epfile_io()
fails with an error other than -EIOCBQUEUED, the io_data 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 sys_io_cancel()) executes after
ffs_epfile_io() 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->ki_complete()` does exactly this by
acquiring `ctx->ctx_lock` and safely removing the kiocb from the active
sequence. In doing so, it ensures that a parallel io_cancel 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.
Fixes: de2080d41b ("gadget/function/f_fs.c: close leaks")
Cc: stable@vger.kernel.org
Reported-by: Xingyu Jin <xingyuj@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Neill Kapron <nkapron@google.com>
Link: https://patch.msgid.link/20260724235100.106011-1-nkapron@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
569dd7e5dc
commit
e78dcb1f7e
|
|
@ -1296,8 +1296,10 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
|
|||
if (res == -EIOCBQUEUED)
|
||||
return res;
|
||||
if (p->aio) {
|
||||
kiocb->ki_complete(kiocb, res);
|
||||
mmdrop(p->mm);
|
||||
kfree(p);
|
||||
return -EIOCBQUEUED;
|
||||
} else {
|
||||
*from = p->data;
|
||||
}
|
||||
|
|
@ -1345,9 +1347,11 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
|
|||
return res;
|
||||
|
||||
if (p->aio) {
|
||||
kiocb->ki_complete(kiocb, res);
|
||||
mmdrop(p->mm);
|
||||
kfree(p->to_free);
|
||||
kfree(p);
|
||||
return -EIOCBQUEUED;
|
||||
} else {
|
||||
*to = p->data;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user