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

Hemant Agrawal <[email protected]>
Newsgroups org.dpdk.dev
Message-ID <[email protected]>
From: Jun Yang <[email protected]>

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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.