Skip to contentSkip to conversation

Patch "usb: renesas_usbhs: fix NULL pointer dereference in xfer_work()" has been added to the 4.7-stable tree

PATCH [email protected] 1 participant 1 message Aug 17, 2016

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

usb: renesas_usbhs: fix NULL pointer dereference in xfer_work()

to the 4.7-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
usb-renesas_usbhs-fix-null-pointer-dereference-in-xfer_work.patch
and it can be found in the queue-4.7 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 4fdef698383db07d829da567e0e405fc41ff3a89 Mon Sep 17 00:00:00 2001

From: Yoshihiro Shimoda <[email protected]>
Date: Wed, 8 Jun 2016 16:32:49 +0900
Subject: usb: renesas_usbhs: fix NULL pointer dereference in xfer_work()

From: Yoshihiro Shimoda <[email protected]>

commit 4fdef698383db07d829da567e0e405fc41ff3a89 upstream.

This patch fixes an issue that the xfer_work() is possible to cause NULL pointer dereference if the usb cable is disconnected while data transfer is running.

In such case, a gadget driver may call usb_ep_disable()) before xfer_work() is actually called. In this case, the usbhs_pkt_pop() will call usbhsf_fifo_unselect(), and then usbhs_pipe_to_fifo() in xfer_work() will return NULL.

Fixes e73a989 ("usb: renesas_usbhs: add DMAEngine support")
---
 drivers/usb/renesas_usbhs/fifo.c |   18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)
drivers/usb/renesas_usbhs/fifo.c +14 -4
@@ -810,20 +810,27 @@ static void xfer_work(struct work_struct
 {
 	struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
 	struct usbhs_pipe *pipe = pkt->pipe;
-	struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
+	struct usbhs_fifo *fifo;
 	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
 	struct dma_async_tx_descriptor *desc;
-	struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt);
+	struct dma_chan *chan;
 	struct device *dev = usbhs_priv_to_dev(priv);
 	enum dma_transfer_direction dir;
+	unsigned long flags;
 
+	usbhs_lock(priv, flags);
+	fifo = usbhs_pipe_to_fifo(pipe);
+	if (!fifo)
+		goto xfer_work_end;
+
+	chan = usbhsf_dma_chan_get(fifo, pkt);
 	dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
 
 	desc = dmaengine_prep_slave_single(chan, pkt->dma + pkt->actual,
 					pkt->trans, dir,
 					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc)
-		return;
+		goto xfer_work_end;
 
 	desc->callback		= usbhsf_dma_complete;
 	desc->callback_param	= pipe;
@@ -831,7 +838,7 @@ static void xfer_work(struct work_struct
 	pkt->cookie = dmaengine_submit(desc);
 	if (pkt->cookie < 0) {
 		dev_err(dev, "Failed to submit dma descriptor\n");
-		return;
+		goto xfer_work_end;
 	}
 
 	dev_dbg(dev, "  %s %d (%d/ %d)\n",
@@ -842,6 +849,9 @@ static void xfer_work(struct work_struct
 	usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
 	dma_async_issue_pending(chan);
 	usbhs_pipe_enable(pipe);
+
+xfer_work_end:
+	usbhs_unlock(priv, flags);
 }
 
 /*

Patches currently in stable-queue which might be from [email protected] are

queue-4.7/usb-renesas_usbhs-protect-the-cfifosel-setting-in-usbhsg_ep_enable.patch queue-4.7/usb-renesas_usbhs-fix-null-pointer-dereference-in-xfer_work.patch