Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 4 Jul 2023 14:00:10 GMT
From:      Marcin Wojtas <mw@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: b9e80b5280b7 - main - ena: Initialize statistics before the interface is available
Message-ID:  <202307041400.364E0AGM071474@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by mw:

URL: https://cgit.FreeBSD.org/src/commit/?id=b9e80b5280b75f2c641d680245df44b8ff26a7b0

commit b9e80b5280b75f2c641d680245df44b8ff26a7b0
Author:     Osama Abboud <osamaabb@amazon.com>
AuthorDate: 2023-01-18 13:19:07 +0000
Commit:     Marcin Wojtas <mw@FreeBSD.org>
CommitDate: 2023-07-04 13:51:16 +0000

    ena: Initialize statistics before the interface is available
    
    In [1], the FBSD community exposed a bug in the fbsd/ena driver.
    
    Bug description:
    ----------------
    Current function call order is as follows:
    
    1. ena_attach()
    1.1. ena_setup_ifnet()
    1.1.1. Registration of ena_get_counter()
    1.1.2. ether_ifattach(ifp, adapter->mac_addr);
    1.2. Statistics allocation and initialization.
    
    At point 1.1.2, when ether_ifattach() returns, the interface is available,
    and stats can be read before they are allocated, leading to kernel panic.
    
    Also fixed a potential memory leak by freeing the stats since they were
    not freed in case the following calls failed.
    
    Fix:
    ----
    This commit moves the statistics allocation and initialization to happen
    before ena_setup_ifnet()
    
    [1] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=268934
    
    Fixes: 9b8d05b8ac78 ("Add support for Amazon Elastic Network Adapter (ENA) NIC")
    Fixes: 30217e2dff10 ("Rework counting of hardware statistics in ENA driver")
    MFC after: 2 weeks
    Sponsored by: Amazon, Inc.
---
 sys/dev/ena/ena.c | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/sys/dev/ena/ena.c b/sys/dev/ena/ena.c
index a4762ce9ebb1..a62b99d5ee1b 100644
--- a/sys/dev/ena/ena.c
+++ b/sys/dev/ena/ena.c
@@ -3479,6 +3479,15 @@ ena_reset_task(void *arg, int pending)
 	ENA_LOCK_UNLOCK();
 }
 
+static void
+ena_free_stats(struct ena_adapter *adapter)
+{
+	ena_free_counters((counter_u64_t *)&adapter->hw_stats,
+	    sizeof(struct ena_hw_stats));
+	ena_free_counters((counter_u64_t *)&adapter->dev_stats,
+	    sizeof(struct ena_stats_dev));
+
+}
 /**
  * ena_attach - Device Initialization Routine
  * @pdev: device information struct
@@ -3656,6 +3665,13 @@ ena_attach(device_t pdev)
 	/* initialize rings basic information */
 	ena_init_io_rings(adapter);
 
+	/* Initialize statistics */
+	ena_alloc_counters((counter_u64_t *)&adapter->dev_stats,
+	    sizeof(struct ena_stats_dev));
+	ena_alloc_counters((counter_u64_t *)&adapter->hw_stats,
+	    sizeof(struct ena_hw_stats));
+	ena_sysctl_add_nodes(adapter);
+
 	/* setup network interface */
 	rc = ena_setup_ifnet(pdev, adapter, &get_feat_ctx);
 	if (unlikely(rc != 0)) {
@@ -3677,13 +3693,6 @@ ena_attach(device_t pdev)
 	taskqueue_start_threads(&adapter->metrics_tq, 1, PI_NET, "%s metricsq",
 	    device_get_nameunit(adapter->pdev));
 
-	/* Initialize statistics */
-	ena_alloc_counters((counter_u64_t *)&adapter->dev_stats,
-	    sizeof(struct ena_stats_dev));
-	ena_alloc_counters((counter_u64_t *)&adapter->hw_stats,
-	    sizeof(struct ena_hw_stats));
-	ena_sysctl_add_nodes(adapter);
-
 #ifdef DEV_NETMAP
 	rc = ena_netmap_attach(adapter);
 	if (rc != 0) {
@@ -3706,6 +3715,7 @@ err_detach:
 	ether_ifdetach(adapter->ifp);
 #endif /* DEV_NETMAP */
 err_msix_free:
+	ena_free_stats(adapter);
 	ena_com_dev_reset(adapter->ena_dev, ENA_REGS_RESET_INIT_ERR);
 	ena_free_mgmnt_irq(adapter);
 	ena_disable_msix(adapter);
@@ -3778,10 +3788,7 @@ ena_detach(device_t pdev)
 	netmap_detach(adapter->ifp);
 #endif /* DEV_NETMAP */
 
-	ena_free_counters((counter_u64_t *)&adapter->hw_stats,
-	    sizeof(struct ena_hw_stats));
-	ena_free_counters((counter_u64_t *)&adapter->dev_stats,
-	    sizeof(struct ena_stats_dev));
+	ena_free_stats(adapter);
 
 	rc = ena_free_rx_dma_tag(adapter);
 	if (unlikely(rc != 0))



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202307041400.364E0AGM071474>