[libvirt] [PATCH 1/6] util: alloc: Introduce freeing helpers that clear the memory before freeing

Peter Krempa pkrempa at redhat.com
Fri May 13 16:04:41 UTC 2016


For a few cases where we handle secret information it's good to clear
the buffers containing sensitive data before freeing them.

Introduce VIR_DISPOSE, VIR_DISPOSE_N and VIR_DISPOSE_STRING that allow
simple clearing fo the buffers holding sensitive information on cleanup
paths.
---
 src/libvirt_private.syms |  1 +
 src/util/viralloc.c      | 36 +++++++++++++++++++++++++++++++
 src/util/viralloc.h      | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/viralloctest.c     | 37 ++++++++++++++++++++++++++++++++
 4 files changed, 130 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a980a32..9c1abbb 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1127,6 +1127,7 @@ virAllocTestInit;
 virAllocTestOOM;
 virAllocVar;
 virDeleteElementsN;
+virDispose;
 virExpandN;
 virFree;
 virInsertElementsN;
diff --git a/src/util/viralloc.c b/src/util/viralloc.c
index 63f43d0..812aa5b 100644
--- a/src/util/viralloc.c
+++ b/src/util/viralloc.c
@@ -583,3 +583,39 @@ void virFree(void *ptrptr)
     *(void**)ptrptr = NULL;
     errno = save_errno;
 }
+
+
+/**
+ * virDispose:
+ * @ptrptr: pointer to pointer for address of memory to be sanitized and freed
+ * @count: count of elements in the array to dispose
+ * @elemet_size: size of one element
+ * @countptr: pointer to the count variable to clear (may be NULL)
+ *
+ * Clear and release the chunk of memory in the pointer pointed to by 'prtptr'.
+ *
+ * If @countptr is provided, it's value is used instead of @count and it's set
+ * to 0 after clearing and freeing the memory.
+ *
+ * After release, 'ptrptr' will be updated to point to NULL.
+ */
+void virDispose(void *ptrptr,
+                size_t count,
+                size_t element_size,
+                size_t *countptr)
+{
+    int save_errno = errno;
+
+    if (countptr)
+        count = *countptr;
+
+    if (*(void**)ptrptr && count > 0)
+        memset(*(void **)ptrptr, 0, count * element_size);
+
+    free(*(void**)ptrptr);
+    *(void**)ptrptr = NULL;
+
+    if (countptr)
+        *countptr = 0;
+    errno = save_errno;
+}
diff --git a/src/util/viralloc.h b/src/util/viralloc.h
index bf85c16..5f4e27b 100644
--- a/src/util/viralloc.h
+++ b/src/util/viralloc.h
@@ -78,6 +78,9 @@ int virAllocVar(void *ptrptr, size_t struct_size, size_t element_size, size_t co
     ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1);
 void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1);

+void virDispose(void *ptrptr, size_t count, size_t element_size, size_t *countptr)
+    ATTRIBUTE_NONNULL(1);
+
 /**
  * VIR_ALLOC:
  * @ptr: pointer to hold address of allocated memory
@@ -561,6 +564,59 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1);
 #  define VIR_FREE(ptr) virFree(&(ptr))
 # endif

+
+/**
+ * VIR_DISPOSE_N:
+ * @ptr: pointer holding address to be cleared and freed
+ * @count: count of elements in @ptr
+ *
+ * Clear the memory of the array of elemets pointed to by 'ptr' of 'count'
+ * elements and free it. Update the pointer/count to NULL/0.
+ *
+ * This macro is safe to use on arguments with side effects.
+ */
+# if !STATIC_ANALYSIS
+/* See explanation in VIR_FREE */
+#  define VIR_DISPOSE_N(ptr, count) virDispose(1 ? (void *) &(ptr) : (ptr), 0, \
+                                             sizeof(*(ptr)), &(count))
+# else
+#  define VIR_DISPOSE_N(ptr, count) virDispose(&(ptr), 0, sizeof(*(ptr)), &(count))
+# endif
+
+
+/**
+ * VIR_DISPOSE_STRING:
+ * @ptr: pointer to a string to be cleared and freed
+ *
+ * Clears the string and frees the corresponding memory.
+ *
+ * This macro is not safe to be used on arguments with side effects.
+ */
+# if !STATIC_ANALYSIS
+/* See explanation in VIR_FREE */
+#  define VIR_DISPOSE_STRING(ptr) virDispose(1 ? (void *) &(ptr) : (ptr),      \
+                                             (ptr) ? strlen((ptr)) : 0, 1, NULL)
+# else
+#  define VIR_DISPOSE_STRING(ptr) virDispose(&(ptr), (ptr) ? strlen((ptr)) : 1, NULL)
+# endif
+
+
+/**
+ * VIR_DISPOSE:
+ * @ptr: pointer to memory to be cleared and freed
+ *
+ * Clears and frees the corresponding memory.
+ *
+ * This macro is safe to be used on arguments with side effects.
+ */
+# if !STATIC_ANALYSIS
+/* See explanation in VIR_FREE */
+#  define VIR_DISPOSE(ptr) virDispose(1 ? (void *) &(ptr) : (ptr), 1, sizeof(*(ptr)), NULL)
+# else
+#  define VIR_DISPOSE(ptr) virDispose(&(ptr), 1, sizeof(*(ptr)), NULL)
+# endif
+
+
 void virAllocTestInit(void);
 int virAllocTestCount(void);
 void virAllocTestOOM(int n, int m);
diff --git a/tests/viralloctest.c b/tests/viralloctest.c
index 8c0826f..dd54f81 100644
--- a/tests/viralloctest.c
+++ b/tests/viralloctest.c
@@ -384,6 +384,41 @@ testInsertArray(const void *opaque ATTRIBUTE_UNUSED)


 static int
+testDispose(const void *opaque ATTRIBUTE_UNUSED)
+{
+    int *num = NULL;
+    int *nums = NULL;
+    size_t nnums = 0;
+    char *str = NULL;
+
+    VIR_DISPOSE(num);
+    VIR_DISPOSE_N(nums, nnums);
+    VIR_DISPOSE_STRING(str);
+
+    nnums = 10;
+    VIR_DISPOSE_N(nums, nnums);
+
+    if (VIR_ALLOC(num) < 0)
+        return -1;
+
+    VIR_DISPOSE(num);
+
+    nnums = 10;
+    if (VIR_ALLOC_N(nums, nnums) < 0)
+        return -1;
+
+    VIR_DISPOSE_N(nums, nnums);
+
+    if (VIR_STRDUP(str, "test") < 0)
+        return -1;
+
+    VIR_DISPOSE_STRING(str);
+
+    return 0;
+}
+
+
+static int
 mymain(void)
 {
     int ret = 0;
@@ -400,6 +435,8 @@ mymain(void)
         ret = -1;
     if (virtTestRun("insert array", testInsertArray, NULL) < 0)
         ret = -1;
+    if (virtTestRun("dispose tests", testDispose, NULL) < 0)
+        ret = -1;

     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-- 
2.8.2




More information about the libvir-list mailing list