mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-01-30 06:33:06 +00:00
Add memory poisoning framework
While an area of memory is poisoned, reading or writing from it triggers a sanitizer violation. Implemented for ASan. Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
parent
3fd3d05196
commit
d29cce91d0
@ -32,6 +32,7 @@
|
||||
#include <mbedtls/platform_util.h>
|
||||
#include "test/helpers.h"
|
||||
#include "test/macros.h"
|
||||
#include "test/memory.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -143,6 +144,45 @@ void memory_leak(const char *name)
|
||||
/* Leak of a heap object */
|
||||
}
|
||||
|
||||
/* name = "test_memory_poison_%(start)_%(offset)_%(count)"
|
||||
* Poison a region starting at start from an 8-byte aligned origin,
|
||||
* encompassing count bytes. Access the region at offset from the start.
|
||||
*/
|
||||
void test_memory_poison(const char *name)
|
||||
{
|
||||
size_t start = 0, offset = 0, count = 0;
|
||||
if (sscanf(name, "%*[^0-9]%zu%*[^0-9]%zu%*[^0-9]%zu",
|
||||
&start, &offset, &count) != 3) {
|
||||
mbedtls_fprintf(stderr, "%s: Bad name format: %s\n", __func__, name);
|
||||
return;
|
||||
}
|
||||
|
||||
union {
|
||||
long long ll;
|
||||
unsigned char buf[32];
|
||||
} aligned;
|
||||
memset(aligned.buf, 'a', sizeof(aligned.buf));
|
||||
|
||||
if (start > sizeof(aligned.buf)) {
|
||||
mbedtls_fprintf(stderr, "%s: start=%zu > size=%zu", __func__,
|
||||
start, sizeof(aligned.buf));
|
||||
return;
|
||||
}
|
||||
if (start + count > sizeof(aligned.buf)) {
|
||||
mbedtls_fprintf(stderr, "%s: start+count=%zu > size=%zu", __func__,
|
||||
start + count, sizeof(aligned.buf));
|
||||
return;
|
||||
}
|
||||
if (offset >= count) {
|
||||
mbedtls_fprintf(stderr, "%s: offset=%zu >= count=%zu", __func__,
|
||||
offset, count);
|
||||
return;
|
||||
}
|
||||
|
||||
MBEDTLS_TEST_MEMORY_POISON(aligned.buf + start, count);
|
||||
mbedtls_printf("%u\n", (unsigned) aligned.buf[start + offset]);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* Threading */
|
||||
@ -291,6 +331,7 @@ metatest_t metatests[] = {
|
||||
{ "double_free", "asan", double_free },
|
||||
{ "read_uninitialized_stack", "msan", read_uninitialized_stack },
|
||||
{ "memory_leak", "asan", memory_leak },
|
||||
{ "test_memory_poison_0_0_8", "asan", test_memory_poison },
|
||||
{ "mutex_lock_not_initialized", "pthread", mutex_lock_not_initialized },
|
||||
{ "mutex_unlock_not_initialized", "pthread", mutex_unlock_not_initialized },
|
||||
{ "mutex_free_not_initialized", "pthread", mutex_free_not_initialized },
|
||||
|
@ -15,4 +15,79 @@
|
||||
#include "mbedtls/build_info.h"
|
||||
#include "mbedtls/platform.h"
|
||||
|
||||
/** \def MBEDTLS_TEST_MEMORY_CAN_POISON
|
||||
*
|
||||
* This macro is defined if the tests are compiled with a method to mark
|
||||
* memory as poisoned, which can be used to enforce some memory access
|
||||
* policies.
|
||||
*
|
||||
* Currently, only Asan (Address Sanitizer) is supported.
|
||||
*/
|
||||
#if defined(__SANITIZE_ADDRESS__)
|
||||
# define MBEDTLS_TEST_HAVE_ASAN
|
||||
#endif
|
||||
#if defined(__has_feature)
|
||||
# if __has_feature(address_sanitizer)
|
||||
# define MBEDTLS_TEST_HAVE_ASAN
|
||||
# endif
|
||||
#endif
|
||||
#if defined(MBEDTLS_TEST_HAVE_ASAN)
|
||||
# define MBEDTLS_TEST_MEMORY_CAN_POISON
|
||||
#endif
|
||||
|
||||
/** \def MBEDTLS_TEST_MEMORY_POISON(buf, size)
|
||||
*
|
||||
* Poison a memory area so that any attempt to read or write from it will
|
||||
* cause a runtime failure.
|
||||
*
|
||||
* The behavior is undefined if any part of the memory area is invalid.
|
||||
*
|
||||
* This is a no-op in builds without a poisoning method.
|
||||
* See #MBEDTLS_TEST_MEMORY_CAN_POISON.
|
||||
*
|
||||
* \param buf Pointer to the beginning of the memory area to poison.
|
||||
* \param size Size of the memory area in bytes.
|
||||
*/
|
||||
|
||||
/** \def MBEDTLS_TEST_MEMORY_UNPOISON(buf, size)
|
||||
*
|
||||
* Undo the effect of #MBEDTLS_TEST_MEMORY_POISON.
|
||||
*
|
||||
* The behavior is undefined if any part of the memory area is invalid,
|
||||
* or if the memory area contains a mixture of poisoned and unpoisoned parts.
|
||||
*
|
||||
* This is a no-op in builds without a poisoning method.
|
||||
* See #MBEDTLS_TEST_MEMORY_CAN_POISON.
|
||||
*
|
||||
* \param buf Pointer to the beginning of the memory area to unpoison.
|
||||
* \param size Size of the memory area in bytes.
|
||||
*/
|
||||
|
||||
#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
|
||||
|
||||
/** Poison a memory area so that any attempt to read or write from it will
|
||||
* cause a runtime failure.
|
||||
*
|
||||
* The behavior is undefined if any part of the memory area is invalid.
|
||||
*/
|
||||
void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size);
|
||||
#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) \
|
||||
mbedtls_test_memory_poison(ptr, size)
|
||||
|
||||
/** Undo the effect of mbedtls_test_memory_poison().
|
||||
*
|
||||
* This is a no-op if the given area is entirely valid, unpoisoned memory.
|
||||
*
|
||||
* The behavior is undefined if any part of the memory area is invalid,
|
||||
* or if the memory area contains a mixture of poisoned and unpoisoned parts.
|
||||
*/
|
||||
void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size);
|
||||
#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) \
|
||||
mbedtls_test_memory_unpoison(ptr, size)
|
||||
|
||||
#else /* MBEDTLS_TEST_MEMORY_CAN_POISON */
|
||||
#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) ((void) 0)
|
||||
#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) ((void) 0)
|
||||
#endif /* MBEDTLS_TEST_MEMORY_CAN_POISON */
|
||||
|
||||
#endif /* TEST_MEMORY_H */
|
||||
|
@ -13,3 +13,25 @@
|
||||
#include <test/macros.h>
|
||||
#include <test/memory.h>
|
||||
|
||||
#if defined(MBEDTLS_TEST_HAVE_ASAN)
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_TEST_HAVE_ASAN)
|
||||
void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size)
|
||||
{
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
__asan_poison_memory_region(ptr, size);
|
||||
}
|
||||
|
||||
void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size)
|
||||
{
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
__asan_unpoison_memory_region(ptr, size);
|
||||
}
|
||||
#endif /* Asan */
|
||||
|
Loading…
x
Reference in New Issue
Block a user