Netdev List
 help / color / mirror / Atom feed
* [PATCH net 0/3] ionic: fix port_info lifetime problems around device reset
@ 2026-08-15  0:00 Eric Joyner
  2026-08-15  0:00 ` [PATCH net 1/3] ionic: check for a NULL port_info in the remaining ethtool ops Eric Joyner
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Eric Joyner @ 2026-08-15  0:00 UTC (permalink / raw)
  To: netdev
  Cc: Brett Creeley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikhil P. Rao, Eric Joyner

The ionic port_info DMA buffer is read by most of the driver's ethtool
ops, and is freed and reallocated by the firmware recovery and PCI reset
paths. Those paths hold no lock that the ethtool ops honor - the
driver takes no rtnl anywhere - so ethtool can dereference a pointer
that has just been set to NULL, or read out of a buffer that has just
been freed.

Patch 1 adds the missing NULL checks to the six ethtool ops that lacked
them; ionic_get_link_ext_stats() and ionic_get_link_ksettings() already
had them. It fixes the oops reachable today and does not depend on the
other two, so it stands on its own if the approach in patch 2 needs
more discussion.

Patch 2 detaches the netdev in ionic_reset_prepare(). The ethtool core
only stays out of a driver when netif_device_present() is false, and the
firmware recovery path already relies on that; the PCI reset path never
did. This is what actually closes the window rather than papering over
it.

Patch 3 fixes an unrelated leak of the same buffer that turned up while
auditing the free paths: probe failures after the port has been set up
unwind through a label that never calls ionic_port_reset().

The port_info lifetime problems were pointed out by the netdev AI review
bot on an unrelated ionic ethtool patch:
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260731214021.15279-1-eric.joyner@amd.com

Signed-off-by: Eric Joyner <eric.joyner@amd.com>
---
Eric Joyner (3):
      ionic: check for a NULL port_info in the remaining ethtool ops
      ionic: detach the netdev in the PCI reset handler
      ionic: free port_info when probe fails after the port is set up

 .../net/ethernet/pensando/ionic/ionic_bus_pci.c    |  2 ++
 .../net/ethernet/pensando/ionic/ionic_ethtool.c    | 30 ++++++++++++++++++++++
 2 files changed, 32 insertions(+)
---
base-commit: 24ef02f934eeb48830cff6b739abc3c62b1d107b
change-id: 20260814-ionic-port-info-lifetime-3163779cb298

Best regards,
-- 
Eric Joyner <eric.joyner@amd.com>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH net 1/3] ionic: check for a NULL port_info in the remaining ethtool ops
  2026-08-15  0:00 [PATCH net 0/3] ionic: fix port_info lifetime problems around device reset Eric Joyner
@ 2026-08-15  0:00 ` Eric Joyner
  2026-08-15 22:39   ` Vadim Fedorenko
  2026-08-15  0:00 ` [PATCH net 2/3] ionic: detach the netdev in the PCI reset handler Eric Joyner
  2026-08-15  0:00 ` [PATCH net 3/3] ionic: free port_info when probe fails after the port is set up Eric Joyner
  2 siblings, 1 reply; 7+ messages in thread
From: Eric Joyner @ 2026-08-15  0:00 UTC (permalink / raw)
  To: netdev
  Cc: Brett Creeley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikhil P. Rao, Eric Joyner

port_info is a coherent DMA buffer that the firmware keeps up to date.
ionic_port_init() frees it and sets idev->port_info to NULL when the
device command to initialize the port fails, and that failure path can
run while the netdev is still registered:

  ionic_lif_deferred_work()
   -> ionic_lif_handle_fw_up()
       -> ionic_port_init()

  ionic_reset_done()
   -> ionic_setup_one()
       -> ionic_port_init()

ionic_get_link_ext_stats() and ionic_get_link_ksettings() already test
the pointer before using it, but the rest of the ethtool ops dereference
it blindly, so an unprivileged "ethtool --show-fec eth0" can oops after
a failed firmware recovery.

Add the same check to the ops that were missing it.

Fixes: c672412f6172 ("ionic: remove lifs on fw reset")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Eric Joyner <eric.joyner@amd.com>
---
 .../net/ethernet/pensando/ionic/ionic_ethtool.c    | 30 ++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
index c4ab4b5caa0a..0830422fe7ba 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
@@ -347,6 +347,11 @@ static int ionic_set_link_ksettings(struct net_device *netdev,
 	if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
 		return -EBUSY;
 
+	if (!idev->port_info) {
+		netdev_err(netdev, "port_info not initialized\n");
+		return -EOPNOTSUPP;
+	}
+
 	/* set autoneg */
 	if (ks->base.autoneg != idev->port_info->config.an_enable) {
 		mutex_lock(&ionic->dev_cmd_lock);
@@ -378,6 +383,11 @@ static void ionic_get_pauseparam(struct net_device *netdev,
 
 	pause->autoneg = 0;
 
+	if (!lif->ionic->idev.port_info) {
+		netdev_err_once(netdev, "port_info not initialized\n");
+		return;
+	}
+
 	pause_type = lif->ionic->idev.port_info->config.pause_type;
 	if (pause_type) {
 		pause->rx_pause = (pause_type & IONIC_PAUSE_F_RX) ? 1 : 0;
@@ -396,6 +406,11 @@ static int ionic_set_pauseparam(struct net_device *netdev,
 	if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
 		return -EBUSY;
 
+	if (!lif->ionic->idev.port_info) {
+		netdev_err(netdev, "port_info not initialized\n");
+		return -EOPNOTSUPP;
+	}
+
 	if (pause->autoneg)
 		return -EOPNOTSUPP;
 
@@ -424,6 +439,11 @@ static int ionic_get_fecparam(struct net_device *netdev,
 {
 	struct ionic_lif *lif = netdev_priv(netdev);
 
+	if (!lif->ionic->idev.port_info) {
+		netdev_err(netdev, "port_info not initialized\n");
+		return -EOPNOTSUPP;
+	}
+
 	switch (lif->ionic->idev.port_info->config.fec_type) {
 	case IONIC_PORT_FEC_TYPE_NONE:
 		fec->active_fec = ETHTOOL_FEC_OFF;
@@ -451,6 +471,11 @@ static int ionic_set_fecparam(struct net_device *netdev,
 	if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
 		return -EBUSY;
 
+	if (!lif->ionic->idev.port_info) {
+		netdev_err(netdev, "port_info not initialized\n");
+		return -EOPNOTSUPP;
+	}
+
 	if (lif->ionic->idev.port_info->config.an_enable) {
 		netdev_err(netdev, "FEC request not allowed while autoneg is enabled\n");
 		return -EINVAL;
@@ -1004,6 +1029,11 @@ static int ionic_get_module_eeprom_by_page(struct net_device *netdev,
 		return -EINVAL;
 	}
 
+	if (!idev->port_info) {
+		NL_SET_ERR_MSG_MOD(extack, "port_info not initialized");
+		return -EOPNOTSUPP;
+	}
+
 	switch (page_data->page) {
 	case 0:
 		src = &idev->port_info->status.xcvr.sprom[page_data->offset];

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net 2/3] ionic: detach the netdev in the PCI reset handler
  2026-08-15  0:00 [PATCH net 0/3] ionic: fix port_info lifetime problems around device reset Eric Joyner
  2026-08-15  0:00 ` [PATCH net 1/3] ionic: check for a NULL port_info in the remaining ethtool ops Eric Joyner
@ 2026-08-15  0:00 ` Eric Joyner
  2026-08-15 22:43   ` Vadim Fedorenko
  2026-08-15  0:00 ` [PATCH net 3/3] ionic: free port_info when probe fails after the port is set up Eric Joyner
  2 siblings, 1 reply; 7+ messages in thread
From: Eric Joyner @ 2026-08-15  0:00 UTC (permalink / raw)
  To: netdev
  Cc: Brett Creeley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikhil P. Rao, Eric Joyner

ionic_reset_prepare() tears down the queues, unmaps the BARs and calls
ionic_dev_teardown(), but leaves the netdev attached and registered for
the whole reset window. The ethtool core only refuses to call into a
driver when netif_device_present() is false, so ethtool ops keep running
against a device that is being dismantled underneath them, and
ionic_reset_done() can free idev->port_info out from under one of them
via ionic_setup_one() -> ionic_port_init().

The firmware recovery path already handles this properly:
ionic_lif_handle_fw_down() detaches before tearing anything down; so do
the same here.

No matching netif_device_attach() is needed on the way back up, since
ionic_reset_done() completes through ionic_restart_lif(), which already
re-attaches once the queues are alive again.

Fixes: a79b559e99be ("ionic: add FLR recovery support")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Eric Joyner <eric.joyner@amd.com>
---
 drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
index 05f19489ec5c..c15c4c705155 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
@@ -447,6 +447,7 @@ static void ionic_reset_prepare(struct pci_dev *pdev)
 	dev_dbg(ionic->dev, "%s: device stopping\n", __func__);
 
 	set_bit(IONIC_LIF_F_FW_RESET, lif->state);
+	netif_device_detach(lif->netdev);
 
 	timer_delete_sync(&ionic->watchdog_timer);
 	cancel_work_sync(&lif->deferred.work);

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net 3/3] ionic: free port_info when probe fails after the port is set up
  2026-08-15  0:00 [PATCH net 0/3] ionic: fix port_info lifetime problems around device reset Eric Joyner
  2026-08-15  0:00 ` [PATCH net 1/3] ionic: check for a NULL port_info in the remaining ethtool ops Eric Joyner
  2026-08-15  0:00 ` [PATCH net 2/3] ionic: detach the netdev in the PCI reset handler Eric Joyner
@ 2026-08-15  0:00 ` Eric Joyner
  2026-08-15 22:49   ` Vadim Fedorenko
  2 siblings, 1 reply; 7+ messages in thread
From: Eric Joyner @ 2026-08-15  0:00 UTC (permalink / raw)
  To: netdev
  Cc: Brett Creeley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikhil P. Rao, Eric Joyner

ionic_probe() allocates the port_info DMA buffer via ionic_setup_one()
-> ionic_port_init(). If probe then fails anywhere after that, it
unwinds through err_out_pci, which never calls ionic_port_reset();
ionic_dev_teardown() and ionic_clear_pci() do not touch port_info, and
so the buffer is leaked.

Since ionic_remove() already frees the port_info DMA buffer with
ionic_port_reset(), call that on the probe error path too.
ionic_port_reset() returns early when port_info is NULL, so it is safe
for the earlier gotos that land on the same label before the port was
ever set up.

Fixes: 04436595c435 ("ionic: Add port management commands")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Eric Joyner <eric.joyner@amd.com>
---
 drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
index c15c4c705155..2fb8795189b7 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
@@ -397,6 +397,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 err_out_free_irqs:
 	ionic_bus_free_irq_vectors(ionic);
 err_out_pci:
+	ionic_port_reset(ionic);
 	ionic_dev_teardown(ionic);
 	ionic_clear_pci(ionic);
 	ionic_debugfs_del_dev(ionic);

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH net 1/3] ionic: check for a NULL port_info in the remaining ethtool ops
  2026-08-15  0:00 ` [PATCH net 1/3] ionic: check for a NULL port_info in the remaining ethtool ops Eric Joyner
@ 2026-08-15 22:39   ` Vadim Fedorenko
  0 siblings, 0 replies; 7+ messages in thread
From: Vadim Fedorenko @ 2026-08-15 22:39 UTC (permalink / raw)
  To: Eric Joyner, netdev
  Cc: Brett Creeley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikhil P. Rao

On 15/08/2026 01:00, Eric Joyner wrote:
> port_info is a coherent DMA buffer that the firmware keeps up to date.
> ionic_port_init() frees it and sets idev->port_info to NULL when the
> device command to initialize the port fails, and that failure path can
> run while the netdev is still registered:
> 
>    ionic_lif_deferred_work()
>     -> ionic_lif_handle_fw_up()
>         -> ionic_port_init()
> 
>    ionic_reset_done()
>     -> ionic_setup_one()
>         -> ionic_port_init()
> 
> ionic_get_link_ext_stats() and ionic_get_link_ksettings() already test
> the pointer before using it, but the rest of the ethtool ops dereference
> it blindly, so an unprivileged "ethtool --show-fec eth0" can oops after
> a failed firmware recovery.
> 
> Add the same check to the ops that were missing it.
> 
> Fixes: c672412f6172 ("ionic: remove lifs on fw reset")
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Eric Joyner <eric.joyner@amd.com>
> ---
>   .../net/ethernet/pensando/ionic/ionic_ethtool.c    | 30 ++++++++++++++++++++++
>   1 file changed, 30 insertions(+)

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net 2/3] ionic: detach the netdev in the PCI reset handler
  2026-08-15  0:00 ` [PATCH net 2/3] ionic: detach the netdev in the PCI reset handler Eric Joyner
@ 2026-08-15 22:43   ` Vadim Fedorenko
  0 siblings, 0 replies; 7+ messages in thread
From: Vadim Fedorenko @ 2026-08-15 22:43 UTC (permalink / raw)
  To: Eric Joyner, netdev
  Cc: Brett Creeley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikhil P. Rao

On 15/08/2026 01:00, Eric Joyner wrote:
> ionic_reset_prepare() tears down the queues, unmaps the BARs and calls
> ionic_dev_teardown(), but leaves the netdev attached and registered for
> the whole reset window. The ethtool core only refuses to call into a
> driver when netif_device_present() is false, so ethtool ops keep running
> against a device that is being dismantled underneath them, and
> ionic_reset_done() can free idev->port_info out from under one of them
> via ionic_setup_one() -> ionic_port_init().
> 
> The firmware recovery path already handles this properly:
> ionic_lif_handle_fw_down() detaches before tearing anything down; so do
> the same here.
> 
> No matching netif_device_attach() is needed on the way back up, since
> ionic_reset_done() completes through ionic_restart_lif(), which already
> re-attaches once the queues are alive again.
> 
> Fixes: a79b559e99be ("ionic: add FLR recovery support")
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Eric Joyner <eric.joyner@amd.com>

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net 3/3] ionic: free port_info when probe fails after the port is set up
  2026-08-15  0:00 ` [PATCH net 3/3] ionic: free port_info when probe fails after the port is set up Eric Joyner
@ 2026-08-15 22:49   ` Vadim Fedorenko
  0 siblings, 0 replies; 7+ messages in thread
From: Vadim Fedorenko @ 2026-08-15 22:49 UTC (permalink / raw)
  To: Eric Joyner, netdev
  Cc: Brett Creeley, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Nikhil P. Rao

On 15/08/2026 01:00, Eric Joyner wrote:
> ionic_probe() allocates the port_info DMA buffer via ionic_setup_one()
> -> ionic_port_init(). If probe then fails anywhere after that, it
> unwinds through err_out_pci, which never calls ionic_port_reset();
> ionic_dev_teardown() and ionic_clear_pci() do not touch port_info, and
> so the buffer is leaked.
> 
> Since ionic_remove() already frees the port_info DMA buffer with
> ionic_port_reset(), call that on the probe error path too.
> ionic_port_reset() returns early when port_info is NULL, so it is safe
> for the earlier gotos that land on the same label before the port was
> ever set up.
> 
> Fixes: 04436595c435 ("ionic: Add port management commands")
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Eric Joyner <eric.joyner@amd.com>
> ---
>   drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
> index c15c4c705155..2fb8795189b7 100644
> --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
> +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
> @@ -397,6 +397,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>   err_out_free_irqs:
>   	ionic_bus_free_irq_vectors(ionic);
>   err_out_pci:
> +	ionic_port_reset(ionic);
>   	ionic_dev_teardown(ionic);
>   	ionic_clear_pci(ionic);
>   	ionic_debugfs_del_dev(ionic);
> 
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-08-15 22:49 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-15  0:00 [PATCH net 0/3] ionic: fix port_info lifetime problems around device reset Eric Joyner
2026-08-15  0:00 ` [PATCH net 1/3] ionic: check for a NULL port_info in the remaining ethtool ops Eric Joyner
2026-08-15 22:39   ` Vadim Fedorenko
2026-08-15  0:00 ` [PATCH net 2/3] ionic: detach the netdev in the PCI reset handler Eric Joyner
2026-08-15 22:43   ` Vadim Fedorenko
2026-08-15  0:00 ` [PATCH net 3/3] ionic: free port_info when probe fails after the port is set up Eric Joyner
2026-08-15 22:49   ` Vadim Fedorenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox