patch "usb: gadget: f_fs: change ep->status safe in ffs_epfile_io()" added to usb-linus
Subsystems (2)
This is a note to let you know that I've just added the patch titled
usb: gadget: f_fs: change ep->status safe in ffs_epfile_io()
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From fb1f16d74e263baa4ad11e31e28b68f144aa55ed Mon Sep 17 00:00:00 2001
From: Linyu Yuan <[email protected]>
Date: Fri, 10 Jun 2022 20:17:57 +0800
Subject: usb: gadget: f_fs: change ep->status safe in ffs_epfile_io()
If a task read/write data in blocking mode, it will wait the completion in ffs_epfile_io(), if function unbind occurs, ffs_func_unbind() will kfree ffs ep, once the task wake up, it still dereference the ffs ep to obtain the request status.
Fix it by moving the request status to io_data which is stack-safe.
--- drivers/usb/gadget/function/f_fs.c | 34 +++++++++++++++++------------- 1 file changed, 19 insertions(+), 15 deletions(-)
drivers/usb/gadget/function/f_fs.c +19 -15
@@ -122,8 +122,6 @@ struct ffs_ep {struct usb_endpoint_descriptor *descs[3 ];u8 num; - -int status;/* P: epfile->mutex */ };struct ffs_epfile {
@@ -227,6 +225,9 @@ struct ffs_io_data {bool use_sg;struct ffs_data *ffs; + +int status; +struct completion done; };struct ffs_desc_helper {
@@ -707,12 +708,15 @@ static const struct file_operations ffs_ep0_operations = {static void ffs_epfile_io_complete (struct usb_ep *_ep,struct usb_request *req) { +struct ffs_io_data *io_data = req->context; +ENTER (); -if (req->context) { -struct ffs_ep *ep = _ep->driver_data; - ep->status = req->status ? req->status : req->actual; -complete (req->context); - } +if (req->status) + io_data->status = req->status; +else + io_data->status = req->actual; + +complete (&io_data->done); }static ssize_t ffs_copy_to_iter (void *data,int data_len,struct iov_iter *iter)
@@ -1050,7 +1054,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)WARN (1 ,"%s: data_len == -EINVAL\n" , __func__); ret = -EINVAL ; }else if (!io_data->aio) { -DECLARE_COMPLETION_ONSTACK (done);bool interrupted = false; req = ep->req;
@@ -1066,7 +1069,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) io_data->buf = data; - req->context = &done; +init_completion (&io_data->done); + req->context = io_data; req->complete = ffs_epfile_io_complete; ret =usb_ep_queue (ep->ep, req,GFP_ATOMIC );
@@ -1075,7 +1079,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)spin_unlock_irq (&epfile->ffs->eps_lock); -if (wait_for_completion_interruptible (&done)) { +if (wait_for_completion_interruptible (&io_data->done)) {/* * To avoid race condition with ffs_epfile_io_complete, * dequeue the request first then check
@@ -1083,17 +1087,17 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)* condition with req->complete callback. */ usb_ep_dequeue (ep->ep, req); -wait_for_completion (&done); - interrupted = ep->status <0 ; +wait_for_completion (&io_data->done); + interrupted = io_data->status <0 ; }if (interrupted) ret = -EINTR ; -else if (io_data->read && ep->status >0 ) - ret =__ffs_epfile_read_data (epfile, data, ep->status, +else if (io_data->read && io_data->status >0 ) + ret =__ffs_epfile_read_data (epfile, data, io_data->status, &io_data->data);else - ret = ep->status; + ret = io_data->status; goto error_mutex; }else if (!(req =usb_ep_alloc_request (ep->ep,GFP_ATOMIC ))) { ret = -ENOMEM ;
Signature · 1 line
2.36.1