blob: c846ad7c6e6ca9eda73081285c16befebebe8690 [file] [log] [blame]
Christopher Ferris0d7cf3e2017-04-19 15:42:19 -07001/*
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 <elf.h>
18#include <errno.h>
19#include <signal.h>
20#include <string.h>
21#include <sys/mman.h>
22#include <sys/ptrace.h>
23#include <sys/types.h>
24#include <unistd.h>
25
26#include <memory>
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 "Elf.h"
34#include "MapInfo.h"
35#include "Memory.h"
36
37class MapInfoTest : public ::testing::Test {
38 protected:
39 static void SetUpTestCase() {
40 std::vector<uint8_t> buffer(1024);
41 memcpy(buffer.data(), ELFMAG, SELFMAG);
42 for (size_t i = SELFMAG; i < buffer.size(); i++) {
43 buffer[i] = i / 256 + 1;
44 }
45 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
46
47 for (size_t i = 0; i < 0x100; i++) {
48 buffer[i] = i / 256 + 1;
49 }
50 memcpy(&buffer[0x100], ELFMAG, SELFMAG);
51 for (size_t i = 0x100 + SELFMAG; i < buffer.size(); i++) {
52 buffer[i] = i / 256 + 1;
53 }
54 ASSERT_TRUE(android::base::WriteFully(elf_at_100_.fd, buffer.data(), buffer.size()));
55 }
56
57 static TemporaryFile elf_;
58
59 static TemporaryFile elf_at_100_;
60};
61TemporaryFile MapInfoTest::elf_;
62TemporaryFile MapInfoTest::elf_at_100_;
63
64TEST_F(MapInfoTest, end_le_start) {
65 MapInfo info{.start = 0x100, .end = 0x100, .offset = 0, .name = elf_.path};
66
67 std::unique_ptr<Memory> memory;
68 memory.reset(info.CreateMemory(getpid()));
69 ASSERT_TRUE(memory.get() == nullptr);
70
71 info.end = 0xff;
72 memory.reset(info.CreateMemory(getpid()));
73 ASSERT_TRUE(memory.get() == nullptr);
74
75 // Make sure this test is valid.
76 info.end = 0x101;
77 memory.reset(info.CreateMemory(getpid()));
78 ASSERT_FALSE(info.CreateMemory(getpid()) == nullptr);
79}
80
81// Verify that if the offset is non-zero but there is no elf at the offset,
82// that the full file is used.
83TEST_F(MapInfoTest, create_memory_file_backed_non_zero_offset_full_file) {
84 MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_.path};
85
86 std::unique_ptr<Memory> memory(info.CreateMemory(getpid()));
87 ASSERT_TRUE(memory.get() != nullptr);
88 ASSERT_EQ(0x100U, info.elf_offset);
89
90 // Read the entire file.
91 std::vector<uint8_t> buffer(1024);
92 ASSERT_TRUE(memory->Read(0, buffer.data(), 1024));
93 ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
94 for (size_t i = SELFMAG; i < buffer.size(); i++) {
95 ASSERT_EQ(i / 256 + 1, buffer[i]) << "Failed at byte " << i;
96 }
97
98 ASSERT_FALSE(memory->Read(1024, buffer.data(), 1));
99}
100
101// Verify that if the offset is non-zero and there is an elf at that
102// offset, that only part of the file is used.
103TEST_F(MapInfoTest, create_memory_file_backed_non_zero_offset_partial_file) {
104 MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_at_100_.path};
105
106 std::unique_ptr<Memory> memory(info.CreateMemory(getpid()));
107 ASSERT_TRUE(memory.get() != nullptr);
108 ASSERT_EQ(0U, info.elf_offset);
109
110 // Read the valid part of the file.
111 std::vector<uint8_t> buffer(0x100);
112 ASSERT_TRUE(memory->Read(0, buffer.data(), 0x100));
113 ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
114 for (size_t i = SELFMAG; i < buffer.size(); i++) {
115 ASSERT_EQ(2, buffer[i]) << "Failed at byte " << i;
116 }
117
118 ASSERT_FALSE(memory->Read(0x100, buffer.data(), 1));
119}
120
121// Verify that device file names will never result in Memory object creation.
122TEST_F(MapInfoTest, create_memory_check_device_maps) {
123 // Set up some memory so that a valid local memory object would
124 // be returned if the file mapping fails, but the device check is incorrect.
125 std::vector<uint8_t> buffer(1024);
126 MapInfo info;
127 info.start = reinterpret_cast<uint64_t>(buffer.data());
128 info.end = info.start + buffer.size();
129 info.offset = 0;
130 std::unique_ptr<Memory> memory;
131
132 info.flags = 0x8000;
133 info.name = "/dev/something";
134 memory.reset(info.CreateMemory(getpid()));
135 ASSERT_TRUE(memory.get() == nullptr);
136}
137
138TEST_F(MapInfoTest, create_memory_local_memory) {
139 // Set up some memory for a valid local memory object.
140 std::vector<uint8_t> buffer(1024);
141 for (size_t i = 0; i < buffer.size(); i++) {
142 buffer[i] = i % 256;
143 }
144
145 MapInfo info;
146 info.start = reinterpret_cast<uint64_t>(buffer.data());
147 info.end = info.start + buffer.size();
148 info.offset = 0;
149
150 std::unique_ptr<Memory> memory;
151 memory.reset(info.CreateMemory(getpid()));
152 ASSERT_TRUE(memory.get() != nullptr);
153
154 std::vector<uint8_t> read_buffer(1024);
155 ASSERT_TRUE(memory->Read(0, read_buffer.data(), read_buffer.size()));
156 for (size_t i = 0; i < read_buffer.size(); i++) {
157 ASSERT_EQ(i % 256, read_buffer[i]) << "Failed at byte " << i;
158 }
159
160 ASSERT_FALSE(memory->Read(read_buffer.size(), read_buffer.data(), 1));
161}
162
163TEST_F(MapInfoTest, create_memory_remote_memory) {
164 std::vector<uint8_t> buffer(1024);
165 memset(buffer.data(), 0xa, buffer.size());
166
167 pid_t pid;
168 if ((pid = fork()) == 0) {
169 while (true)
170 ;
171 exit(1);
172 }
173 ASSERT_LT(0, pid);
174
175 ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) != -1);
176 uint64_t iterations = 0;
177 siginfo_t si;
178 while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) < 0 && errno == ESRCH) {
179 usleep(30);
180 iterations++;
181 ASSERT_LT(iterations, 500000000ULL);
182 }
183
184 MapInfo info;
185 info.start = reinterpret_cast<uint64_t>(buffer.data());
186 info.end = info.start + buffer.size();
187 info.offset = 0;
188
189 std::unique_ptr<Memory> memory;
190 memory.reset(info.CreateMemory(pid));
191 ASSERT_TRUE(memory.get() != nullptr);
192 // Set the local memory to a different value to guarantee we are reading
193 // from the remote process.
194 memset(buffer.data(), 0x1, buffer.size());
195 std::vector<uint8_t> read_buffer(1024);
196 ASSERT_TRUE(memory->Read(0, read_buffer.data(), read_buffer.size()));
197 for (size_t i = 0; i < read_buffer.size(); i++) {
198 ASSERT_EQ(0xaU, read_buffer[i]) << "Failed at byte " << i;
199 }
200
201 ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
202
203 kill(pid, SIGKILL);
204}
205
206TEST_F(MapInfoTest, get_elf) {
207 // Create a map to use as initialization data.
208 void* map = mmap(nullptr, 1024, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
209 ASSERT_NE(MAP_FAILED, map);
210
211 uint64_t start = reinterpret_cast<uint64_t>(map);
212 MapInfo info{.start = start, .end = start + 1024, .offset = 0, .name = ""};
213
214 // The map contains garbage, but this should still produce an elf object.
215 Elf* elf = info.GetElf(getpid(), false);
216 ASSERT_TRUE(elf != nullptr);
217 ASSERT_FALSE(elf->valid());
218
219 ASSERT_EQ(0, munmap(map, 1024));
220}