1 /*
2 * Copyright (C) 2024 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 #if defined(__aarch64__)
17
18 #include <stdint.h>
19 #include <sys/mman.h>
20
21 #include <optional>
22
23 #include "bionic/mte.h"
24 #include "bionic/page.h"
25 #include "unwindstack/AndroidUnwinder.h"
26 #include "unwindstack/Memory.h"
27
28 #include <android-base/test_utils.h>
29 #include <procinfo/process_map.h>
30
31 #include "gtest/gtest.h"
32
33 #include "libdebuggerd/tombstone.h"
34
35 struct ScopedUnmap {
36 void* ptr;
37 size_t size;
~ScopedUnmapScopedUnmap38 ~ScopedUnmap() { munmap(ptr, size); }
39 };
40
41 class MteStackHistoryTest : public ::testing::TestWithParam<int> {
SetUp()42 void SetUp() override {
43 #if !defined(__aarch64__)
44 GTEST_SKIP();
45 #endif
46 SKIP_WITH_HWASAN;
47 unwinder.emplace();
48 unwindstack::ErrorData E;
49 ASSERT_TRUE(unwinder->Initialize(E));
50 }
51
52 protected:
53 // std::optional so we don't construct it for the SKIP cases.
54 std::optional<unwindstack::AndroidLocalUnwinder> unwinder;
55 };
56
TEST(MteStackHistoryUnwindTest,TestOne)57 TEST(MteStackHistoryUnwindTest, TestOne) {
58 #if !defined(__aarch64__)
59 GTEST_SKIP();
60 #endif
61 SKIP_WITH_HWASAN;
62 size_t size = stack_mte_ringbuffer_size(0);
63 char* data = static_cast<char*>(stack_mte_ringbuffer_allocate(0, nullptr));
64 ScopedUnmap s{data, size};
65
66 uintptr_t taggedfp = (1ULL << 56) | 1;
67 uintptr_t pc = reinterpret_cast<uintptr_t>(&memcpy);
68 memcpy(data, &pc, sizeof(pc));
69 memcpy(data + 8, &taggedfp, sizeof(taggedfp));
70
71 // The MTE TLS is at TLS - 3, so we allocate 3 placeholders.
72 void* tls[4] = {data + 16};
73
74 unwindstack::AndroidLocalUnwinder unwinder;
75 unwindstack::ErrorData E;
76 unwinder.Initialize(E);
77 StackHistoryBuffer shb;
78 dump_stack_history(&unwinder, reinterpret_cast<uintptr_t>(&tls[3]), shb, /* nounwind= */ false);
79 ASSERT_EQ(shb.entries_size(), 1);
80 const StackHistoryBufferEntry& e = shb.entries(0);
81 EXPECT_EQ(e.addr().pc(), pc);
82 EXPECT_EQ(e.addr().file_name(), "/apex/com.android.runtime/lib64/bionic/libc.so");
83 EXPECT_EQ(e.fp(), 1ULL);
84 EXPECT_EQ(e.tag(), 1ULL);
85 }
86
FindMapping(void * data)87 static std::optional<android::procinfo::MapInfo> FindMapping(void* data) {
88 std::optional<android::procinfo::MapInfo> result;
89 android::procinfo::ReadMapFile(
90 "/proc/self/maps", [&result, data](const android::procinfo::MapInfo& info) {
91 auto data_int = reinterpret_cast<uint64_t>(data) & ((1ULL << 56ULL) - 1ULL);
92 if (info.start <= data_int && data_int < info.end) {
93 result = info;
94 }
95 });
96 return result;
97 }
98
TEST_P(MteStackHistoryTest,TestFree)99 TEST_P(MteStackHistoryTest, TestFree) {
100 int size_cls = GetParam();
101 size_t size = stack_mte_ringbuffer_size(size_cls);
102 void* data = stack_mte_ringbuffer_allocate(size_cls, nullptr);
103 EXPECT_EQ(stack_mte_ringbuffer_size_from_pointer(reinterpret_cast<uintptr_t>(data)), size);
104 auto before = FindMapping(data);
105 ASSERT_TRUE(before.has_value());
106 EXPECT_EQ(before->end - before->start, size);
107 stack_mte_free_ringbuffer(reinterpret_cast<uintptr_t>(data));
108 for (size_t i = 0; i < size; i += page_size()) {
109 auto after = FindMapping(static_cast<char*>(data) + i);
110 EXPECT_TRUE(!after.has_value() || after->name != before->name);
111 }
112 }
113
TEST_P(MteStackHistoryTest,TestEmpty)114 TEST_P(MteStackHistoryTest, TestEmpty) {
115 int size_cls = GetParam();
116 size_t size = stack_mte_ringbuffer_size(size_cls);
117 void* data = stack_mte_ringbuffer_allocate(size_cls, nullptr);
118 ScopedUnmap s{data, size};
119 // The MTE TLS is at TLS - 3, so we allocate 3 placeholders.
120 void* tls[4] = {data};
121
122 StackHistoryBuffer shb;
123 dump_stack_history(&*unwinder, reinterpret_cast<uintptr_t>(&tls[3]), shb, /* nounwind= */ true);
124 EXPECT_EQ(shb.entries_size(), 0);
125 }
126
TEST_P(MteStackHistoryTest,TestFull)127 TEST_P(MteStackHistoryTest, TestFull) {
128 int size_cls = GetParam();
129 size_t size = stack_mte_ringbuffer_size(size_cls);
130 char* data = static_cast<char*>(stack_mte_ringbuffer_allocate(size_cls, nullptr));
131 ScopedUnmap s{data, size};
132 uintptr_t itr = 1;
133 for (char* d = data; d < &data[size]; d += 16) {
134 uintptr_t taggedfp = ((itr & 15) << 56) | itr;
135 uintptr_t pc = itr;
136 memcpy(d, &pc, sizeof(pc));
137 memcpy(d + 8, &taggedfp, sizeof(taggedfp));
138 ++itr;
139 }
140 // The MTE TLS is at TLS - 3, so we allocate 3 placeholders.
141 // Because the buffer is full, and we point at one past the last inserted element,
142 // due to wrap-around we point at the beginning of the buffer.
143 void* tls[4] = {data};
144
145 StackHistoryBuffer shb;
146 dump_stack_history(&*unwinder, reinterpret_cast<uintptr_t>(&tls[3]), shb, /* nounwind= */ true);
147 EXPECT_EQ(static_cast<size_t>(shb.entries_size()), size / 16);
148 for (const auto& entry : shb.entries()) {
149 EXPECT_EQ(entry.addr().pc(), --itr);
150 EXPECT_EQ(entry.addr().pc(), entry.fp());
151 EXPECT_EQ(entry.addr().pc() & 15, entry.tag());
152 }
153 }
154
TEST_P(MteStackHistoryTest,TestHalfFull)155 TEST_P(MteStackHistoryTest, TestHalfFull) {
156 int size_cls = GetParam();
157 size_t size = stack_mte_ringbuffer_size(size_cls);
158 size_t half_size = size / 2;
159
160 char* data = static_cast<char*>(stack_mte_ringbuffer_allocate(size_cls, nullptr));
161 ScopedUnmap s{data, size};
162
163 uintptr_t itr = 1;
164 for (char* d = data; d < &data[half_size]; d += 16) {
165 uintptr_t taggedfp = ((itr & 15) << 56) | itr;
166 uintptr_t pc = itr;
167 memcpy(d, &pc, sizeof(pc));
168 memcpy(d + 8, &taggedfp, sizeof(taggedfp));
169 ++itr;
170 }
171 // The MTE TLS is at TLS - 3, so we allocate 3 placeholders.
172 void* tls[4] = {&data[half_size]};
173
174 StackHistoryBuffer shb;
175 dump_stack_history(&*unwinder, reinterpret_cast<uintptr_t>(&tls[3]), shb, /* nounwind= */ true);
176 EXPECT_EQ(static_cast<size_t>(shb.entries_size()), half_size / 16);
177 for (const auto& entry : shb.entries()) {
178 EXPECT_EQ(entry.addr().pc(), --itr);
179 EXPECT_EQ(entry.addr().pc(), entry.fp());
180 EXPECT_EQ(entry.addr().pc() & 15, entry.tag());
181 }
182 }
183
184 INSTANTIATE_TEST_SUITE_P(MteStackHistoryTestInstance, MteStackHistoryTest, testing::Range(0, 8));
185
186 #endif
187