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