If register_netdev() fails in ibmveth_probe(), for example with -EINTR
when the binding task is killed, probe frees the netdev but leaves the
pool%d kobjects embedded in it registered in sysfs. Reading
/sys/devices/vio/<unit>/pool0/num is then a use-after-free, and the
next probe cannot add pool0.
Put the kobjects before freeing the netdev, as ibmveth_remove() does,
on this path and on the netif_set_real_num_tx_queues() one.
As in remove(), the kobjects have no release(), so with
CONFIG_DEBUG_KOBJECT_RELEASE their deferred cleanup, including
removing the sysfs files, can still run after the free.
Tested on a POWER10 LPAR with register_netdev() forced to fail with
-EINTR: no pool%d directories remain and the device binds again.
Fixes: 860f242eb534 ("[PATCH] ibmveth change buffer pools dynamically")
Signed-off-by: Mingming Cao <[email protected]>
---
drivers/net/ethernet/ibm/ibmveth.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmveth.c
b/drivers/net/ethernet/ibm/ibmveth.c
index b89ce389d951..d5ba2f2650d0 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1965,8 +1965,7 @@ static int ibmveth_probe(struct vio_dev *dev, const
struct vio_device_id *id)
if (rc) {
netdev_dbg(netdev, "failed to set number of tx queues rc=%d\n",
rc);
- free_netdev(netdev);
- return rc;
+ goto err_put_pools;
}
adapter->tx_ltb_size = PAGE_ALIGN(IBMVETH_MAX_TX_BUF_SIZE);
for (i = 0; i < IBMVETH_MAX_QUEUES; i++)
@@ -1981,13 +1980,18 @@ static int ibmveth_probe(struct vio_dev *dev, const
struct vio_device_id *id)
if (rc) {
netdev_dbg(netdev, "failed to register netdev rc=%d\n", rc);
- free_netdev(netdev);
- return rc;
+ goto err_put_pools;
}
netdev_dbg(netdev, "registered\n");
return 0;
+
+err_put_pools:
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
+ kobject_put(&adapter->rx_buff_pool[i].kobj);
+ free_netdev(netdev);
+ return rc;
}
static void ibmveth_remove(struct vio_dev *dev)
--
2.39.3 (Apple Git-146)