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