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

[Backport 2.28] Enable and disable memory poisoning at runtime
diff --git a/programs/test/metatest.c b/programs/test/metatest.c
index 1724aed..a082621 100644
--- a/programs/test/metatest.c
+++ b/programs/test/metatest.c
@@ -366,22 +366,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/include/test/memory.h b/tests/include/test/memory.h
index 43fbb63..d4bbeec 100644
--- a/tests/include/test/memory.h
+++ b/tests/include/test/memory.h
@@ -61,6 +61,12 @@
 
 #if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
 
+/** 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 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.
  *
@@ -68,7 +74,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().
  *
@@ -79,7 +88,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 02513e9..81be111 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -876,7 +876,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
@@ -1497,7 +1497,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..9da7f20 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)
+
+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 */