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