• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 #include <sys/prctl.h>
19 
20 #include "platform/bionic/malloc.h"
21 #include "platform/bionic/mte.h"
22 #include "utils.h"
23 
24 #include <bionic/malloc_tagged_pointers.h>
25 
KernelSupportsTaggedPointers()26 static bool KernelSupportsTaggedPointers() {
27 #ifdef __aarch64__
28 #define PR_SET_TAGGED_ADDR_CTRL 55
29 #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
30   int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
31   return res >= 0 && res & PR_TAGGED_ADDR_ENABLE;
32 #else
33   return false;
34 #endif
35 }
36 
TEST(tagged_pointers,check_tagged_pointer_dies)37 TEST(tagged_pointers, check_tagged_pointer_dies) {
38   if (!KernelSupportsTaggedPointers()) {
39     GTEST_SKIP() << "Kernel doesn't support tagged pointers.";
40   }
41 
42 #ifdef __aarch64__
43   if (mte_supported()) {
44     GTEST_SKIP() << "Tagged pointers are not used on MTE hardware.";
45   }
46 
47   void *x = malloc(1);
48 
49   // Ensure that `x` has a pointer tag.
50   EXPECT_NE(reinterpret_cast<uintptr_t>(x) >> 56, 0u);
51 
52   x = untag_address(x);
53   EXPECT_DEATH(free(x), "Pointer tag for 0x[a-zA-Z0-9]* was truncated");
54 
55   HeapTaggingLevel tag_level = M_HEAP_TAGGING_LEVEL_TBI;
56   EXPECT_TRUE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level)));
57   EXPECT_DEATH(free(untag_address(malloc(1))), "Pointer tag for 0x[a-zA-Z0-9]* was truncated");
58 
59   tag_level = M_HEAP_TAGGING_LEVEL_ASYNC;
60   EXPECT_FALSE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level)));
61 
62   x = malloc(1);
63   void *y = malloc(1);
64   // Disable heap tagging.
65   tag_level = M_HEAP_TAGGING_LEVEL_NONE;
66   EXPECT_TRUE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level)));
67   // Ensure an older tagged pointer can still be freed.
68   free(x);
69   // Tag mismatch is not detected on old pointers.
70   free(untag_address(y));
71   // New pointers are not tagged.
72   x = malloc(1);
73   EXPECT_EQ(untag_address(x), x);
74   free(x);
75 
76   // Switching back to checked mode is not possible.
77   tag_level = M_HEAP_TAGGING_LEVEL_TBI;
78   EXPECT_FALSE(android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &tag_level, sizeof(tag_level)));
79   // We remain in the unchecked mode.
80   x = malloc(1);
81   EXPECT_EQ(untag_address(x), x);
82   free(x);
83 #endif // defined(__aarch64__)
84 }
85