diff options
author | Chao Bi <chao.bi@intel.com> | 2014-04-13 23:19:53 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2014-04-16 11:11:47 -0400 |
commit | 97839ca4b06ab27790700ad7da6be9a75fc0cc1d (patch) | |
tree | 1aad06a0dfb7fd602f3f276bbce68013186ee3e3 | |
parent | 9dc9cb0c9ad0f999e29ce4c4f307cd2abbe752d3 (diff) |
usb: gadget: ffs: race between ffs_epfile_io() and ffs_func_eps_disable()
ffs_epfile_io() is called from userspace, while ffs_func_eps_disable() might be
called from USB disconnect interrupt, the two functions would run in parallel
but they are not well protected, that epfile->ep would be removed by
ffs_func_eps_disable() during ffs_epfile_io() is referring this pointer, then
it leads to kernel PANIC.
The scenario is as below:
Thread 1 Thread 2
| |
SyS_read dwc3_gadget_disconnect_interrupt
| |
ffs_epfile_read reset_config
| |
ffs_epfile_io ffs_func_eps_disable
| |
----- usb_ep_disable(): epfile->ep->ep->desc = NULL
| |
usb_ep_align_maybe(): -----
it refers ep->desc->wMaxPacketSize -----
Signed-off-by: Chao Bi <chao.bi@intel.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r-- | drivers/usb/gadget/f_fs.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2e164dca08e8..1e12b3ee56fd 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c | |||
@@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
745 | */ | 745 | */ |
746 | struct usb_gadget *gadget = epfile->ffs->gadget; | 746 | struct usb_gadget *gadget = epfile->ffs->gadget; |
747 | 747 | ||
748 | spin_lock_irq(&epfile->ffs->eps_lock); | ||
749 | /* In the meantime, endpoint got disabled or changed. */ | ||
750 | if (epfile->ep != ep) { | ||
751 | spin_unlock_irq(&epfile->ffs->eps_lock); | ||
752 | return -ESHUTDOWN; | ||
753 | } | ||
748 | /* | 754 | /* |
749 | * Controller may require buffer size to be aligned to | 755 | * Controller may require buffer size to be aligned to |
750 | * maxpacketsize of an out endpoint. | 756 | * maxpacketsize of an out endpoint. |
@@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
752 | data_len = io_data->read ? | 758 | data_len = io_data->read ? |
753 | usb_ep_align_maybe(gadget, ep->ep, io_data->len) : | 759 | usb_ep_align_maybe(gadget, ep->ep, io_data->len) : |
754 | io_data->len; | 760 | io_data->len; |
761 | spin_unlock_irq(&epfile->ffs->eps_lock); | ||
755 | 762 | ||
756 | data = kmalloc(data_len, GFP_KERNEL); | 763 | data = kmalloc(data_len, GFP_KERNEL); |
757 | if (unlikely(!data)) | 764 | if (unlikely(!data)) |