History

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.

Linyu Yuan committed 4 years ago

Commit fb1f16d1 parent 802dcaf1 file · +19 −15Browse files

Unified · Split

drivers/usb/gadget/function/f_fs.c+19−15
@@ -122,8 +122,6 @@ struct ffs_ep { · 121 unmodified lines
122122 struct usb_endpoint_descriptor *descs[3];
123123
124124 u8 num;
125−
126− int status; /* P: epfile->mutex */
127125 };
128126
129127 struct ffs_epfile {
@@ -227,6 +225,9 @@ struct ffs_io_data { · 97 unmodified lines
227225 bool use_sg;
228226
229227 struct ffs_data *ffs;
228+
229+ int status;
230+ struct completion done;
230231 };
231232
232233 struct ffs_desc_helper {
@@ -707,12 +708,15 @@ static const struct file_operations ffs_ep0_operations = { · 474 unmodified lines
707708
708709 static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
709710 {
711+ struct ffs_io_data *io_data = req->context;
712+
710713 ENTER();
711− if (req->context) {
712− struct ffs_ep *ep = _ep->driver_data;
713− ep->status = req->status ? req->status : req->actual;
714− complete(req->context);
715− }
714+ if (req->status)
715+ io_data->status = req->status;
716+ else
717+ io_data->status = req->actual;
718+
719+ complete(&io_data->done);
716720 }
717721
718722 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) · 331 unmodified lines
10501054 WARN(1, "%s: data_len == -EINVAL\n", __func__);
10511055 ret = -EINVAL;
10521056 } else if (!io_data->aio) {
1053− DECLARE_COMPLETION_ONSTACK(done);
10541057 bool interrupted = false;
10551058
10561059 req = ep->req;
@@ -1066,7 +1069,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) · 9 unmodified lines
10661069
10671070 io_data->buf = data;
10681071
1069− req->context = &done;
1072+ init_completion(&io_data->done);
1073+ req->context = io_data;
10701074 req->complete = ffs_epfile_io_complete;
10711075
10721076 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) · 2 unmodified lines
10751079
10761080 spin_unlock_irq(&epfile->ffs->eps_lock);
10771081
1078− if (wait_for_completion_interruptible(&done)) {
1082+ if (wait_for_completion_interruptible(&io_data->done)) {
10791083 /*
10801084 * To avoid race condition with ffs_epfile_io_complete,
10811085 * 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) · 1 unmodified line
10831087 * condition with req->complete callback.
10841088 */
10851089 usb_ep_dequeue(ep->ep, req);
1086− wait_for_completion(&done);
1087− interrupted = ep->status < 0;
1090+ wait_for_completion(&io_data->done);
1091+ interrupted = io_data->status < 0;
10881092 }
10891093
10901094 if (interrupted)
10911095 ret = -EINTR;
1092− else if (io_data->read && ep->status > 0)
1093− ret = __ffs_epfile_read_data(epfile, data, ep->status,
1096+ else if (io_data->read && io_data->status > 0)
1097+ ret = __ffs_epfile_read_data(epfile, data, io_data->status,
10941098 &io_data->data);
10951099 else
1096− ret = ep->status;
1100+ ret = io_data->status;
10971101 goto error_mutex;
10981102 } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) {
10991103 ret = -ENOMEM;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t