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 <time.h>
26 #include <unistd.h>
27
28 #include <vector>
29
30 #include <android-base/test_utils.h>
31 #include <android-base/file.h>
32 #include <gtest/gtest.h>
33
34 #include "Memory.h"
35
36 class MemoryRemoteTest : public ::testing::Test {
37 protected:
NanoTime()38 static uint64_t NanoTime() {
39 struct timespec t = { 0, 0 };
40 clock_gettime(CLOCK_MONOTONIC, &t);
41 return static_cast<uint64_t>(t.tv_sec * NS_PER_SEC + t.tv_nsec);
42 }
43
Attach(pid_t pid)44 static bool Attach(pid_t pid) {
45 if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
46 return false;
47 }
48
49 uint64_t start = NanoTime();
50 siginfo_t si;
51 while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) < 0 && errno == ESRCH) {
52 if ((NanoTime() - start) > 10 * NS_PER_SEC) {
53 printf("%d: Failed to stop after 10 seconds.\n", pid);
54 return false;
55 }
56 usleep(30);
57 }
58 return true;
59 }
60
Detach(pid_t pid)61 static bool Detach(pid_t pid) {
62 return ptrace(PTRACE_DETACH, pid, 0, 0) == 0;
63 }
64
65 static constexpr size_t NS_PER_SEC = 1000000000ULL;
66 };
67
TEST_F(MemoryRemoteTest,read)68 TEST_F(MemoryRemoteTest, read) {
69 std::vector<uint8_t> src(1024);
70 memset(src.data(), 0x4c, 1024);
71
72 pid_t pid;
73 if ((pid = fork()) == 0) {
74 while (true);
75 exit(1);
76 }
77 ASSERT_LT(0, pid);
78
79 ASSERT_TRUE(Attach(pid));
80
81 MemoryRemote remote(pid);
82
83 std::vector<uint8_t> dst(1024);
84 ASSERT_TRUE(remote.Read(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
85 for (size_t i = 0; i < 1024; i++) {
86 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
87 }
88
89 ASSERT_TRUE(Detach(pid));
90
91 kill(pid, SIGKILL);
92 }
93
TEST_F(MemoryRemoteTest,read_fail)94 TEST_F(MemoryRemoteTest, read_fail) {
95 int pagesize = getpagesize();
96 void* src = mmap(nullptr, pagesize * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,-1, 0);
97 memset(src, 0x4c, pagesize * 2);
98 ASSERT_NE(MAP_FAILED, src);
99 // Put a hole right after the first page.
100 ASSERT_EQ(0, munmap(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(src) + pagesize),
101 pagesize));
102
103 pid_t pid;
104 if ((pid = fork()) == 0) {
105 while (true);
106 exit(1);
107 }
108 ASSERT_LT(0, pid);
109
110 ASSERT_TRUE(Attach(pid));
111
112 MemoryRemote remote(pid);
113
114 std::vector<uint8_t> dst(pagesize);
115 ASSERT_TRUE(remote.Read(reinterpret_cast<uint64_t>(src), dst.data(), pagesize));
116 for (size_t i = 0; i < 1024; i++) {
117 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
118 }
119
120 ASSERT_FALSE(remote.Read(reinterpret_cast<uint64_t>(src) + pagesize, dst.data(), 1));
121 ASSERT_TRUE(remote.Read(reinterpret_cast<uint64_t>(src) + pagesize - 1, dst.data(), 1));
122 ASSERT_FALSE(remote.Read(reinterpret_cast<uint64_t>(src) + pagesize - 4, dst.data(), 8));
123
124 ASSERT_EQ(0, munmap(src, pagesize));
125
126 ASSERT_TRUE(Detach(pid));
127
128 kill(pid, SIGKILL);
129 }
130
TEST_F(MemoryRemoteTest,read_illegal)131 TEST_F(MemoryRemoteTest, read_illegal) {
132 pid_t pid;
133 if ((pid = fork()) == 0) {
134 while (true);
135 exit(1);
136 }
137 ASSERT_LT(0, pid);
138
139 ASSERT_TRUE(Attach(pid));
140
141 MemoryRemote remote(pid);
142
143 std::vector<uint8_t> dst(100);
144 ASSERT_FALSE(remote.Read(0, dst.data(), 1));
145 ASSERT_FALSE(remote.Read(0, dst.data(), 100));
146
147 ASSERT_TRUE(Detach(pid));
148
149 kill(pid, SIGKILL);
150 }
151