[PATCH v9 24/25] drivers: add dpaax destructor to gate EAL memory frees

Hemant Agrawal hemant.agrawal at nxp.com
Wed Aug 12 19:46:08 CEST 2026


From: Jun Yang <jun.yang at nxp.com>

Add a dpaax_enter_destructor() function that drivers call at the start
of their RTE_FINI destructors to signal that the process is tearing
down. Subsequent attempts to free EAL-backed memory (such as IOVA table
entries) are then skipped, avoiding use-after-free crashes when the EAL
has already unmapped hugepages before per-driver destructors run.

Callers updated: dpaa_bus, dpaa_mempool, dpaa_ethdev.

Signed-off-by: Jun Yang <jun.yang at nxp.com>
---
 drivers/bus/dpaa/dpaa_bus.c             |  1 +
 drivers/common/dpaax/compat.h           | 22 +++++++++++++++++-----
 drivers/common/dpaax/dpaax_iova_table.c | 25 ++++++++++++++++++++++++-
 drivers/mempool/dpaa/dpaa_mempool.c     |  7 ++++---
 drivers/net/dpaa/dpaa_ethdev.c          |  1 +
 5 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/drivers/bus/dpaa/dpaa_bus.c b/drivers/bus/dpaa/dpaa_bus.c
index 16892b5247..01bfaacbf7 100644
--- a/drivers/bus/dpaa/dpaa_bus.c
+++ b/drivers/bus/dpaa/dpaa_bus.c
@@ -915,6 +915,7 @@ RTE_FINI_PRIO(dpaa_cleanup, 102)
 	if (!dpaa_bus_global_init)
 		return;
 
+	dpaax_enter_destructor();
 	/* cleanup portals in case non-graceful exit */
 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
 		/* Check for non zero id */
diff --git a/drivers/common/dpaax/compat.h b/drivers/common/dpaax/compat.h
index d0635255da..b826a55de2 100644
--- a/drivers/common/dpaax/compat.h
+++ b/drivers/common/dpaax/compat.h
@@ -2,7 +2,7 @@
  *
  * Copyright 2011 Freescale Semiconductor, Inc.
  * All rights reserved.
- * Copyright 2019-2020 NXP
+ * Copyright 2019-2020, 2026 NXP
  *
  */
 
@@ -336,11 +336,23 @@ static inline void copy_bytes(void *dest, const void *src, size_t sz)
 #define copy_bytes memcpy
 #endif
 
-/* Allocator stuff */
-#define kmalloc(sz, t)	rte_malloc(NULL, sz, 0)
-#define kzalloc(sz, t)  rte_zmalloc(NULL, sz, 0)
+__rte_internal
+void dpaax_enter_destructor(void);
+__rte_internal
+int is_dpaax_in_destructor(void);
+
+/* Allocator stuff, make sure the eal memory pool is available when calling.*/
+#define kmalloc(sz, _t) ((void)(_t), rte_malloc(NULL, sz, 0))
+#define kzalloc(sz, _t) ((void)(_t), rte_zmalloc(NULL, sz, 0))
 #define vmalloc(sz)	rte_malloc(NULL, sz, 0)
-#define kfree(p)	rte_free(p)
+
+#define kfree(p) \
+({ \
+	if (!is_dpaax_in_destructor()) \
+		rte_free(p); \
+	else \
+		pr_debug("Eal memory has been destroyed.\n"); \
+})
 
 static inline unsigned long get_zeroed_page(gfp_t __foo __rte_unused)
 {
diff --git a/drivers/common/dpaax/dpaax_iova_table.c b/drivers/common/dpaax/dpaax_iova_table.c
index 1220d9654b..d53b24d4f4 100644
--- a/drivers/common/dpaax/dpaax_iova_table.c
+++ b/drivers/common/dpaax/dpaax_iova_table.c
@@ -1,17 +1,40 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2023 NXP
+ * Copyright 2018-2023,2026 NXP
  */
 
 #include <eal_export.h>
 #include <rte_memory.h>
 
 #include "dpaax_iova_table.h"
+#include "compat.h"
 #include "dpaax_logs.h"
 
 /* Global table reference */
 RTE_EXPORT_INTERNAL_SYMBOL(dpaax_iova_table_p)
 struct dpaax_iova_table *dpaax_iova_table_p;
 
+/*
+ * Track whether the process is executing DPDK destructors. During
+ * teardown the EAL memory subsystem may already be gone, so freeing
+ * EAL memory from a DPAAx destructor is unsafe. Drivers mark the
+ * destructor context via dpaax_enter_destructor() so that kfree()
+ * (see compat.h) can skip rte_free() in that window.
+ */
+static int s_dpaax_in_destructor;
+
+RTE_EXPORT_INTERNAL_SYMBOL(dpaax_enter_destructor)
+void dpaax_enter_destructor(void)
+{
+	s_dpaax_in_destructor = 1;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(is_dpaax_in_destructor)
+int is_dpaax_in_destructor(void)
+{
+	return s_dpaax_in_destructor;
+}
+
+
 static int dpaax_handle_memevents(void);
 
 /* A structure representing the device-tree node available in /proc/device-tree.
diff --git a/drivers/mempool/dpaa/dpaa_mempool.c b/drivers/mempool/dpaa/dpaa_mempool.c
index 1687700482..d2c68ac747 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.c
+++ b/drivers/mempool/dpaa/dpaa_mempool.c
@@ -517,15 +517,16 @@ RTE_FINI_PRIO(dpaa_mpool_finish, RTE_PRIORITY_104)
 {
 	uint16_t bpid;
 
+	dpaax_enter_destructor();
+
 	for (bpid = 0; bpid < DPAA_MAX_BPOOLS; bpid++) {
 		if (s_dpaa_bpid_allocated_flag[bpid].used) {
 			bman_free_bpid(bpid, s_dpaa_bpid_allocated_flag[bpid].flags);
 			s_dpaa_bpid_allocated_flag[bpid].used = false;
 		}
 	}
-	/** The rte_dpaa_bpid_info and bman_pool from EAL mem have been released
-	 * with EAL mem pool being destroyed.
-	 */
+	rte_free(rte_dpaa_bpid_info);
+	rte_dpaa_bpid_info = NULL;
 }
 
 RTE_MEMPOOL_REGISTER_OPS(dpaa_mpool_ops);
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 1751a7dd1a..d6da3a329a 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -2824,6 +2824,7 @@ RTE_FINI_PRIO(dpaa_finish, 103)
 	struct rte_eth_dev *dev;
 
 	PMD_INIT_FUNC_TRACE();
+	dpaax_enter_destructor();
 	/* For secondary, primary will do all the cleanup */
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return;
-- 
2.25.1



More information about the dev mailing list