On 20-07-16 13:55:25, Marek Szyprowski wrote: > When binding an UDC driver to the pending gadget fails in > check_pending_gadget_drivers(), the usb_add_gadget_udc_release() function > ends without waiting for the usb_gadget_state_work to finish, what in > turn might cause the whole struct usb_gadget being freed by the caller > before the usb_gadget_state_work being executed. > > This can be observed on some boards with USB Mass Storage gadget > compiled-in and kernel booted without the needed module parameters: > > dwc2 12480000.hsotg: dwc2_check_params: Invalid parameter besl=1 > dwc2 12480000.hsotg: dwc2_check_params: Invalid parameter g_np_tx_fifo_size=1024 > dwc2 12480000.hsotg: EPs: 16, dedicated fifos, 7808 entries in SPRAM > Mass Storage Function, version: 2009/09/11 > LUN: removable file: (no medium) > no file given for LUN0 > g_mass_storage 12480000.hsotg: failed to start g_mass_storage: -22 > dwc2: probe of 12480000.hsotg failed with error -22 > 8<--- cut here --- > Unable to handle kernel NULL pointer dereference at virtual address 00000004 > pgd = (ptrval) > [00000004] *pgd=00000000 > Internal error: Oops: 5 [#1] PREEMPT SMP ARM > Modules linked in: > CPU: 1 PID: 88 Comm: kworker/1:2 Not tainted 5.8.0-rc5-next-20200715-00062-gc5bb489ae825-dirty #8792 > Hardware name: Samsung Exynos (Flattened Device Tree) > Workqueue: 0x0 (rcu_gp) > PC is at process_one_work+0x44/0x7dc > ... > Process kworker/1:2 (pid: 88, stack limit = 0x(ptrval)) > Stack: (0xed9f1f00 to 0xed9f2000) > ... > [<c0148590>] (process_one_work) from [<c0148d6c>] (worker_thread+0x44/0x51c) > [<c0148d6c>] (worker_thread) from [<c01500c0>] (kthread+0x158/0x1a0) > [<c01500c0>] (kthread) from [<c0100114>] (ret_from_fork+0x14/0x20) > Exception stack(0xed9f1fb0 to 0xed9f1ff8) > ... > ---[ end trace 5033c1326a62e5f3 ]--- > note: kworker/1:2[88] exited with preempt_count 1 > > Fix this by flushing pending work in error path. > > Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> > --- > drivers/usb/gadget/udc/core.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c > index c33ad8a333ad..4f82bcd31fd3 100644 > --- a/drivers/usb/gadget/udc/core.c > +++ b/drivers/usb/gadget/udc/core.c > @@ -1230,6 +1230,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, > return 0; > > err_del_udc: > + flush_work(&gadget->work); > device_del(&udc->dev); > > err_unlist_udc: > -- > 2.17.1 > Reviewed-by: Peter Chen <peter.chen@xxxxxxx> -- Thanks, Peter Chen