Merge pull request #1162 from gabor-mezei-arm/buffer_sharing_copy_output_buffer
Add allocate and copy style output buffer protection
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 36baa3b..0cb208e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -297,6 +297,8 @@
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)
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index 0778731..5a26821 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -78,6 +78,9 @@
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)
diff --git a/programs/test/metatest.c b/programs/test/metatest.c
index 392b638..79c57d1 100644
--- a/programs/test/metatest.c
+++ b/programs/test/metatest.c
@@ -362,22 +362,22 @@
{ "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 },
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 0869aaa..188d5d5 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -251,6 +251,8 @@
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.")
diff --git a/tests/include/test/memory.h b/tests/include/test/memory.h
index c22ef53..20fd8d3 100644
--- a/tests/include/test/memory.h
+++ b/tests/include/test/memory.h
@@ -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_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))
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 4465d05..0daab09 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1125,7 +1125,7 @@
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 @@
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
diff --git a/tests/src/test_memory.c b/tests/src/test_memory.c
index c277be8..ac9dde6 100644
--- a/tests/src/test_memory.c
+++ b/tests/src/test_memory.c
@@ -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 @@
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 @@
align_for_asan(&ptr, &size);
__asan_unpoison_memory_region(ptr, size);
}
-#endif /* Asan */
+#endif /* Memory poisoning */