mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
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:
parent
ced1e846a0
commit
eb2116fd9a
@ -1127,6 +1127,7 @@ virAllocTestInit;
|
||||
virAllocTestOOM;
|
||||
virAllocVar;
|
||||
virDeleteElementsN;
|
||||
virDispose;
|
||||
virExpandN;
|
||||
virFree;
|
||||
virInsertElementsN;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user