summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlbert Wang <albertccwang@google.com>2022-05-18 14:13:15 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-05-19 18:15:03 +0200
commit3c5880745b4439ac64eccdb040e37fc1cc4c5406 (patch)
tree24b0ef1bdf16df383cf13d0639a601b193524200 /drivers
parent6c5ba7395b1badce5e0b8e597907751e952646cb (diff)
downloadlinux-3c5880745b4439ac64eccdb040e37fc1cc4c5406.tar.bz2
usb: dwc3: gadget: Move null pinter check to proper place
When dwc3_gadget_ep_cleanup_completed_requests() called to dwc3_gadget_giveback() where the dwc3 lock is released, other thread is able to execute. In this situation, usb_ep_disable() gets the chance to clear endpoint descriptor pointer which leds to the null pointer dereference problem. So needs to move the null pointer check to a proper place. Example call stack: Thread#1: dwc3_thread_interrupt() spin_lock -> dwc3_process_event_buf() -> dwc3_process_event_entry() -> dwc3_endpoint_interrupt() -> dwc3_gadget_endpoint_trbs_complete() -> dwc3_gadget_ep_cleanup_completed_requests() ... -> dwc3_giveback() spin_unlock Thread#2 executes Thread#2: configfs_composite_disconnect() -> __composite_disconnect() -> ffs_func_disable() -> ffs_func_set_alt() -> ffs_func_eps_disable() -> usb_ep_disable() wait for dwc3 spin_lock Thread#1 released lock clear endpoint.desc Fixes: 26288448120b ("usb: dwc3: gadget: Fix null pointer exception") Cc: stable <stable@kernel.org> Signed-off-by: Albert Wang <albertccwang@google.com> Link: https://lore.kernel.org/r/20220518061315.3359198-1-albertccwang@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/dwc3/gadget.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 8c366fa82105..00427d108ab9 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -3384,14 +3384,14 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep,
struct dwc3 *dwc = dep->dwc;
bool no_started_trb = true;
- if (!dep->endpoint.desc)
- return no_started_trb;
-
dwc3_gadget_ep_cleanup_completed_requests(dep, event, status);
if (dep->flags & DWC3_EP_END_TRANSFER_PENDING)
goto out;
+ if (!dep->endpoint.desc)
+ return no_started_trb;
+
if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
list_empty(&dep->started_list) &&
(list_empty(&dep->pending_list) || status == -EXDEV))