diff options
author | Peter Collingbourne <pcc@google.com> | 2020-04-01 19:54:48 -0700 |
---|---|---|
committer | Peter Collingbourne <pcc@google.com> | 2020-05-05 13:28:16 -0700 |
commit | d3060019de533cc1e1ccf444c80b37ebb3490c9f (patch) | |
tree | 0b8b45a1b6e7e4ec4a92bdf5c1bb2c8ed5752dcf | |
parent | 514faf92c82ca4f88e4a58f771ff5e393ceec317 (diff) | |
download | bionic-d3060019de533cc1e1ccf444c80b37ebb3490c9f.tar.gz |
Introduce a new heap tagging level, M_HEAP_TAGGING_LEVEL_SYNC.
The SYNC tagging level enables stack trace collection for allocations and
deallocations, which allows allocation and deallocation stack traces to
appear in tombstones when encountering a tag check fault in synchronous tag
checking mode.
Bug: 135772972
Change-Id: Ibda9f51b29d2c8e2c993fc74425dea7bfa23ab1e
-rw-r--r-- | libc/bionic/heap_tagging.cpp | 47 | ||||
-rw-r--r-- | libc/bionic/malloc_common_dynamic.cpp | 8 | ||||
-rw-r--r-- | libc/platform/bionic/malloc.h | 2 | ||||
-rw-r--r-- | libc/private/bionic_globals.h | 3 | ||||
-rw-r--r-- | linker/linker_debuggerd_android.cpp | 2 | ||||
-rw-r--r-- | tests/Android.bp | 4 | ||||
-rw-r--r-- | tests/heap_tagging_level_test.cpp | 202 | ||||
-rw-r--r-- | tests/malloc_test.cpp | 66 | ||||
-rw-r--r-- | tests/tagged_pointers_test.cpp | 84 |
9 files changed, 248 insertions, 170 deletions
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp index e5e8ec3f1..c3aa82317 100644 --- a/libc/bionic/heap_tagging.cpp +++ b/libc/bionic/heap_tagging.cpp @@ -34,13 +34,12 @@ #include <platform/bionic/mte_kernel.h> extern "C" void scudo_malloc_disable_memory_tagging(); +extern "C" void scudo_malloc_set_track_allocation_stacks(int); static HeapTaggingLevel heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE; void SetDefaultHeapTaggingLevel() { #if defined(__aarch64__) -#define PR_SET_TAGGED_ADDR_CTRL 55 -#define PR_TAGGED_ADDR_ENABLE (1UL << 0) #ifdef ANDROID_EXPERIMENTAL_MTE // First, try enabling MTE in asynchronous mode, with tag 0 excluded. This will fail if the kernel // or hardware doesn't support MTE, and we will fall back to just enabling tagged pointers in @@ -81,34 +80,48 @@ bool SetHeapTaggingLevel(void* arg, size_t arg_size) { switch (tag_level) { case M_HEAP_TAGGING_LEVEL_NONE: +#if defined(USE_SCUDO) + scudo_malloc_disable_memory_tagging(); +#endif + if (heap_tagging_level == M_HEAP_TAGGING_LEVEL_TBI) { + __libc_globals.mutate([](libc_globals* globals) { + // Preserve the untag mask (we still want to untag pointers when passing them to the + // allocator), but clear the fixed tag and the check mask, so that pointers are no longer + // tagged and checks no longer happen. + globals->heap_pointer_tag = static_cast<uintptr_t>(0xffull << UNTAG_SHIFT); + }); + } break; case M_HEAP_TAGGING_LEVEL_TBI: case M_HEAP_TAGGING_LEVEL_ASYNC: + case M_HEAP_TAGGING_LEVEL_SYNC: if (heap_tagging_level == M_HEAP_TAGGING_LEVEL_NONE) { error_log( "SetHeapTaggingLevel: re-enabling tagging after it was disabled is not supported"); - } else { - error_log("SetHeapTaggingLevel: switching between TBI and ASYNC is not supported"); + return false; + } else if (tag_level == M_HEAP_TAGGING_LEVEL_TBI || + heap_tagging_level == M_HEAP_TAGGING_LEVEL_TBI) { + error_log("SetHeapTaggingLevel: switching between TBI and ASYNC/SYNC is not supported"); + return false; } - return false; + + if (tag_level == M_HEAP_TAGGING_LEVEL_ASYNC) { +#if defined(USE_SCUDO) + scudo_malloc_set_track_allocation_stacks(0); +#endif + } else if (tag_level == M_HEAP_TAGGING_LEVEL_ASYNC) { +#if defined(USE_SCUDO) + scudo_malloc_set_track_allocation_stacks(1); +#endif + } + break; default: error_log("SetHeapTaggingLevel: unknown tagging level"); return false; } + heap_tagging_level = tag_level; info_log("SetHeapTaggingLevel: tag level set to %d", tag_level); - if (heap_tagging_level == M_HEAP_TAGGING_LEVEL_NONE) { -#if defined(USE_SCUDO) - scudo_malloc_disable_memory_tagging(); -#endif - __libc_globals.mutate([](libc_globals* globals) { - // Preserve the untag mask (we still want to untag pointers when passing them to the - // allocator if we were doing so before), but clear the fixed tag and the check mask, - // so that pointers are no longer tagged and checks no longer happen. - globals->heap_pointer_tag &= 0xffull << UNTAG_SHIFT; - }); - } - return true; } diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp index da87c332e..6a82ae3a5 100644 --- a/libc/bionic/malloc_common_dynamic.cpp +++ b/libc/bionic/malloc_common_dynamic.cpp @@ -366,6 +366,9 @@ static bool InstallHooks(libc_globals* globals, const char* options, const char* return true; } +extern "C" const char* __scudo_get_stack_depot_addr(); +extern "C" const char* __scudo_get_region_info_addr(); + // Initializes memory allocation framework once per process. static void MallocInitImpl(libc_globals* globals) { char prop[PROP_VALUE_MAX]; @@ -373,6 +376,11 @@ static void MallocInitImpl(libc_globals* globals) { MaybeInitGwpAsanFromLibc(globals); +#if defined(USE_SCUDO) + __libc_shared_globals()->scudo_stack_depot = __scudo_get_stack_depot_addr(); + __libc_shared_globals()->scudo_region_info = __scudo_get_region_info_addr(); +#endif + // Prefer malloc debug since it existed first and is a more complete // malloc interceptor than the hooks. bool hook_installed = false; diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h index 0ea7e3c12..f9eb03f33 100644 --- a/libc/platform/bionic/malloc.h +++ b/libc/platform/bionic/malloc.h @@ -116,6 +116,8 @@ enum HeapTaggingLevel { M_HEAP_TAGGING_LEVEL_TBI = 1, // Enable heap tagging if supported, at a level appropriate for asynchronous memory tag checks. M_HEAP_TAGGING_LEVEL_ASYNC = 2, + // Enable heap tagging if supported, at a level appropriate for synchronous memory tag checks. + M_HEAP_TAGGING_LEVEL_SYNC = 3, }; // Manipulates bionic-specific handling of memory allocation APIs such as diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h index 54605dbf3..5c9b726d2 100644 --- a/libc/private/bionic_globals.h +++ b/libc/private/bionic_globals.h @@ -103,6 +103,9 @@ struct libc_shared_globals { const gwp_asan::AllocatorState* gwp_asan_state = nullptr; const gwp_asan::AllocationMetadata* gwp_asan_metadata = nullptr; + + const char* scudo_stack_depot = nullptr; + const char* scudo_region_info = nullptr; }; __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals(); diff --git a/linker/linker_debuggerd_android.cpp b/linker/linker_debuggerd_android.cpp index 6a816736f..203e44159 100644 --- a/linker/linker_debuggerd_android.cpp +++ b/linker/linker_debuggerd_android.cpp @@ -40,6 +40,8 @@ static debugger_process_info get_process_info() { .fdsan_table = &__libc_shared_globals()->fd_table, .gwp_asan_state = __libc_shared_globals()->gwp_asan_state, .gwp_asan_metadata = __libc_shared_globals()->gwp_asan_metadata, + .scudo_stack_depot = __libc_shared_globals()->scudo_stack_depot, + .scudo_region_info = __libc_shared_globals()->scudo_region_info, }; } #endif diff --git a/tests/Android.bp b/tests/Android.bp index c75108483..1f45595f2 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -117,6 +117,7 @@ cc_test_library { "glob_test.cpp", "grp_pwd_test.cpp", "grp_pwd_file_test.cpp", + "heap_tagging_level_test.cpp", "iconv_test.cpp", "ifaddrs_test.cpp", "ifunc_test.cpp", @@ -231,9 +232,6 @@ cc_test_library { "libprocinfo", "libsystemproperties", ], - srcs: [ - "tagged_pointers_test.cpp", - ], }, }, diff --git a/tests/heap_tagging_level_test.cpp b/tests/heap_tagging_level_test.cpp new file mode 100644 index 000000000..05123fde2 --- /dev/null +++ b/tests/heap_tagging_level_test.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> +#include <sys/prctl.h> + +#if defined(__BIONIC__) +#include "platform/bionic/malloc.h" +#include "platform/bionic/mte.h" +#include "utils.h" + +#include "SignalUtils.h" + +#include <bionic/malloc_tagged_pointers.h> + +static bool KernelSupportsTaggedPointers() { +#ifdef __aarch64__ + int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0); + return res >= 0 && res & PR_TAGGED_ADDR_ENABLE; +#else + return false; +#endif +} + +static bool SetHeapTaggingLevel(HeapTaggingLevel level) { + return android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &level, sizeof(level)); +} +#endif + +TEST(heap_tagging_level, tagged_pointer_dies) { +#if defined(__BIONIC__) + if (!KernelSupportsTaggedPointers()) { + GTEST_SKIP() << "Kernel doesn't support tagged pointers."; + } + +#ifdef __aarch64__ + if (mte_supported()) { + GTEST_SKIP() << "Tagged pointers are not used on MTE hardware."; + } + + void *x = malloc(1); + + // Ensure that `x` has a pointer tag. + EXPECT_NE(reinterpret_cast<uintptr_t>(x) >> 56, 0u); + + x = untag_address(x); + EXPECT_DEATH(free(x), "Pointer tag for 0x[a-zA-Z0-9]* was truncated"); + + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_TBI)); + EXPECT_DEATH(free(untag_address(malloc(1))), "Pointer tag for 0x[a-zA-Z0-9]* was truncated"); + + x = malloc(1); + void *y = malloc(1); + // Disable heap tagging. + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_NONE)); + // Ensure an older tagged pointer can still be freed. + free(x); + // Tag mismatch is not detected on old pointers. + free(untag_address(y)); +#endif // defined(__aarch64__) +#else + GTEST_SKIP() << "bionic-only test"; +#endif // defined(__BIONIC__) +} + +#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(heap_tagging_level, sync_async_bad_accesses_die) { +#if defined(__BIONIC__) && defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE) + if (!(getauxval(AT_HWCAP2) & HWCAP2_MTE)) { + GTEST_SKIP() << "requires MTE support"; + } + + 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]; +#endif +} + +TEST(heap_tagging_level, none_pointers_untagged) { +#if defined(__BIONIC__) +#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE) + EXPECT_TRUE(SetTagCheckingLevel(PR_MTE_TCF_NONE)); +#endif + + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_NONE)); + std::unique_ptr<int[]> p = std::make_unique<int[]>(4); + EXPECT_EQ(untag_address(p.get()), p.get()); +#else + GTEST_SKIP() << "bionic-only test"; +#endif +} + +TEST(heap_tagging_level, tagging_level_transitions) { +#if defined(__BIONIC__) && defined(__aarch64__) + if (!KernelSupportsTaggedPointers()) { + GTEST_SKIP() << "Kernel doesn't support tagged pointers."; + } + +#if defined(ANDROID_EXPERIMENTAL_MTE) + EXPECT_TRUE(SetTagCheckingLevel(PR_MTE_TCF_NONE)); +#endif + + EXPECT_FALSE(SetHeapTaggingLevel(static_cast<HeapTaggingLevel>(12345))); + + if (mte_supported()) { + // ASYNC -> ... + EXPECT_FALSE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_TBI)); + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC)); + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_SYNC)); + + // SYNC -> ... + EXPECT_FALSE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_TBI)); + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_SYNC)); + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC)); + } else { + // TBI -> ... + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_TBI)); + EXPECT_FALSE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC)); + EXPECT_FALSE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_SYNC)); + } + + // TBI -> NONE on non-MTE, ASYNC -> NONE on MTE. + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_NONE)); + + // NONE -> ... + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_NONE)); + EXPECT_FALSE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_TBI)); + EXPECT_FALSE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC)); + EXPECT_FALSE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_SYNC)); +#else + GTEST_SKIP() << "bionic/arm64 only"; +#endif +} + +TEST(heap_tagging_level, tagging_level_transition_sync_none) { +#if defined(__BIONIC__) && defined(__aarch64__) + // We can't test SYNC -> NONE in tagging_level_transitions because we can only make one transition + // to NONE (which we use to test ASYNC -> NONE), so we test it here separately. + if (!mte_supported()) { + GTEST_SKIP() << "requires MTE support"; + } + +#if defined(ANDROID_EXPERIMENTAL_MTE) + EXPECT_TRUE(SetTagCheckingLevel(PR_MTE_TCF_NONE)); +#endif + + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_SYNC)); + EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_NONE)); +#else + GTEST_SKIP() << "bionic/arm64 only"; +#endif +} diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp index a2f310e2b..47a90332e 100644 --- a/tests/malloc_test.cpp +++ b/tests/malloc_test.cpp @@ -1201,69 +1201,3 @@ 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"; - } - - 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 -} diff --git a/tests/tagged_pointers_test.cpp b/tests/tagged_pointers_test.cpp deleted file mode 100644 index 56d10374d..000000000 --- a/tests/tagged_pointers_test.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> -#include <sys/prctl.h> - -#include "platform/bionic/malloc.h" -#include "platform/bionic/mte.h" -#include "utils.h" - -#include <bionic/malloc_tagged_pointers.h> - -static bool KernelSupportsTaggedPointers() { -#ifdef __aarch64__ -#define PR_SET_TAGGED_ADDR_CTRL 55 -#define PR_TAGGED_ADDR_ENABLE (1UL << 0) - int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0); - return res >= 0 && res & PR_TAGGED_ADDR_ENABLE; -#else - return false; -#endif -} - -TEST(tagged_pointers, check_tagged_pointer_dies) { - if (!KernelSupportsTaggedPointers()) { - GTEST_SKIP() << "Kernel doesn't support tagged pointers."; - } - -#ifdef __aarch64__ - if (mte_supported()) { - GTEST_SKIP() << "Tagged pointers are not used on MTE hardware."; - } - - void *x = malloc(1); - - // Ensure that `x` has a pointer tag. - EXPECT_NE(reinterpret_cast<uintptr_t>(x) >> 56, 0u); - - x = untag_address(x); - EXPECT_DEATH(free(x), "Pointer tag for 0x[a-zA-Z0-9]* was truncated"); - - HeapTaggingLevel tag_level = M_HEAP_TAGGING_LEVEL_TBI; - EXPECT_TRUE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level))); - EXPECT_DEATH(free(untag_address(malloc(1))), "Pointer tag for 0x[a-zA-Z0-9]* was truncated"); - - tag_level = M_HEAP_TAGGING_LEVEL_ASYNC; - EXPECT_FALSE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level))); - - x = malloc(1); - void *y = malloc(1); - // Disable heap tagging. - tag_level = M_HEAP_TAGGING_LEVEL_NONE; - EXPECT_TRUE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level))); - // Ensure an older tagged pointer can still be freed. - free(x); - // Tag mismatch is not detected on old pointers. - free(untag_address(y)); - // New pointers are not tagged. - x = malloc(1); - EXPECT_EQ(untag_address(x), x); - free(x); - - // Switching back to checked mode is not possible. - tag_level = M_HEAP_TAGGING_LEVEL_TBI; - EXPECT_FALSE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level))); - // We remain in the unchecked mode. - x = malloc(1); - EXPECT_EQ(untag_address(x), x); - free(x); -#endif // defined(__aarch64__) -} |