git: d45b063c06d4 - main - gve: fix kernel panic on attach failure
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 07 Oct 2026 14:05:08 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=d45b063c06d46d0f43489708e226821cddbad53b
commit d45b063c06d46d0f43489708e226821cddbad53b
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-07 13:29:40 +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
---
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 5e0611e1d6e4..53451acc1934 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);
}