Re: [PATCH net-next v3 09/15] gve: simplify reset logic
[email protected] Tue, 04 Aug 2026 18:47:01 +0000
| Newsgroups | org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: New issues: - [High] The `while (!service_task_enabled)` loop in `gve_recover` forcefully enables `service_task`, overriding concurrent `disable_work_sync` calls from PM suspend, allowing the task to run while the device is suspended. Pre-existing issues: - [High] `gve_xsk_pool_enable` and `gve_xsk_pool_disable` unconditionally dereference `priv->xsk_pools`, which is NULL if the device failed to recover from a reset. -- --- Patch [9]: [PATCH net-next v3 09/15] gve: simplify reset logic --- commit e14381443089f802adbf14cabd9d5e8b89337630 Author: Joshua Washington <[email protected]> Subject: gve: simplify reset logic This commit simplifies the GVE reset logic by removing recursive resets, avoiding resets during teardown, and separating control plane resource allocation from device setup. Shared resources are now retained until the hardware reset completes to prevent premature release. > diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c > index 6f04eefd04166..578520e107930 100644 > --- a/drivers/net/ethernet/google/gve/gve_main.c > +++ b/drivers/net/ethernet/google/gve/gve_main.c > @@ -591,7 +591,22 @@ static void gve_free_notify_blocks(struct gve_priv *priv) > priv->msix_vectors = NULL; > } > > -static int gve_setup_device_resources(struct gve_priv *priv) > +static void gve_free_control_plane_resources(struct gve_priv *priv) > +{ > + bitmap_free(priv->xsk_pools); > + priv->xsk_pools = NULL; [Severity: High] This is a pre-existing issue, but does the driver safely handle a NULL xsk_pools bitmap if recovery fails? If gve_recover() fails during a reset (for example, if gve_setup_device() fails), priv->xsk_pools is left as NULL because it is freed here during teardown. Since the netdev remains registered, a subsequent AF_XDP socket bind from userspace could call gve_xsk_pool_enable() or gve_xsk_pool_disable(). These functions unconditionally dereference the bitmap: drivers/net/ethernet/google/gve/gve_main.c:gve_xsk_pool_enable() { ... set_bit(qid, priv->xsk_pools); ... } Could this lead to an immediate NULL pointer dereference if a user with sufficient privileges configures AF_XDP on the failed device? [ ... ] > -static int gve_reset_recovery(struct gve_priv *priv, bool was_up) > +static int gve_recover(struct gve_priv *priv, bool setup_queues) > { > + bool service_task_enabled = false; > int err; > > err = gve_adminq_init(priv); > if (err) { > dev_err(&priv->pdev->dev, > "Failed to alloc admin queue: err=%d\n", err); > - goto err; > + goto teardown_device; > } > > err = gve_adminq_verify_driver_compatibility(priv); > if (err) { > dev_err(&priv->pdev->dev, > "Could not verify driver compatibility: err=%d\n", err); > - goto err_free_adminq; > + goto teardown_device; > } > > err = gve_setup_device(priv); > if (err) > - goto err_free_adminq; > - if (was_up) { > + goto teardown_device; > + > + /* In the case of cascading failures, the disable count could be greater > + * than 1. The service task must be enabled before starting queues. > + */ > + while (!service_task_enabled) > + service_task_enabled = enable_work(&priv->service_task); [Severity: High] Could this loop override a concurrent suspend operation? If a device reset (gve_reset) runs concurrently with power management suspend (gve_suspend), gve_suspend increments the service task's disable count via disable_work_sync() and waits for the rtnl_lock. If gve_reset holds the rtnl_lock and executes gve_recover(), it drops the disable count to 0 in this loop. Once gve_reset finishes, gve_suspend acquires the lock, completes teardown, and suspends the device to D3. Since the service_task is now enabled, couldn't it be scheduled to run while the device is suspended? This might result in an MMIO read on a D3 state device, causing a kernel panic or PCIe AER fatal error. [ ... ] > @@ -3017,16 +3025,14 @@ static int gve_suspend(struct device *dev) > struct gve_priv *priv = netdev_priv(netdev); > bool was_up = netif_running(priv->dev); > > + disable_work_sync(&priv->service_task); > + > priv->suspend_cnt++; -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=9