Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp5153236pxb; Sun, 7 Nov 2021 06:17:51 -0800 (PST) X-Google-Smtp-Source: ABdhPJzp/U+xqOz5qBf+PCZwBrNYYyMuuuXPKSat03Vw8Y1VjKmP6POTuwfWo0HuDHwu+ExYomaM X-Received: by 2002:a05:6e02:18c5:: with SMTP id s5mr17241560ilu.193.1636294671152; Sun, 07 Nov 2021 06:17:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1636294671; cv=none; d=google.com; s=arc-20160816; b=JpW85K6eP+OZmqr4ud/ok9wc72zM9gHib5Y5cUthFP6TMjg5Gax1oE58Oz6WfYmKlb phodPHx5mEB1d5vjjJweLQUWAsNIqHo/jhseMGu+/epGk0I//EHF4SXo9Q8g78q+yWRK Zql0gbVUafPsULPQr2XQ1UZ4nwZfdJ6v4GHpunEWkQqZ7UYACt4gz3WvmfBqB+Cd+VXu TaFBIZ6qcgeBZZgW2LWNk/yArT/dtOSS/FUf/xymobpntsJYiNb4y34J/0RyCO9X52Uv KmzeCjYFyxW6ZLE5N+J3WqQonhtmtHLpz0sCyH4MRh877JuYUfh2KyiTf9CcJY0re1he BYgA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=h1memygO2sKLZ0JgC4x0uWmnrzMnm3jgaZ3h6WrbN5I=; b=jBQmziz5/hj7fzCnAOm0J5pSflE+2pRt+ABqDl2L1Z2nZwtD7eYaWXiwCoel70SkHt SBiu1n8iSRw7o6r1xOuKqP409u2ki7/VOOcWdm1jcpY7hCjV0+y+L2DXNoMBnJCWLmKZ W78VrQRKqG0aOnW6lAfuHGg1TmX0EgYrZ33OfvRrFqC6QgEia6z8W9j5oIA9tKFB80IV 826tpCOuJwS8Tw0yRzDnqyQh/ZVqdBMGG00yw48ME89UyRQ1tm6A12JD8gcApjGcrj/+ l7sUfwX/as4FGR400tg3Wieog9PmnXHpBDEUJ8tKHTbmSrUAXeFJ5iv7AyhSV6sC1aLo 8YZg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id y6si27540922ilu.49.2021.11.07.06.17.38; Sun, 07 Nov 2021 06:17:51 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234739AbhKGFLJ (ORCPT + 99 others); Sun, 7 Nov 2021 01:11:09 -0400 Received: from smtp10.smtpout.orange.fr ([80.12.242.132]:63587 "EHLO smtp.smtpout.orange.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231261AbhKGFLI (ORCPT ); Sun, 7 Nov 2021 01:11:08 -0400 Received: from localhost.localdomain ([114.149.34.46]) by smtp.orange.fr with ESMTPA id jaPOmihyw3ptZjaPmm9Zak; Sun, 07 Nov 2021 06:08:25 +0100 X-ME-Helo: localhost.localdomain X-ME-Auth: MDU0YmViZGZmMDIzYiBlMiM2NTczNTRjNWZkZTMwOGRiOGQ4ODf3NWI1ZTMyMzdiODlhOQ== X-ME-Date: Sun, 07 Nov 2021 06:08:25 +0100 X-ME-IP: 114.149.34.46 From: Vincent Mailhol To: Marc Kleine-Budde , linux-can@vger.kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Vincent Mailhol , Matt Kline Subject: [PATCH v2] can: m_can: m_can_read_fifo: fix memory leak in error branch Date: Sun, 7 Nov 2021 14:07:55 +0900 Message-Id: <20211107050755.70655-1-mailhol.vincent@wanadoo.fr> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In m_can_read_fifo(), if the second call to m_can_fifo_read() fails, the function jump to the out_fail label and returns without calling m_can_receive_skb(). This means that the skb previously allocated by alloc_can_skb() is not freed. In other terms, this is a memory leak. This patch adds a goto label to destroy the skb if an error occurs. Issue was found with GCC -fanalyzer, please follow the link below for details. Fixes: e39381770ec9 ("can: m_can: Disable IRQs on FIFO bus errors") CC: Matt Kline Signed-off-by: Vincent Mailhol --- * Appendix: how the issue was found * This issue was found using GCC's static analysis tool: -fanalyzer: https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html The step to reproduce are: 1. Install GCC 11. 2. Hack the kernel's Makefile to add the -fanalyzer flag (we leave it as an exercise for the reader to figure out the details of how to do so). 3. Decorate the function alloc_can_skb() with __attribute__((__malloc__ (dealloc, netif_rx))). This step helps the static analyzer to figure out the constructor/destructor pairs (not something it can deduce by himself). 4. Compile. The compiler then throws below warning: | drivers/net/can/m_can/m_can.c: In function 'm_can_read_fifo': | drivers/net/can/m_can/m_can.c:537:9: warning: leak of 'skb' [CWE-401] [-Wanalyzer-malloc-leak] | 537 | return err; | | ^~~~~~ | 'm_can_rx_handler': events 1-6 | | | | 899 | static int m_can_rx_handler(struct net_device *dev, int quota) | | | ^~~~~~~~~~~~~~~~ | | | | | | | (1) entry to 'm_can_rx_handler' | |...... | | 907 | if (!irqstatus) | | | ~ | | | | | | | (2) following 'false' branch (when 'irqstatus != 0')... | |...... | | 920 | if (cdev->version <= 31 && irqstatus & IR_MRAF && | | | ~~ | | | | | | | (3) ...to here | |...... | | 939 | if (irqstatus & IR_RF0N) { | | | ~ | | | | | | | (4) following 'true' branch... | | 940 | rx_work_or_err = m_can_do_rx_poll(dev, (quota - work_done)); | | | ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | | | | | (6) calling 'm_can_do_rx_poll' from 'm_can_rx_handler' | | | (5) ...to here | | | +--> 'm_can_do_rx_poll': events 7-8 | | | | 540 | static int m_can_do_rx_poll(struct net_device *dev, int quota) | | | ^~~~~~~~~~~~~~~~ | | | | | | | (7) entry to 'm_can_do_rx_poll' | |...... | | 548 | if (!(rxfs & RXFS_FFL_MASK)) { | | | ~ | | | | | | | (8) following 'false' branch... | | | 'm_can_do_rx_poll': event 9 | | | |cc1: | | (9): ...to here | | | 'm_can_do_rx_poll': events 10-12 | | | | 553 | while ((rxfs & RXFS_FFL_MASK) && (quota > 0)) { | | | ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~ | | | | | | | (10) following 'true' branch... | | 554 | err = m_can_read_fifo(dev, rxfs); | | | ~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | | | | | (12) calling 'm_can_read_fifo' from 'm_can_do_rx_poll' | | | (11) ...to here | | | +--> 'm_can_read_fifo': events 13-24 | | | | 470 | static int m_can_read_fifo(struct net_device *dev, u32 rxfs) | | | ^~~~~~~~~~~~~~~ | | | | | | | (13) entry to 'm_can_read_fifo' | |...... | | 484 | if (err) | | | ~ | | | | | | | (14) following 'false' branch... | |...... | | 487 | if (fifo_header.dlc & RX_BUF_FDF) | | | ~~ ~ | | | | | | | | | (16) following 'true' branch... | | | (15) ...to here | | 488 | skb = alloc_canfd_skb(dev, &cf); | | | ~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | | | | | (18) allocated here | | | (17) ...to here | |...... | | 491 | if (!skb) { | | | ~ | | | | | | | (19) assuming 'skb' is non-NULL | | | (20) following 'false' branch (when 'skb' is non-NULL)... | |...... | | 496 | if (fifo_header.dlc & RX_BUF_FDF) | | | ~~ | | | | | | | (21) ...to here | |...... | | 519 | if (err) | | | ~ | | | | | | | (22) following 'true' branch... | | 520 | goto out_fail; | | | ~~~~ | | | | | | | (23) ...to here | |...... | | 537 | return err; | | | ~~~~~~ | | | | | | | (24) 'skb' leaks here; was allocated at (18) | | --- drivers/net/can/m_can/m_can.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 2470c47b2e31..f4f54012dea7 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -517,7 +517,7 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs) err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DATA, cf->data, DIV_ROUND_UP(cf->len, 4)); if (err) - goto out_fail; + goto out_free_skb; } /* acknowledge rx fifo 0 */ @@ -532,6 +532,8 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs) return 0; +out_free_skb: + kfree_skb(skb); out_fail: netdev_err(dev, "FIFO read returned %d\n", err); return err; -- 2.32.0