Merge pull request #1141 from davidhorstmann-arm/memory-poisoning-runtime-enable

Enable and disable memory poisoning at runtime
This commit is contained in:
David Horstmann 2024-01-24 14:46:43 +00:00 committed by GitHub
commit 9c5c9c351d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 54 additions and 24 deletions

View File

@ -297,6 +297,8 @@ if(ENABLE_TESTING OR ENABLE_PROGRAMS)
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library)
# Request C11, needed for memory poisoning tests
set_target_properties(mbedtls_test PROPERTIES C_STANDARD 11)
file(GLOB MBEDTLS_TEST_HELPER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_helpers/*.c)

View File

@ -78,6 +78,9 @@ foreach(exe IN LISTS executables_libs executables_mbedcrypto)
target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
endif()
# Request C11, required for memory poisoning
set_target_properties(${exe} PROPERTIES C_STANDARD 11)
# This emulates "if ( ... IN_LIST ... )" which becomes available in CMake 3.3
list(FIND executables_libs ${exe} exe_index)
if (${exe_index} GREATER -1)

View File

@ -362,22 +362,22 @@ 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_r", "asan", test_memory_poison },
{ "test_memory_poison_0_0_8_w", "asan", test_memory_poison },
{ "test_memory_poison_0_7_8_r", "asan", test_memory_poison },
{ "test_memory_poison_0_7_8_w", "asan", test_memory_poison },
{ "test_memory_poison_0_0_1_r", "asan", test_memory_poison },
{ "test_memory_poison_0_0_1_w", "asan", test_memory_poison },
{ "test_memory_poison_0_1_2_r", "asan", test_memory_poison },
{ "test_memory_poison_0_1_2_w", "asan", test_memory_poison },
{ "test_memory_poison_7_0_8_r", "asan", test_memory_poison },
{ "test_memory_poison_7_0_8_w", "asan", test_memory_poison },
{ "test_memory_poison_7_7_8_r", "asan", test_memory_poison },
{ "test_memory_poison_7_7_8_w", "asan", test_memory_poison },
{ "test_memory_poison_7_0_1_r", "asan", test_memory_poison },
{ "test_memory_poison_7_0_1_w", "asan", test_memory_poison },
{ "test_memory_poison_7_1_2_r", "asan", test_memory_poison },
{ "test_memory_poison_7_1_2_w", "asan", test_memory_poison },
{ "test_memory_poison_0_0_8_r", "poison", test_memory_poison },
{ "test_memory_poison_0_0_8_w", "poison", test_memory_poison },
{ "test_memory_poison_0_7_8_r", "poison", test_memory_poison },
{ "test_memory_poison_0_7_8_w", "poison", test_memory_poison },
{ "test_memory_poison_0_0_1_r", "poison", test_memory_poison },
{ "test_memory_poison_0_0_1_w", "poison", test_memory_poison },
{ "test_memory_poison_0_1_2_r", "poison", test_memory_poison },
{ "test_memory_poison_0_1_2_w", "poison", test_memory_poison },
{ "test_memory_poison_7_0_8_r", "poison", test_memory_poison },
{ "test_memory_poison_7_0_8_w", "poison", test_memory_poison },
{ "test_memory_poison_7_7_8_r", "poison", test_memory_poison },
{ "test_memory_poison_7_7_8_w", "poison", test_memory_poison },
{ "test_memory_poison_7_0_1_r", "poison", test_memory_poison },
{ "test_memory_poison_7_0_1_w", "poison", test_memory_poison },
{ "test_memory_poison_7_1_2_r", "poison", test_memory_poison },
{ "test_memory_poison_7_1_2_w", "poison", 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 },

View File

@ -251,6 +251,8 @@ function(add_test_suite suite_name)
target_include_directories(test_suite_${data_name}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../library)
# Request C11, which is needed for memory poisoning tests
set_target_properties(test_suite_${data_name} PROPERTIES C_STANDARD 11)
if(${data_name} MATCHES ${SKIP_TEST_SUITES_REGEX})
message(STATUS "The test suite ${data_name} will not be executed.")

View File

@ -22,9 +22,12 @@
* memory as poisoned, which can be used to enforce some memory access
* policies.
*
* Support for the C11 thread_local keyword is also required.
*
* Currently, only Asan (Address Sanitizer) is supported.
*/
#if defined(MBEDTLS_TEST_HAVE_ASAN)
#if defined(MBEDTLS_TEST_HAVE_ASAN) && \
(__STDC_VERSION__ >= 201112L)
# define MBEDTLS_TEST_MEMORY_CAN_POISON
#endif
@ -62,6 +65,12 @@
#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
/** Thread-local variable used to enable memory poisoning. This is set and
* unset in the test wrappers so that calls to PSA functions from the library
* do not poison memory.
*/
extern _Thread_local unsigned int mbedtls_test_memory_poisoning_count;
/** Poison a memory area so that any attempt to read or write from it will
* cause a runtime failure.
*
@ -69,7 +78,10 @@
*/
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)
do { \
mbedtls_test_memory_poisoning_count++; \
mbedtls_test_memory_poison(ptr, size); \
} while (0)
/** Undo the effect of mbedtls_test_memory_poison().
*
@ -80,7 +92,12 @@ void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size);
*/
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)
do { \
mbedtls_test_memory_unpoison(ptr, size); \
if (mbedtls_test_memory_poisoning_count != 0) { \
mbedtls_test_memory_poisoning_count--; \
} \
} while (0)
#else /* MBEDTLS_TEST_MEMORY_CAN_POISON */
#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) ((void) (ptr), (void) (size))

View File

@ -1125,7 +1125,7 @@ component_test_default_cmake_gcc_asan () {
programs/test/selftest
msg "test: metatests (GCC, ASan build)"
tests/scripts/run-metatests.sh any asan
tests/scripts/run-metatests.sh any asan poison
msg "test: ssl-opt.sh (ASan build)" # ~ 1 min
tests/ssl-opt.sh
@ -1944,7 +1944,7 @@ component_test_everest () {
make test
msg "test: metatests (clang, ASan)"
tests/scripts/run-metatests.sh any asan
tests/scripts/run-metatests.sh any asan poison
msg "test: Everest ECDH context - ECDH-related part of ssl-opt.sh (ASan build)" # ~ 5s
tests/ssl-opt.sh -f ECDH

View File

@ -13,12 +13,15 @@
#include <test/macros.h>
#include <test/memory.h>
#if defined(MBEDTLS_TEST_HAVE_ASAN)
#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
#include <sanitizer/asan_interface.h>
#include <stdint.h>
#endif
#if defined(MBEDTLS_TEST_HAVE_ASAN)
#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
_Thread_local unsigned int mbedtls_test_memory_poisoning_count = 0;
static void align_for_asan(const unsigned char **p_ptr, size_t *p_size)
{
uintptr_t start = (uintptr_t) *p_ptr;
@ -36,6 +39,9 @@ static void align_for_asan(const unsigned char **p_ptr, size_t *p_size)
void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size)
{
if (mbedtls_test_memory_poisoning_count == 0) {
return;
}
if (size == 0) {
return;
}
@ -51,4 +57,4 @@ void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size)
align_for_asan(&ptr, &size);
__asan_unpoison_memory_region(ptr, size);
}
#endif /* Asan */
#endif /* Memory poisoning */