util: alloc: Introduce freeing helpers that clear the memory before freeing

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.
This commit is contained in:
Peter Krempa 2016-05-13 14:59:01 +02:00
parent ced1e846a0
commit eb2116fd9a
4 changed files with 130 additions and 0 deletions

View File

@ -1127,6 +1127,7 @@ virAllocTestInit;
virAllocTestOOM;
virAllocVar;
virDeleteElementsN;
virDispose;
virExpandN;
virFree;
virInsertElementsN;

View 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;
}

View 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);

View 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;
}