Four error paths in the secondary-process branch of
rte_pmd_tap_probe() returned -1 without cleanup:

- primary process not alive: leaked eth_dev
- process_private malloc failure: leaked eth_dev
- tap_mp_attach_queues failure: leaked eth_dev and process_private
- rte_mp_action_register failure: leaked eth_dev and process_private

Add secondary_fail and secondary_fail_pp labels to free
process_private and release the ethdev port.

Bugzilla ID: 1881
Fixes: c9aa56edec8e ("net/tap: access primary process queues from secondary")
Cc: [email protected]

Signed-off-by: Stephen Hemminger <[email protected]>
---
 drivers/net/tap/rte_eth_tap.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 9b38d1f50b..974b45ecad 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -2502,31 +2502,38 @@ rte_pmd_tap_probe(struct rte_vdev_device *dev)
                eth_dev->tx_pkt_burst = pmd_tx_burst;
                if (!rte_eal_primary_proc_alive(NULL)) {
                        TAP_LOG(ERR, "Primary process is missing");
-                       return -1;
+                       goto secondary_fail;
                }
                eth_dev->process_private = malloc(sizeof(struct 
pmd_process_private));
                if (eth_dev->process_private == NULL) {
                        TAP_LOG(ERR,
                                "Failed to alloc memory for process private");
-                       return -1;
+                       goto secondary_fail;
                }
                memset(eth_dev->process_private, 0, sizeof(struct 
pmd_process_private));
 
                ret = tap_mp_attach_queues(name, eth_dev);
                if (ret != 0)
-                       return -1;
+                       goto secondary_fail_pp;
 
                if (!tap_devices_count) {
                        ret = rte_mp_action_register(TAP_MP_REQ_START_RXTX, 
tap_mp_req_start_rxtx);
                        if (ret < 0 && rte_errno != ENOTSUP) {
                                TAP_LOG(ERR, "tap: Failed to register IPC 
callback: %s",
                                        strerror(rte_errno));
-                               return -1;
+                               goto secondary_fail_pp;
                        }
                }
                tap_devices_count++;
                rte_eth_dev_probing_finish(eth_dev);
                return 0;
+
+secondary_fail_pp:
+               free(eth_dev->process_private);
+               eth_dev->process_private = NULL;
+secondary_fail:
+               rte_eth_dev_release_port(eth_dev);
+               return -1;
        }
 
        /* use tap%d which causes kernel to choose next available */
-- 
2.51.0

Reply via email to