All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marc Kleine-Budde <mkl@pengutronix.de>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, kuba@kernel.org, linux-can@vger.kernel.org,
	kernel@pengutronix.de, Rhett Aultman <rhett.aultman@samsara.com>,
	stable@vger.kernel.org, Marc Kleine-Budde <mkl@pengutronix.de>
Subject: [PATCH net 04/15] can: gs_usb: gs_usb_open/close(): fix memory leak
Date: Mon,  4 Jul 2022 14:26:02 +0200	[thread overview]
Message-ID: <20220704122613.1551119-5-mkl@pengutronix.de> (raw)
In-Reply-To: <20220704122613.1551119-1-mkl@pengutronix.de>

From: Rhett Aultman <rhett.aultman@samsara.com>

The gs_usb driver appears to suffer from a malady common to many USB
CAN adapter drivers in that it performs usb_alloc_coherent() to
allocate a number of USB request blocks (URBs) for RX, and then later
relies on usb_kill_anchored_urbs() to free them, but this doesn't
actually free them. As a result, this may be leaking DMA memory that's
been used by the driver.

This commit is an adaptation of the techniques found in the esd_usb2
driver where a similar design pattern led to a memory leak. It
explicitly frees the RX URBs and their DMA memory via a call to
usb_free_coherent(). Since the RX URBs were allocated in the
gs_can_open(), we remove them in gs_can_close() rather than in the
disconnect function as was done in esd_usb2.

For more information, see the 928150fad41b ("can: esd_usb2: fix memory
leak").

Link: https://lore.kernel.org/all/alpine.DEB.2.22.394.2206031547001.1630869@thelappy
Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
Cc: stable@vger.kernel.org
Signed-off-by: Rhett Aultman <rhett.aultman@samsara.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/usb/gs_usb.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index b29ba9138866..d3a658b444b5 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -268,6 +268,8 @@ struct gs_can {
 
 	struct usb_anchor tx_submitted;
 	atomic_t active_tx_urbs;
+	void *rxbuf[GS_MAX_RX_URBS];
+	dma_addr_t rxbuf_dma[GS_MAX_RX_URBS];
 };
 
 /* usb interface struct */
@@ -742,6 +744,7 @@ static int gs_can_open(struct net_device *netdev)
 		for (i = 0; i < GS_MAX_RX_URBS; i++) {
 			struct urb *urb;
 			u8 *buf;
+			dma_addr_t buf_dma;
 
 			/* alloc rx urb */
 			urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -752,7 +755,7 @@ static int gs_can_open(struct net_device *netdev)
 			buf = usb_alloc_coherent(dev->udev,
 						 dev->parent->hf_size_rx,
 						 GFP_KERNEL,
-						 &urb->transfer_dma);
+						 &buf_dma);
 			if (!buf) {
 				netdev_err(netdev,
 					   "No memory left for USB buffer\n");
@@ -760,6 +763,8 @@ static int gs_can_open(struct net_device *netdev)
 				return -ENOMEM;
 			}
 
+			urb->transfer_dma = buf_dma;
+
 			/* fill, anchor, and submit rx urb */
 			usb_fill_bulk_urb(urb,
 					  dev->udev,
@@ -781,10 +786,17 @@ static int gs_can_open(struct net_device *netdev)
 					   "usb_submit failed (err=%d)\n", rc);
 
 				usb_unanchor_urb(urb);
+				usb_free_coherent(dev->udev,
+						  sizeof(struct gs_host_frame),
+						  buf,
+						  buf_dma);
 				usb_free_urb(urb);
 				break;
 			}
 
+			dev->rxbuf[i] = buf;
+			dev->rxbuf_dma[i] = buf_dma;
+
 			/* Drop reference,
 			 * USB core will take care of freeing it
 			 */
@@ -842,13 +854,20 @@ static int gs_can_close(struct net_device *netdev)
 	int rc;
 	struct gs_can *dev = netdev_priv(netdev);
 	struct gs_usb *parent = dev->parent;
+	unsigned int i;
 
 	netif_stop_queue(netdev);
 
 	/* Stop polling */
 	parent->active_channels--;
-	if (!parent->active_channels)
+	if (!parent->active_channels) {
 		usb_kill_anchored_urbs(&parent->rx_submitted);
+		for (i = 0; i < GS_MAX_RX_URBS; i++)
+			usb_free_coherent(dev->udev,
+					  sizeof(struct gs_host_frame),
+					  dev->rxbuf[i],
+					  dev->rxbuf_dma[i]);
+	}
 
 	/* Stop sending URBs */
 	usb_kill_anchored_urbs(&dev->tx_submitted);
-- 
2.35.1



  parent reply	other threads:[~2022-07-04 12:52 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-04 12:25 [PATCH net 0/15] pull-request: can 2022-07-04 Marc Kleine-Budde
2022-07-04 12:25 ` [PATCH net 01/15] can: bcm: use call_rcu() instead of costly synchronize_rcu() Marc Kleine-Budde
2022-07-05  3:30   ` patchwork-bot+netdevbpf
2022-07-04 12:26 ` [PATCH net 02/15] Revert "can: xilinx_can: Limit CANFD brp to 2" Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 03/15] can: rcar_canfd: Fix data transmission failed on R-Car V3U Marc Kleine-Budde
2022-07-04 12:26 ` Marc Kleine-Budde [this message]
2022-07-04 12:26 ` [PATCH net 05/15] can: grcan: grcan_probe(): remove extra of_node_get() Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 06/15] can: m_can: m_can_chip_config(): actually enable internal timestamping Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 07/15] can: m_can: m_can_{read_fifo,echo_tx_event}(): shift timestamp to full 32 bits Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 08/15] can: kvaser_usb: replace run-time checks with struct kvaser_usb_driver_info Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 09/15] can: kvaser_usb: kvaser_usb_leaf: fix CAN clock frequency regression Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 10/15] can: kvaser_usb: kvaser_usb_leaf: fix bittiming limits Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 11/15] can: mcp251xfd: mcp251xfd_regmap_crc_read(): improve workaround handling for mcp2517fd Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 12/15] can: mcp251xfd: mcp251xfd_regmap_crc_read(): update workaround broken CRC on TBC register Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 13/15] can: mcp251xfd: mcp251xfd_stop(): add missing hrtimer_cancel() Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 14/15] can: mcp251xfd: mcp251xfd_register_get_dev_id(): use correct length to read dev_id Marc Kleine-Budde
2022-07-04 12:26 ` [PATCH net 15/15] can: mcp251xfd: mcp251xfd_register_get_dev_id(): fix endianness conversion Marc Kleine-Budde

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220704122613.1551119-5-mkl@pengutronix.de \
    --to=mkl@pengutronix.de \
    --cc=davem@davemloft.net \
    --cc=kernel@pengutronix.de \
    --cc=kuba@kernel.org \
    --cc=linux-can@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=rhett.aultman@samsara.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.