All of lore.kernel.org
 help / color / mirror / Atom feed
* [RE-RESEND PATCH 1/4] usb: musb: Fix runtime PM race in musb_queue_resume_work
@ 2021-01-23 14:24 Paul Cercueil
  2021-01-23 14:25 ` [RE-RESEND PATCH 2/4] usb: musb: Fix NULL check on struct musb_request field Paul Cercueil
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Paul Cercueil @ 2021-01-23 14:24 UTC (permalink / raw)
  To: Bin Liu, Greg Kroah-Hartman
  Cc: Tony Lindgren, od, linux-mips, linux-usb, linux-kernel,
	Paul Cercueil, stable

musb_queue_resume_work() would call the provided callback if the runtime
PM status was 'active'. Otherwise, it would enqueue the request if the
hardware was still suspended (musb->is_runtime_suspended is true).

This causes a race with the runtime PM handlers, as it is possible to be
in the case where the runtime PM status is not yet 'active', but the
hardware has been awaken (PM resume function has been called).

When hitting the race, the resume work was not enqueued, which probably
triggered other bugs further down the stack. For instance, a telnet
connection on Ingenic SoCs would result in a 50/50 chance of a
segmentation fault somewhere in the musb code.

Rework the code so that either we call the callback directly if
(musb->is_runtime_suspended == 0), or enqueue the query otherwise.

Fixes: ea2f35c01d5e ("usb: musb: Fix sleeping function called from invalid context for hdrc glue")
Cc: stable@vger.kernel.org # v4.9+
Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Reviewed-by: Tony Lindgren <tony@atomide.com>
Tested-by: Tony Lindgren <tony@atomide.com>
---
 drivers/usb/musb/musb_core.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 849e0b770130..1cd87729ba60 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2240,32 +2240,35 @@ int musb_queue_resume_work(struct musb *musb,
 {
 	struct musb_pending_work *w;
 	unsigned long flags;
+	bool is_suspended;
 	int error;
 
 	if (WARN_ON(!callback))
 		return -EINVAL;
 
-	if (pm_runtime_active(musb->controller))
-		return callback(musb, data);
+	spin_lock_irqsave(&musb->list_lock, flags);
+	is_suspended = musb->is_runtime_suspended;
+
+	if (is_suspended) {
+		w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC);
+		if (!w) {
+			error = -ENOMEM;
+			goto out_unlock;
+		}
 
-	w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC);
-	if (!w)
-		return -ENOMEM;
+		w->callback = callback;
+		w->data = data;
 
-	w->callback = callback;
-	w->data = data;
-	spin_lock_irqsave(&musb->list_lock, flags);
-	if (musb->is_runtime_suspended) {
 		list_add_tail(&w->node, &musb->pending_list);
 		error = 0;
-	} else {
-		dev_err(musb->controller, "could not add resume work %p\n",
-			callback);
-		devm_kfree(musb->controller, w);
-		error = -EINPROGRESS;
 	}
+
+out_unlock:
 	spin_unlock_irqrestore(&musb->list_lock, flags);
 
+	if (!is_suspended)
+		error = callback(musb, data);
+
 	return error;
 }
 EXPORT_SYMBOL_GPL(musb_queue_resume_work);
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-01-24  9:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-23 14:24 [RE-RESEND PATCH 1/4] usb: musb: Fix runtime PM race in musb_queue_resume_work Paul Cercueil
2021-01-23 14:25 ` [RE-RESEND PATCH 2/4] usb: musb: Fix NULL check on struct musb_request field Paul Cercueil
2021-01-23 14:25 ` [RE-RESEND PATCH 3/4] usb: musb: dma: Remove unused variable Paul Cercueil
2021-01-23 14:25 ` [RE-RESEND PATCH 4/4] usb: musb: jz4740: Add missing CR to error strings Paul Cercueil
2021-01-23 16:41 ` [RE-RESEND PATCH 1/4] usb: musb: Fix runtime PM race in musb_queue_resume_work Sergei Shtylyov
2021-01-24  8:38   ` Paul Cercueil

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.