FAILED: patch "[PATCH] usb: gadget: f_fs: Fix Use-After-Free in AIO error path" failed to apply to 7.2-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 7.2-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-7.2.y
git checkout FETCH_HEAD
git cherry-pick -x e78dcb1f7ec271449c54984dc90c62a5ba272de7
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090331-linoleum-freeware-d223@gregkh' --subject-prefix 'PATCH 7.2.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e78dcb1f7ec271449c54984dc90c62a5ba272de7 Mon Sep 17 00:00:00 2001
From: Neill Kapron <[email protected]>
Date: Fri, 24 Jul 2026 23:51:00 +0000
Subject: [PATCH] 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.
drivers/usb/gadget/function/f_fs.c +4 -0
@@ -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; }
Sasha Levin
maintainerPATCH 1/2 USB: gadget: ffs: fix mm lifetime handling
From: Gabriel Prostitis <[email protected]>
[ Upstream commit 5eb5c72c72fef76cb765ef1669b62b6a3ba1bfc8 ]
io_data stores a pointer to the submitting task's mm_struct, but does not currently hold a reference to it while async requests are pending.
This can result in a use-after-free if the task exits before completion handling finishes.
Take a reference with mmgrab() when queuing the read request and release it with mmdrop() on request completion.
Stable-dep-of: e78dcb1f7ec2 ("usb: gadget: f_fs: Fix Use-After-Free in AIO error path")
--- drivers/usb/gadget/function/f_fs.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-)
drivers/usb/gadget/function/f_fs.c +20 -7
@@ -867,9 +867,15 @@ static void ffs_user_copy_worker(struct work_struct *work)bool kiocb_has_eventfd = io_data->kiocb->ki_flags &IOCB_EVENTFD ;if (io_data->read && ret >0 ) { -kthread_use_mm (io_data->mm); - ret =ffs_copy_to_iter (io_data->buf, ret, &io_data->data); -kthread_unuse_mm (io_data->mm); +if (mmget_not_zero (io_data->mm)) { +kthread_use_mm (io_data->mm); + ret =ffs_copy_to_iter (io_data->buf, ret, &io_data->data); +kthread_unuse_mm (io_data->mm); +mmput (io_data->mm); + }else { + ret = -EFAULT ; + } +mmdrop (io_data->mm); } io_data->kiocb->ki_complete (io_data->kiocb, ret);
@@ -1264,16 +1270,20 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) kiocb->private = p; -if (p->aio) +if (p->aio) { +mmgrab (p->mm);kiocb_set_cancel_fn (kiocb, ffs_aio_cancel); + } res =ffs_epfile_io (kiocb->ki_filp, p);if (res == -EIOCBQUEUED )return res; -if (p->aio) +if (p->aio) { +mmdrop (p->mm);kfree (p); -else + }else { *from = p->data; + }return res; }
@@ -1308,14 +1318,17 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) kiocb->private = p; -if (p->aio) +if (p->aio) { +mmgrab (p->mm);kiocb_set_cancel_fn (kiocb, ffs_aio_cancel); + } res =ffs_epfile_io (kiocb->ki_filp, p);if (res == -EIOCBQUEUED )return res;if (p->aio) { +mmdrop (p->mm);kfree (p->to_free);kfree (p); }else {
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 usb: gadget: f_fs: Fix Use-After-Free in AIO error path
From: Neill Kapron <[email protected]>
[ Upstream commit e78dcb1f7ec271449c54984dc90c62a5ba272de7 ]
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.
--- drivers/usb/gadget/function/f_fs.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/gadget/function/f_fs.c +4 -0
@@ -1279,8 +1279,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; }
@@ -1328,9 +1330,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; }
Signature · 1 line
2.53.0