1 /*
2 * Copyright (C) 2016 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 <errno.h>
18 #include <signal.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/mman.h>
23 #include <sys/ptrace.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 #include <vector>
28
29 #include <android-base/file.h>
30 #include <android-base/test_utils.h>
31 #include <gtest/gtest.h>
32
33 #include "MemoryRemote.h"
34
35 #include "MemoryFake.h"
36 #include "TestUtils.h"
37
38 namespace unwindstack {
39
TEST(MemoryRemoteTest,read)40 TEST(MemoryRemoteTest, read) {
41 std::vector<uint8_t> src(1024);
42 memset(src.data(), 0x4c, 1024);
43
44 pid_t pid;
45 if ((pid = fork()) == 0) {
46 while (true);
47 exit(1);
48 }
49 ASSERT_LT(0, pid);
50 TestScopedPidReaper reap(pid);
51
52 ASSERT_TRUE(TestAttach(pid));
53
54 MemoryRemote remote(pid);
55
56 std::vector<uint8_t> dst(1024);
57 ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
58 for (size_t i = 0; i < 1024; i++) {
59 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
60 }
61
62 ASSERT_TRUE(TestDetach(pid));
63 }
64
TEST(MemoryRemoteTest,read_large)65 TEST(MemoryRemoteTest, read_large) {
66 static constexpr size_t kTotalPages = 245;
67 std::vector<uint8_t> src(kTotalPages * getpagesize());
68 for (size_t i = 0; i < kTotalPages; i++) {
69 memset(&src[i * getpagesize()], i, getpagesize());
70 }
71
72 pid_t pid;
73 if ((pid = fork()) == 0) {
74 while (true)
75 ;
76 exit(1);
77 }
78 ASSERT_LT(0, pid);
79 TestScopedPidReaper reap(pid);
80
81 ASSERT_TRUE(TestAttach(pid));
82
83 MemoryRemote remote(pid);
84
85 std::vector<uint8_t> dst(kTotalPages * getpagesize());
86 ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), src.size()));
87 for (size_t i = 0; i < kTotalPages * getpagesize(); i++) {
88 ASSERT_EQ(i / getpagesize(), dst[i]) << "Failed at byte " << i;
89 }
90
91 ASSERT_TRUE(TestDetach(pid));
92 }
93
TEST(MemoryRemoteTest,read_partial)94 TEST(MemoryRemoteTest, read_partial) {
95 char* mapping = static_cast<char*>(
96 mmap(nullptr, 4 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
97 ASSERT_NE(MAP_FAILED, mapping);
98 memset(mapping, 0x4c, 4 * getpagesize());
99 ASSERT_EQ(0, mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE));
100 ASSERT_EQ(0, munmap(mapping + 3 * getpagesize(), getpagesize()));
101
102 pid_t pid;
103 if ((pid = fork()) == 0) {
104 while (true)
105 ;
106 exit(1);
107 }
108 ASSERT_LT(0, pid);
109 TestScopedPidReaper reap(pid);
110
111 // Unmap from our process.
112 ASSERT_EQ(0, munmap(mapping, 3 * getpagesize()));
113
114 ASSERT_TRUE(TestAttach(pid));
115
116 MemoryRemote remote(pid);
117
118 std::vector<uint8_t> dst(4096);
119 size_t bytes =
120 remote.Read(reinterpret_cast<uint64_t>(mapping + getpagesize() - 1024), dst.data(), 4096);
121 // Some read methods can read PROT_NONE maps, allow that.
122 ASSERT_LE(1024U, bytes);
123 for (size_t i = 0; i < bytes; i++) {
124 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
125 }
126
127 // Now verify that reading stops at the end of a map.
128 bytes =
129 remote.Read(reinterpret_cast<uint64_t>(mapping + 3 * getpagesize() - 1024), dst.data(), 4096);
130 ASSERT_EQ(1024U, bytes);
131 for (size_t i = 0; i < bytes; i++) {
132 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
133 }
134
135 ASSERT_TRUE(TestDetach(pid));
136 }
137
TEST(MemoryRemoteTest,read_fail)138 TEST(MemoryRemoteTest, read_fail) {
139 int pagesize = getpagesize();
140 void* src = mmap(nullptr, pagesize * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,-1, 0);
141 memset(src, 0x4c, pagesize * 2);
142 ASSERT_NE(MAP_FAILED, src);
143 // Put a hole right after the first page.
144 ASSERT_EQ(0, munmap(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(src) + pagesize),
145 pagesize));
146
147 pid_t pid;
148 if ((pid = fork()) == 0) {
149 while (true);
150 exit(1);
151 }
152 ASSERT_LT(0, pid);
153 TestScopedPidReaper reap(pid);
154
155 ASSERT_TRUE(TestAttach(pid));
156
157 MemoryRemote remote(pid);
158
159 std::vector<uint8_t> dst(pagesize);
160 ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src), dst.data(), pagesize));
161 for (size_t i = 0; i < 1024; i++) {
162 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
163 }
164
165 ASSERT_FALSE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize, dst.data(), 1));
166 ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize - 1, dst.data(), 1));
167 ASSERT_FALSE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize - 4, dst.data(), 8));
168
169 // Check overflow condition is caught properly.
170 ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200));
171
172 ASSERT_EQ(0, munmap(src, pagesize));
173
174 ASSERT_TRUE(TestDetach(pid));
175 }
176
TEST(MemoryRemoteTest,read_overflow)177 TEST(MemoryRemoteTest, read_overflow) {
178 pid_t pid;
179 if ((pid = fork()) == 0) {
180 while (true)
181 ;
182 exit(1);
183 }
184 ASSERT_LT(0, pid);
185 TestScopedPidReaper reap(pid);
186
187 ASSERT_TRUE(TestAttach(pid));
188
189 MemoryRemote remote(pid);
190
191 // Check overflow condition is caught properly.
192 std::vector<uint8_t> dst(200);
193 ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200));
194
195 ASSERT_TRUE(TestDetach(pid));
196 }
197
TEST(MemoryRemoteTest,read_illegal)198 TEST(MemoryRemoteTest, read_illegal) {
199 pid_t pid;
200 if ((pid = fork()) == 0) {
201 while (true);
202 exit(1);
203 }
204 ASSERT_LT(0, pid);
205 TestScopedPidReaper reap(pid);
206
207 ASSERT_TRUE(TestAttach(pid));
208
209 MemoryRemote remote(pid);
210
211 std::vector<uint8_t> dst(100);
212 ASSERT_FALSE(remote.ReadFully(0, dst.data(), 1));
213 ASSERT_FALSE(remote.ReadFully(0, dst.data(), 100));
214
215 ASSERT_TRUE(TestDetach(pid));
216 }
217
TEST(MemoryRemoteTest,read_mprotect_hole)218 TEST(MemoryRemoteTest, read_mprotect_hole) {
219 size_t page_size = getpagesize();
220 void* mapping =
221 mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
222 ASSERT_NE(MAP_FAILED, mapping);
223 memset(mapping, 0xFF, 3 * page_size);
224 ASSERT_EQ(0, mprotect(static_cast<char*>(mapping) + page_size, page_size, PROT_NONE));
225
226 pid_t pid;
227 if ((pid = fork()) == 0) {
228 while (true);
229 exit(1);
230 }
231 ASSERT_LT(0, pid);
232 TestScopedPidReaper reap(pid);
233
234 ASSERT_EQ(0, munmap(mapping, 3 * page_size));
235
236 ASSERT_TRUE(TestAttach(pid));
237
238 MemoryRemote remote(pid);
239 std::vector<uint8_t> dst(getpagesize() * 4, 0xCC);
240 size_t read_size = remote.Read(reinterpret_cast<uint64_t>(mapping), dst.data(), page_size * 3);
241 // Some read methods can read PROT_NONE maps, allow that.
242 ASSERT_LE(page_size, read_size);
243 for (size_t i = 0; i < read_size; ++i) {
244 ASSERT_EQ(0xFF, dst[i]);
245 }
246 for (size_t i = read_size; i < dst.size(); ++i) {
247 ASSERT_EQ(0xCC, dst[i]);
248 }
249
250 ASSERT_TRUE(TestDetach(pid));
251 }
252
TEST(MemoryRemoteTest,read_munmap_hole)253 TEST(MemoryRemoteTest, read_munmap_hole) {
254 size_t page_size = getpagesize();
255 void* mapping =
256 mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
257 ASSERT_NE(MAP_FAILED, mapping);
258 memset(mapping, 0xFF, 3 * page_size);
259 ASSERT_EQ(0, munmap(static_cast<char*>(mapping) + page_size, page_size));
260
261 pid_t pid;
262 if ((pid = fork()) == 0) {
263 while (true)
264 ;
265 exit(1);
266 }
267 ASSERT_LT(0, pid);
268 TestScopedPidReaper reap(pid);
269
270 ASSERT_EQ(0, munmap(mapping, page_size));
271 ASSERT_EQ(0, munmap(static_cast<char*>(mapping) + 2 * page_size, page_size));
272
273 ASSERT_TRUE(TestAttach(pid));
274
275 MemoryRemote remote(pid);
276 std::vector<uint8_t> dst(getpagesize() * 4, 0xCC);
277 size_t read_size = remote.Read(reinterpret_cast<uint64_t>(mapping), dst.data(), page_size * 3);
278 ASSERT_EQ(page_size, read_size);
279 for (size_t i = 0; i < read_size; ++i) {
280 ASSERT_EQ(0xFF, dst[i]);
281 }
282 for (size_t i = read_size; i < dst.size(); ++i) {
283 ASSERT_EQ(0xCC, dst[i]);
284 }
285
286 ASSERT_TRUE(TestDetach(pid));
287 }
288
289 // Verify that the memory remote object chooses a memory read function
290 // properly. Either process_vm_readv or ptrace.
TEST(MemoryRemoteTest,read_choose_correctly)291 TEST(MemoryRemoteTest, read_choose_correctly) {
292 size_t page_size = getpagesize();
293 void* mapping =
294 mmap(nullptr, 2 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
295 ASSERT_NE(MAP_FAILED, mapping);
296 memset(mapping, 0xFC, 2 * page_size);
297 ASSERT_EQ(0, mprotect(static_cast<char*>(mapping), page_size, PROT_NONE));
298
299 pid_t pid;
300 if ((pid = fork()) == 0) {
301 while (true)
302 ;
303 exit(1);
304 }
305 ASSERT_LT(0, pid);
306 TestScopedPidReaper reap(pid);
307
308 ASSERT_EQ(0, munmap(mapping, 2 * page_size));
309
310 ASSERT_TRUE(TestAttach(pid));
311
312 // We know that process_vm_readv of a mprotect'd PROT_NONE region will fail.
313 // Read from the PROT_NONE area first to force the choice of ptrace.
314 MemoryRemote remote_ptrace(pid);
315 uint32_t value;
316 size_t bytes = remote_ptrace.Read(reinterpret_cast<uint64_t>(mapping), &value, sizeof(value));
317 ASSERT_EQ(sizeof(value), bytes);
318 ASSERT_EQ(0xfcfcfcfcU, value);
319 bytes = remote_ptrace.Read(reinterpret_cast<uint64_t>(mapping) + page_size, &value, sizeof(value));
320 ASSERT_EQ(sizeof(value), bytes);
321 ASSERT_EQ(0xfcfcfcfcU, value);
322 bytes = remote_ptrace.Read(reinterpret_cast<uint64_t>(mapping), &value, sizeof(value));
323 ASSERT_EQ(sizeof(value), bytes);
324 ASSERT_EQ(0xfcfcfcfcU, value);
325
326 // Now verify that choosing process_vm_readv results in failing reads of
327 // the PROT_NONE part of the map. Read from a valid map first which
328 // should prefer process_vm_readv, and keep that as the read function.
329 MemoryRemote remote_readv(pid);
330 bytes = remote_readv.Read(reinterpret_cast<uint64_t>(mapping) + page_size, &value, sizeof(value));
331 ASSERT_EQ(sizeof(value), bytes);
332 ASSERT_EQ(0xfcfcfcfcU, value);
333 bytes = remote_readv.Read(reinterpret_cast<uint64_t>(mapping), &value, sizeof(value));
334 ASSERT_EQ(0U, bytes);
335 bytes = remote_readv.Read(reinterpret_cast<uint64_t>(mapping) + page_size, &value, sizeof(value));
336 ASSERT_EQ(sizeof(value), bytes);
337 ASSERT_EQ(0xfcfcfcfcU, value);
338
339 ASSERT_TRUE(TestDetach(pid));
340 }
341
342 } // namespace unwindstack
343