[v6,02/11] eal: add new secure free function

Message ID 20250213221819.1856769-3-stephen@networkplumber.org (mailing list archive)
State Superseded
Delegated to: Thomas Monjalon
Headers
Series secure zeroing of memory |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Stephen Hemminger Feb. 13, 2025, 10:16 p.m. UTC
Although internally rte_free does poison the buffer in most
cases, it is useful to have function that explicitly does
this to avoid any security issues.

Name of new API is chosen to be similar to Linux kernel
kfree_sensitive() to make porting drivers easier.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/eal/common/rte_malloc.c  | 30 ++++++++++++++++++++++++------
 lib/eal/include/rte_malloc.h | 20 ++++++++++++++++++++
 lib/eal/version.map          |  3 +++
 3 files changed, 47 insertions(+), 6 deletions(-)
  

Comments

Morten Brørup Feb. 15, 2025, 3:25 p.m. UTC | #1
> +
> +/**

Missing:
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *

> + * Frees the memory space pointed to by the provided pointer
> + * and guarantees it will be zero'd before reuse. Since this
> + * function is slower than simple rte_free() it should only
> + * be used for security keys and other sensitive data.
> + *
> + * This pointer must have been returned by a previous call to
> + * rte_malloc(), rte_zmalloc(), rte_calloc() or rte_realloc(). The
> behaviour of
> + * rte_free() is undefined if the pointer does not match this
> requirement.
> + *
> + * If the pointer is NULL, the function does nothing.
> + *
> + * @param ptr
> + *   The pointer to memory to be freed.
> + */
> +__rte_experimental
> +void
> +rte_free_sensitive(void *ptr);
> +

With the warning added to the description,
Acked-by: Morten Brørup <mb@smartsharesystems.com>
  

Patch

diff --git a/lib/eal/common/rte_malloc.c b/lib/eal/common/rte_malloc.c
index 3eed4d4be6..fc2d2ae3f1 100644
--- a/lib/eal/common/rte_malloc.c
+++ b/lib/eal/common/rte_malloc.c
@@ -15,6 +15,7 @@ 
 #include <rte_eal_memconfig.h>
 #include <rte_common.h>
 #include <rte_spinlock.h>
+#include <rte_string_fns.h>
 
 #include <eal_trace_internal.h>
 
@@ -27,27 +28,44 @@ 
 
 
 /* Free the memory space back to heap */
-static void
-mem_free(void *addr, const bool trace_ena)
+static inline void
+mem_free(void *addr, const bool trace_ena, bool zero)
 {
+	struct malloc_elem *elem;
+
 	if (trace_ena)
 		rte_eal_trace_mem_free(addr);
 
-	if (addr == NULL) return;
-	if (malloc_heap_free(malloc_elem_from_data(addr)) < 0)
+	if (addr == NULL)
+		return;
+
+	elem = malloc_elem_from_data(addr);
+	if (zero) {
+		size_t data_len = elem->size - MALLOC_ELEM_OVERHEAD;
+
+		rte_memzero_explicit(addr, data_len);
+	}
+
+	if (malloc_heap_free(elem) < 0)
 		EAL_LOG(ERR, "Error: Invalid memory");
 }
 
 void
 rte_free(void *addr)
 {
-	mem_free(addr, true);
+	mem_free(addr, true, false);
+}
+
+void
+rte_free_sensitive(void *addr)
+{
+	mem_free(addr, true, true);
 }
 
 void
 eal_free_no_trace(void *addr)
 {
-	mem_free(addr, false);
+	mem_free(addr, false, false);
 }
 
 static void *
diff --git a/lib/eal/include/rte_malloc.h b/lib/eal/include/rte_malloc.h
index c8836de67c..69c965099d 100644
--- a/lib/eal/include/rte_malloc.h
+++ b/lib/eal/include/rte_malloc.h
@@ -51,6 +51,26 @@  struct rte_malloc_socket_stats {
 void
 rte_free(void *ptr);
 
+
+/**
+ * Frees the memory space pointed to by the provided pointer
+ * and guarantees it will be zero'd before reuse. Since this
+ * function is slower than simple rte_free() it should only
+ * be used for security keys and other sensitive data.
+ *
+ * This pointer must have been returned by a previous call to
+ * rte_malloc(), rte_zmalloc(), rte_calloc() or rte_realloc(). The behaviour of
+ * rte_free() is undefined if the pointer does not match this requirement.
+ *
+ * If the pointer is NULL, the function does nothing.
+ *
+ * @param ptr
+ *   The pointer to memory to be freed.
+ */
+__rte_experimental
+void
+rte_free_sensitive(void *ptr);
+
 /**
  * This function allocates memory from the huge-page area of memory. The memory
  * is not cleared. In NUMA systems, the memory allocated resides on the same
diff --git a/lib/eal/version.map b/lib/eal/version.map
index a20c713eb1..fa67ff44d5 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -398,6 +398,9 @@  EXPERIMENTAL {
 	# added in 24.11
 	rte_bitset_to_str;
 	rte_lcore_var_alloc;
+
+	# added in 25.03
+	rte_free_sensitive;
 };
 
 INTERNAL {