diff options
author | Winter Wang <wente.wang@nxp.com> | 2016-07-27 10:03:19 +0800 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2016-08-11 15:09:44 +0300 |
commit | cee51c33f52ebf673a088a428ac0fecc33ab77fa (patch) | |
tree | 00c1469a09a303a6e18b7d8e29181a40513f6f7d /drivers/usb/gadget | |
parent | 88c09eacf560c3303d0ee8cf91b8b7ff7f000350 (diff) |
usb: gadget: configfs: add mutex lock before unregister gadget
There may be a race condition if f_fs calls unregister_gadget_item in
ffs_closed() when unregister_gadget is called by UDC store at the same time.
this leads to a kernel NULL pointer dereference:
[ 310.644928] Unable to handle kernel NULL pointer dereference at virtual address 00000004
[ 310.645053] init: Service 'adbd' is being killed...
[ 310.658938] pgd = c9528000
[ 310.662515] [00000004] *pgd=19451831, *pte=00000000, *ppte=00000000
[ 310.669702] Internal error: Oops: 817 [#1] PREEMPT SMP ARM
[ 310.675211] Modules linked in:
[ 310.678294] CPU: 0 PID: 1537 Comm: ->transport Not tainted 4.1.15-03725-g793404c #2
[ 310.685958] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[ 310.692493] task: c8e24200 ti: c945e000 task.ti: c945e000
[ 310.697911] PC is at usb_gadget_unregister_driver+0xb4/0xd0
[ 310.703502] LR is at __mutex_lock_slowpath+0x10c/0x16c
[ 310.708648] pc : [<c075efc0>] lr : [<c0bfb0bc>] psr: 600f0113
<snip..>
[ 311.565585] [<c075efc0>] (usb_gadget_unregister_driver) from [<c075e2b8>] (unregister_gadget_item+0x1c/0x34)
[ 311.575426] [<c075e2b8>] (unregister_gadget_item) from [<c076fcc8>] (ffs_closed+0x8c/0x9c)
[ 311.583702] [<c076fcc8>] (ffs_closed) from [<c07736b8>] (ffs_data_reset+0xc/0xa0)
[ 311.591194] [<c07736b8>] (ffs_data_reset) from [<c07738ac>] (ffs_data_closed+0x90/0xd0)
[ 311.599208] [<c07738ac>] (ffs_data_closed) from [<c07738f8>] (ffs_ep0_release+0xc/0x14)
[ 311.607224] [<c07738f8>] (ffs_ep0_release) from [<c023e030>] (__fput+0x80/0x1d0)
[ 311.614635] [<c023e030>] (__fput) from [<c014e688>] (task_work_run+0xb0/0xe8)
[ 311.621788] [<c014e688>] (task_work_run) from [<c010afdc>] (do_work_pending+0x7c/0xa4)
[ 311.629718] [<c010afdc>] (do_work_pending) from [<c010770c>] (work_pending+0xc/0x20)
for functions using functionFS, i.e. android adbd will close /dev/usb-ffs/adb/ep0
when usb IO thread fails, but switch adb from on to off also triggers write
"none" > UDC. These 2 operations both call unregister_gadget, which will lead
to the panic above.
add a mutex before calling unregister_gadget for api used in f_fs.
Signed-off-by: Winter Wang <wente.wang@nxp.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/configfs.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 70cf3477f951..f9237fe2be05 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1490,7 +1490,9 @@ void unregister_gadget_item(struct config_item *item) { struct gadget_info *gi = to_gadget_info(item); + mutex_lock(&gi->lock); unregister_gadget(gi); + mutex_unlock(&gi->lock); } EXPORT_SYMBOL_GPL(unregister_gadget_item); |