]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: alloc: Introduce freeing helpers that clear the memory before freeing
authorPeter Krempa <pkrempa@redhat.com>
Fri, 13 May 2016 12:59:01 +0000 (14:59 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 16 May 2016 10:58:48 +0000 (12:58 +0200)
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
src/util/viralloc.c
src/util/viralloc.h
tests/viralloctest.c

index fb248085904fed499818efdf8b53b07c3b35719c..87d758129de216f9c10c2bd6dcb17959b29e1364 100644 (file)
@@ -1127,6 +1127,7 @@ virAllocTestInit;
 virAllocTestOOM;
 virAllocVar;
 virDeleteElementsN;
+virDispose;
 virExpandN;
 virFree;
 virInsertElementsN;
index 63f43d03e11c5b6f3dfb11d97bbb8d64575e2323..812aa5b3f946a186efd58c994aef0e3f55fcb225 100644 (file)
@@ -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;
+}
index bf85c168246c8c2bf6d343ae0c80304f31eeb92b..5f4e27bb80018186434c7a84f280e4d218d41e53 100644 (file)
@@ -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);
index 8c0826faae9fa0f4183b1985c3d9d8eb2ceb45cf..dd54f8186a2b8b6023e64058b7bd77139603fbd1 100644 (file)
@@ -383,6 +383,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)
 {
@@ -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;
 }