summaryrefslogtreecommitdiff
path: root/tests/malloc_test.cpp
diff options
context:
space:
mode:
authorPeter Collingbourne <pcc@google.com>2020-02-21 00:59:32 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2020-02-21 00:59:32 +0000
commit935aae907c614b7cbebfd9f18566a70742817eb2 (patch)
tree4ee0208b8fbaca35f06cd862dab8c72aaf2694d1 /tests/malloc_test.cpp
parent9ed719e16757d203e450fa3ca63761e7731652e1 (diff)
parent45819dde10da8fb28a4ce9e6fc17f852839cd2c9 (diff)
Merge "Allow android_mallopt(M_SET_HEAP_TAGGING_LEVEL) to control scudo heap tagging."
Diffstat (limited to 'tests/malloc_test.cpp')
-rw-r--r--tests/malloc_test.cpp72
1 files changed, 72 insertions, 0 deletions
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 4da6d3f4d..594441487 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -25,6 +25,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -40,7 +42,10 @@
#if defined(__BIONIC__)
+#include "SignalUtils.h"
+
#include "platform/bionic/malloc.h"
+#include "platform/bionic/mte_kernel.h"
#include "platform/bionic/reserved_signals.h"
#include "private/bionic_config.h"
@@ -1196,3 +1201,70 @@ TEST(android_mallopt, set_allocation_limit_multiple_threads) {
GTEST_SKIP() << "bionic extension";
#endif
}
+
+#if defined(__BIONIC__) && defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+template <int SiCode> void CheckSiCode(int, siginfo_t* info, void*) {
+ if (info->si_code != SiCode) {
+ _exit(2);
+ }
+ _exit(1);
+}
+
+static bool SetTagCheckingLevel(int level) {
+ int tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+ if (tagged_addr_ctrl < 0) {
+ return false;
+ }
+
+ tagged_addr_ctrl = (tagged_addr_ctrl & ~PR_MTE_TCF_MASK) | level;
+ return prctl(PR_SET_TAGGED_ADDR_CTRL, tagged_addr_ctrl, 0, 0, 0) == 0;
+}
+#endif
+
+TEST(android_mallopt, tag_level) {
+#if defined(__BIONIC__) && defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+ if (!(getauxval(AT_HWCAP2) & HWCAP2_MTE)) {
+ GTEST_SKIP() << "requires MTE support";
+ return;
+ }
+
+ std::unique_ptr<int[]> p = std::make_unique<int[]>(4);
+
+ // First, check that memory tagging is enabled and the default tag checking level is async.
+ // We assume that scudo is used on all MTE enabled hardware; scudo inserts a header with a
+ // mismatching tag before each allocation.
+ EXPECT_EXIT(
+ {
+ ScopedSignalHandler ssh(SIGSEGV, CheckSiCode<SEGV_MTEAERR>, SA_SIGINFO);
+ p[-1] = 42;
+ },
+ testing::ExitedWithCode(1), "");
+
+ EXPECT_TRUE(SetTagCheckingLevel(PR_MTE_TCF_SYNC));
+ EXPECT_EXIT(
+ {
+ ScopedSignalHandler ssh(SIGSEGV, CheckSiCode<SEGV_MTESERR>, SA_SIGINFO);
+ p[-1] = 42;
+ },
+ testing::ExitedWithCode(1), "");
+
+ EXPECT_TRUE(SetTagCheckingLevel(PR_MTE_TCF_NONE));
+ volatile int oob ATTRIBUTE_UNUSED = p[-1];
+
+ HeapTaggingLevel tag_level = M_HEAP_TAGGING_LEVEL_TBI;
+ EXPECT_FALSE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level)));
+
+ tag_level = M_HEAP_TAGGING_LEVEL_NONE;
+ EXPECT_TRUE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level)));
+ std::unique_ptr<int[]> p2 = std::make_unique<int[]>(4);
+ EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(p2.get()) >> 56);
+
+ tag_level = M_HEAP_TAGGING_LEVEL_ASYNC;
+ EXPECT_FALSE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level)));
+
+ tag_level = M_HEAP_TAGGING_LEVEL_NONE;
+ EXPECT_TRUE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level)));
+#else
+ GTEST_SKIP() << "arm64 only";
+#endif
+}