Commit fc9823ed authored by Krishna Kurapati's avatar Krishna Kurapati Committed by Treehugger Robot
Browse files

ANDROID: usb: gadget: configfs: Protect composite_setup in a spinlock



In one of the SMMU faults (NULL Pointer derefernce) the following
race condition was observed and func->interfaces_nums was being
accessed for f_fs interface after it was unbinded resulting in a
crash.

Thread-1                             Thread-2

ffs_func_req_match+0x68/0xc8
				drain_workqueue+0xac
				gsi_unbind[usb_f_gsi]+0x64
				purge_configs_funcs+0xb4
				configfs_composite_unbind+0xac
				usb_gadget_remove_driver+0xac
				usb_gadget_unregister_driver+0xd8
				gadget_dev_desc_UDC_store+0x114

android_setup+0x164/0x2a8
dwc3_ep0_inspect_setup+0x100/0x440
dwc3_ep0_interrupt+0xac/0x300
dwc3_process_event_entry+0x80/0x724
dwc3_process_event_buf+0x80/0x434
dwc3_thread_interrupt+0x60/0x124
irq_thread_fn+0x54/0xe4
irq_thread+0x3a4/0x6ec
kthread+0x188/0x1ec
ret_from_fork+0x10/0x20

The events happened in order are as follows:

We got a setup packet for ffs interface and was passed to android
setup callback from ep0.c. As part of the delegate request, the
dwc->lock is released.

At this instant a composition switch occurred and as per traces
and crash dumps:

1. UDC Stop was done successfully. So run stop is set to '0'
2. Composite disconnect was done and ep disable for all ep's is done
   gadget->connected = FALSE

3. Async callbacks disabled
   dwc->aysnc_callbacks = FALSE

4. composite unbind is going on and the ffs interface in question is
unbinded
udc->driver != NULL
(as per crash dump indicating that unbind is in progress)

5. Purge configs was ongoing because as per crash dumps:
otg_desc[0] = NULL;
cdev->os_desc_req->buf is not NULL

(configfs_composite_unbind is going on, but composite_dev_cleanup
not yet done)

As per the traces:

23.794712:  dwc3_event   event=49216  ep0state=1  str=
23.794909:  dwc3_ctrl_req   bRequestType=161  bRequest=1  wValue=0
wIndex=2  wLength=4096

23.799740:  usb_gadget_disconnect   speed=5  max_speed=6  state=7
mA=0 deactivated=0  connected=0  ret=0

This indicated that android setup came first followed by composite
disconnect. Since the dwc->lock was released by delegate_request,
soft disconnect gets unblocked and runs parallel to composite setup.

After this, there is no check in path of composite setup
indicating unbind happened and bail out is necessary instead of
executing any function ops.

Protect composite_setup (as part of android_setup) in a spinlock
to block composite_disconnect/unbind running in parallel.

Moreover, in the configfs counterpart of android_setup (configfs_
composite_stetup), the composite_setup call is done with spinlock
held.

It is only the android_setup missing this lock.

Bug: 280548269
Fixes: 7a160e2b ("ANDROID: usb: gadget: configfs: Add Uevent to notify userspace")
Change-Id: Id245e9f72801541689fcb185ba0459824bfb3904
Signed-off-by: default avatarKrishna Kurapati <quic_kriskura@quicinc.com>
(cherry picked from commit 9ad803f2)
parent df4ee615
Loading
Loading
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment