git: 8aee0c376754 - stable/15 - gve: fix kernel panic on attach failure

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 22 Oct 2026 17:32:24 UTC
The branch stable/15 has been updated by markj:

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

commit 8aee0c376754dd9fb3123d81f24129920c42690b
Author:     Jasper Tran O'Leary <jtranoleary@google.com>
AuthorDate: 2026-10-07 13:29:28 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-10-22 15:45:42 +0000

    gve: fix kernel panic on attach failure
    
    When device initialization fails during attach (for instance, if device
    resource configuration or firmware negotiation fails), the driver aborts
    and unrolls partial state via its detach routine. However, the teardown
    path assumes transmit and receive queues have already been created. If
    attach aborts before queue allocation, tearing down the uninitialized
    queues triggers a NULL pointer dereference and panics the kernel during
    boot.
    
    Guard queue teardown against uninitialized queue state so that early
    attach failures unwind safely, allowing the driver to report the failure
    gracefully without crashing the operating system.
    
    Signed-off-by: Jasper Tran O'Leary <jtranoleary@google.com>
    
    Reviewed by:    adrian, markj
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D60385
    
    (cherry picked from commit d45b063c06d46d0f43489708e226821cddbad53b)
---
 sys/dev/gve/gve_main.c | 16 ++++++++++------
 sys/dev/gve/gve_rx.c   |  3 +++
 sys/dev/gve/gve_tx.c   |  3 +++
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/sys/dev/gve/gve_main.c b/sys/dev/gve/gve_main.c
index 10197a8e15f8..fc88b3dfd014 100644
--- a/sys/dev/gve/gve_main.c
+++ b/sys/dev/gve/gve_main.c
@@ -694,13 +694,17 @@ gve_free_rings(struct gve_priv *priv)
 {
 	gve_free_irqs(priv);
 
-	gve_free_tx_rings(priv, 0, priv->tx_cfg.num_queues);
-	free(priv->tx, M_GVE);
-	priv->tx = NULL;
+	if (priv->tx != NULL) {
+		gve_free_tx_rings(priv, 0, priv->tx_cfg.num_queues);
+		free(priv->tx, M_GVE);
+		priv->tx = NULL;
+	}
 
-	gve_free_rx_rings(priv, 0, priv->rx_cfg.num_queues);
-	free(priv->rx, M_GVE);
-	priv->rx = NULL;
+	if (priv->rx != NULL) {
+		gve_free_rx_rings(priv, 0, priv->rx_cfg.num_queues);
+		free(priv->rx, M_GVE);
+		priv->rx = NULL;
+	}
 }
 
 static int
diff --git a/sys/dev/gve/gve_rx.c b/sys/dev/gve/gve_rx.c
index de64375ac4f3..8d3f1e2a68d9 100644
--- a/sys/dev/gve/gve_rx.c
+++ b/sys/dev/gve/gve_rx.c
@@ -209,6 +209,9 @@ gve_free_rx_rings(struct gve_priv *priv, uint16_t start_idx, uint16_t stop_idx)
 {
 	int i;
 
+	if (priv->rx == NULL)
+		return;
+
 	for (i = start_idx; i < stop_idx; i++)
 		gve_rx_free_ring(priv, i);
 }
diff --git a/sys/dev/gve/gve_tx.c b/sys/dev/gve/gve_tx.c
index 84e3a4c4eb9f..1fe7c7b21912 100644
--- a/sys/dev/gve/gve_tx.c
+++ b/sys/dev/gve/gve_tx.c
@@ -207,6 +207,9 @@ gve_free_tx_rings(struct gve_priv *priv, uint16_t start_idx, uint16_t stop_idx)
 {
 	int i;
 
+	if (priv->tx == NULL)
+		return;
+
 	for (i = start_idx; i < stop_idx; i++)
 		gve_tx_free_ring(priv, i);
 }