[PATCH v4 08/10] net/tap: fix use-after-free on remote flow creation failure

Stephen Hemminger
2026-02-20T17:07:20Z

After a local TC filter rule is installed and the flow is inserted
into pmd->flows, failure during remote flow creation jumps to the
fail label which frees the flow without removing it from the list
and without deleting the kernel-side TC rule.

Send RTM_DELTFILTER to clean up the local rule and call
LIST_REMOVE before freeing.

Bugzilla ID: 1881
Fixes: 2bc06869cd94 ("net/tap: add remote netdevice traffic capture")
Cc: stable@dpdk.org

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/tap/tap_flow.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c
index 9d4ef27a8a..427faf75d5 100644
--- a/drivers/net/tap/tap_flow.c
+++ b/drivers/net/tap/tap_flow.c
@@ -1293,7 +1293,7 @@ tap_flow_create(struct rte_eth_dev *dev,
rte_flow_error_set(
error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
"cannot allocate memory for rte_flow");
- goto fail;
+ goto fail_remove;
}
msg = &remote_flow->msg;
/* set the rule if_index for the remote netdevice */
@@ -1307,14 +1307,14 @@ tap_flow_create(struct rte_eth_dev *dev,
rte_flow_error_set(
error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
NULL, "rte flow rule validation failed");
- goto fail;
+ goto fail_remove;
}
err = tap_nl_send(pmd->nlsk_fd, &msg->nh);
if (err < 0) {
rte_flow_error_set(
error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
NULL, "Failure sending nl request");
- goto fail;
+ goto fail_remove;
}
err = tap_nl_recv_ack(pmd->nlsk_fd);
if (err < 0) {
@@ -1325,15 +1325,22 @@ tap_flow_create(struct rte_eth_dev *dev,
error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
NULL,
"overlapping rules or Kernel too old for flower support");
- goto fail;
+ goto fail_remove;
}
flow->remote_flow = remote_flow;
}
return flow;
+
+fail_remove:
+ /* Delete the local TC rule that was already installed */
+ flow->msg.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ flow->msg.nh.nlmsg_type = RTM_DELTFILTER;
+ if (tap_nl_send(pmd->nlsk_fd, &flow->msg.nh) >= 0)
+ tap_nl_recv_ack(pmd->nlsk_fd);
+ LIST_REMOVE(flow, next);
fail:
rte_free(remote_flow);
- if (flow)
- tap_flow_free(pmd, flow);
+ tap_flow_free(pmd, flow);
return NULL;
}

--
2.51.0