tap_tx_queue_release() reads dev->data->rx_queues[qid] to find out whether
the queue file descriptor is still shared with the Rx side. When ethdev
tears both queue arrays down it releases the Rx queues first and frees
dev->data->rx_queues, so the Tx release dereferences a NULL array and the
process crashes.

Both ethdev call sites do that: the reset_queues error path of
rte_eth_dev_configure(), reached whenever the driver rejects a
reconfigure, and rte_eth_dev_internal_reset(), which bonding calls
unconditionally when a member port is removed.

Treat a freed Rx array like an already released Rx queue and close the
file descriptor. tap_rx_queue_release() reads dev->data->tx_queues the
same way; that array is always still allocated when it runs, but guard it
too so both paths stay symmetric.

Fixes: 72ab1dc1598e ("net/tap: do not duplicate file descriptors")
Cc: [email protected]
Signed-off-by: Maxime Leroy <[email protected]>
---
 drivers/net/tap/rte_eth_tap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index b93452f168..eec18a7c97 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1170,7 +1170,7 @@ tap_rx_queue_release(struct rte_eth_dev *dev, uint16_t 
qid)
 
        tap_rxq_pool_free(rxq->pool);
 
-       if (dev->data->tx_queues[qid] == NULL)
+       if (dev->data->tx_queues == NULL || dev->data->tx_queues[qid] == NULL)
                tap_queue_close(process_private, qid);
 
        rte_free(rxq);
@@ -1187,7 +1187,7 @@ tap_tx_queue_release(struct rte_eth_dev *dev, uint16_t 
qid)
                return;
 
        process_private = rte_eth_devices[txq->out_port].process_private;
-       if (dev->data->rx_queues[qid] == NULL)
+       if (dev->data->rx_queues == NULL || dev->data->rx_queues[qid] == NULL)
                tap_queue_close(process_private, qid);
 
        rte_free(txq);
-- 
2.43.0

Reply via email to