1 /*
2 * Copyright 2020 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 "UnwinderComponentCreator.h"
18
19 #include <map>
20 #include <memory>
21 #include <string>
22 #include <vector>
23
GetRegisters(ArchEnum arch)24 std::unique_ptr<Regs> GetRegisters(ArchEnum arch) {
25 switch (arch) {
26 case unwindstack::ARCH_ARM: {
27 std::unique_ptr<unwindstack::RegsArm> regs = std::make_unique<unwindstack::RegsArm>();
28 return regs;
29 }
30 case unwindstack::ARCH_ARM64: {
31 std::unique_ptr<unwindstack::RegsArm64> regs = std::make_unique<unwindstack::RegsArm64>();
32 return regs;
33 }
34 case unwindstack::ARCH_X86: {
35 std::unique_ptr<unwindstack::RegsX86> regs = std::make_unique<unwindstack::RegsX86>();
36 return regs;
37 }
38 case unwindstack::ARCH_X86_64: {
39 std::unique_ptr<unwindstack::RegsX86_64> regs = std::make_unique<unwindstack::RegsX86_64>();
40 return regs;
41 }
42 case unwindstack::ARCH_MIPS: {
43 std::unique_ptr<unwindstack::RegsMips> regs = std::make_unique<unwindstack::RegsMips>();
44 return regs;
45 }
46 case unwindstack::ARCH_MIPS64: {
47 std::unique_ptr<unwindstack::RegsMips64> regs = std::make_unique<unwindstack::RegsMips64>();
48 return regs;
49 }
50 case unwindstack::ARCH_UNKNOWN:
51 default: {
52 std::unique_ptr<unwindstack::RegsX86_64> regs = std::make_unique<unwindstack::RegsX86_64>();
53 return regs;
54 }
55 }
56 }
57
GetArch(FuzzedDataProvider * data_provider)58 ArchEnum GetArch(FuzzedDataProvider* data_provider) {
59 uint8_t arch = data_provider->ConsumeIntegralInRange<uint8_t>(1, kArchCount);
60 return static_cast<ArchEnum>(arch);
61 }
62
ElfAddMapInfo(Maps * maps,uint64_t start,uint64_t end,uint64_t offset,uint64_t flags,const char * name,Elf * elf=nullptr)63 void ElfAddMapInfo(Maps* maps, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
64 const char* name, Elf* elf = nullptr) {
65 std::string str_name(name);
66 maps->Add(start, end, offset, flags, name, static_cast<uint64_t>(-1));
67 if (elf != nullptr) {
68 const auto& map_info = *--maps->end();
69 map_info->set_elf(elf);
70 }
71 }
72
ElfPushFakeFunctionData(FuzzedDataProvider * data_provider,ElfInterfaceFake * elf)73 void ElfPushFakeFunctionData(FuzzedDataProvider* data_provider, ElfInterfaceFake* elf) {
74 uint8_t func_count = data_provider->ConsumeIntegralInRange<uint>(0, kMaxFuncCount);
75 for (uint8_t i = 0; i < func_count; i++) {
76 std::string func_name = data_provider->ConsumeRandomLengthString(kMaxFuncNameLen);
77 bool global = data_provider->ConsumeBool();
78 if (global) {
79 elf->FakeSetGlobalVariable(func_name, data_provider->ConsumeIntegral<uint64_t>());
80 } else {
81 ElfInterfaceFake::FakePushFunctionData(FunctionData(func_name, i));
82 }
83 }
84 }
ElfPushFakeStepData(FuzzedDataProvider * data_provider)85 void ElfPushFakeStepData(FuzzedDataProvider* data_provider) {
86 uint8_t step_count = data_provider->ConsumeIntegralInRange<uint>(0, kMaxStepCount);
87 for (uint8_t i = 0; i < step_count; i++) {
88 uint64_t pc = data_provider->ConsumeIntegral<uint64_t>();
89 uint64_t sp = data_provider->ConsumeIntegral<uint64_t>();
90 bool finished = i + 1 == step_count;
91 ElfInterfaceFake::FakePushStepData(StepData(pc, sp, finished));
92 }
93 }
94
PopulateElfFake(FuzzedDataProvider * data_provider)95 ElfFake* PopulateElfFake(FuzzedDataProvider* data_provider) {
96 // This will be passed to a smart pointer in ElfAddMapInfo.
97 ElfFake* elf = new ElfFake(new MemoryFake);
98
99 // This will be handled by a smart pointer within Elf.
100 ElfInterfaceFake* interface_fake = new ElfInterfaceFake(nullptr);
101 std::string build_id = data_provider->ConsumeRandomLengthString(kMaxBuildIdLen);
102 interface_fake->FakeSetBuildID(build_id);
103 std::string so_name = data_provider->ConsumeRandomLengthString(kMaxSoNameLen);
104 interface_fake->FakeSetSoname(so_name.c_str());
105
106 elf->FakeSetArch(GetArch(data_provider));
107 elf->FakeSetLoadBias(data_provider->ConsumeIntegral<uint64_t>());
108
109 ElfPushFakeFunctionData(data_provider, interface_fake);
110 ElfPushFakeStepData(data_provider);
111
112 elf->FakeSetInterface(interface_fake);
113 ElfInterfaceFake::FakeClear();
114 return elf;
115 }
116
117 static constexpr size_t kPageSize = 4096;
118
AlignToPage(uint64_t address,uint64_t * aligned_address)119 static inline bool AlignToPage(uint64_t address, uint64_t* aligned_address) {
120 if (__builtin_add_overflow(address, kPageSize - 1, aligned_address)) {
121 return false;
122 }
123 *aligned_address &= ~(kPageSize - 1);
124 return true;
125 }
126
GetMaps(FuzzedDataProvider * data_provider)127 std::unique_ptr<Maps> GetMaps(FuzzedDataProvider* data_provider) {
128 std::unique_ptr<Maps> maps = std::make_unique<Maps>();
129 std::map<uint64_t, uint64_t> map_ends;
130 uint8_t entry_count = data_provider->ConsumeIntegralInRange<uint8_t>(0, kMaxMapEntryCount);
131 for (uint8_t i = 0; i < entry_count; i++) {
132 uint64_t start;
133 if (!AlignToPage(data_provider->ConsumeIntegral<uint64_t>(), &start)) {
134 // Overflowed.
135 continue;
136 }
137 uint64_t end;
138 if (!AlignToPage(data_provider->ConsumeIntegralInRange<uint64_t>(start, UINT64_MAX), &end)) {
139 // Overflowed.
140 continue;
141 }
142 if (start == end) {
143 // It's impossible to see start == end in the real world, so
144 // make sure the map contains at least one page of data.
145 if (__builtin_add_overflow(end, 0x1000, &end)) {
146 continue;
147 }
148 }
149 // Make sure not to add overlapping maps, that is not something that can
150 // happen in the real world.
151 auto entry = map_ends.upper_bound(start);
152 if (entry != map_ends.end() && end > entry->second) {
153 continue;
154 }
155 map_ends[end] = start;
156
157 uint64_t offset;
158 if (!AlignToPage(data_provider->ConsumeIntegral<uint64_t>(), &offset)) {
159 // Overflowed.
160 continue;
161 }
162 std::string map_info_name = data_provider->ConsumeRandomLengthString(kMaxMapInfoNameLen);
163 uint8_t flags = PROT_READ | PROT_WRITE;
164
165 bool exec = data_provider->ConsumeBool();
166 if (exec) {
167 flags |= PROT_EXEC;
168 }
169
170 bool shouldAddElf = data_provider->ConsumeBool();
171 if (shouldAddElf) {
172 ElfAddMapInfo(maps.get(), start, end, offset, flags, map_info_name.c_str(),
173 PopulateElfFake(data_provider));
174 } else {
175 ElfAddMapInfo(maps.get(), start, end, offset, flags, map_info_name.c_str());
176 }
177 }
178 maps->Sort();
179 return maps;
180 }
181
182 // This code (until PutElfFilesInMemory) is pretty much directly copied from JitDebugTest.cpp
183 // There's a few minor modifications, most notably, all methods accept a MemoryFake pointer, and
184 // PutElfInMemory inserts JIT data when called.
WriteDescriptor32(MemoryFake * memory,uint64_t addr,uint32_t entry)185 void WriteDescriptor32(MemoryFake* memory, uint64_t addr, uint32_t entry) {
186 // Format of the 32 bit JITDescriptor structure:
187 // uint32_t version
188 memory->SetData32(addr, 1);
189 // uint32_t action_flag
190 memory->SetData32(addr + 4, 0);
191 // uint32_t relevant_entry
192 memory->SetData32(addr + 8, 0);
193 // uint32_t first_entry
194 memory->SetData32(addr + 12, entry);
195 }
196
WriteDescriptor64(MemoryFake * memory,uint64_t addr,uint64_t entry)197 void WriteDescriptor64(MemoryFake* memory, uint64_t addr, uint64_t entry) {
198 // Format of the 64 bit JITDescriptor structure:
199 // uint32_t version
200 memory->SetData32(addr, 1);
201 // uint32_t action_flag
202 memory->SetData32(addr + 4, 0);
203 // uint64_t relevant_entry
204 memory->SetData64(addr + 8, 0);
205 // uint64_t first_entry
206 memory->SetData64(addr + 16, entry);
207 }
208
WriteEntry32Pack(MemoryFake * memory,uint64_t addr,uint32_t prev,uint32_t next,uint32_t elf_addr,uint64_t elf_size)209 void WriteEntry32Pack(MemoryFake* memory, uint64_t addr, uint32_t prev, uint32_t next,
210 uint32_t elf_addr, uint64_t elf_size) {
211 // Format of the 32 bit JITCodeEntry structure:
212 // uint32_t next
213 memory->SetData32(addr, next);
214 // uint32_t prev
215 memory->SetData32(addr + 4, prev);
216 // uint32_t symfile_addr
217 memory->SetData32(addr + 8, elf_addr);
218 // uint64_t symfile_size
219 memory->SetData64(addr + 12, elf_size);
220 }
221
WriteEntry32Pad(MemoryFake * memory,uint64_t addr,uint32_t prev,uint32_t next,uint32_t elf_addr,uint64_t elf_size)222 void WriteEntry32Pad(MemoryFake* memory, uint64_t addr, uint32_t prev, uint32_t next,
223 uint32_t elf_addr, uint64_t elf_size) {
224 // Format of the 32 bit JITCodeEntry structure:
225 // uint32_t next
226 memory->SetData32(addr, next);
227 // uint32_t prev
228 memory->SetData32(addr + 4, prev);
229 // uint32_t symfile_addr
230 memory->SetData32(addr + 8, elf_addr);
231 // uint32_t pad
232 memory->SetData32(addr + 12, 0);
233 // uint64_t symfile_size
234 memory->SetData64(addr + 16, elf_size);
235 }
236
WriteEntry64(MemoryFake * memory,uint64_t addr,uint64_t prev,uint64_t next,uint64_t elf_addr,uint64_t elf_size)237 void WriteEntry64(MemoryFake* memory, uint64_t addr, uint64_t prev, uint64_t next,
238 uint64_t elf_addr, uint64_t elf_size) {
239 // Format of the 64 bit JITCodeEntry structure:
240 // uint64_t next
241 memory->SetData64(addr, next);
242 // uint64_t prev
243 memory->SetData64(addr + 8, prev);
244 // uint64_t symfile_addr
245 memory->SetData64(addr + 16, elf_addr);
246 // uint64_t symfile_size
247 memory->SetData64(addr + 24, elf_size);
248 }
249
250 template <typename EhdrType, typename ShdrType>
PutElfInMemory(MemoryFake * memory,uint64_t offset,uint8_t class_type,uint8_t machine_type,uint32_t pc,uint32_t size)251 void PutElfInMemory(MemoryFake* memory, uint64_t offset, uint8_t class_type, uint8_t machine_type,
252 uint32_t pc, uint32_t size) {
253 EhdrType ehdr;
254 memset(&ehdr, 0, sizeof(ehdr));
255 uint64_t sh_offset = sizeof(ehdr);
256 memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
257 ehdr.e_ident[EI_CLASS] = class_type;
258 ehdr.e_machine = machine_type;
259 ehdr.e_shstrndx = 1;
260 ehdr.e_shoff = sh_offset;
261 ehdr.e_shentsize = sizeof(ShdrType);
262 ehdr.e_shnum = 3;
263 memory->SetMemory(offset, &ehdr, sizeof(ehdr));
264
265 ShdrType shdr;
266 memset(&shdr, 0, sizeof(shdr));
267 shdr.sh_type = SHT_NULL;
268 memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
269
270 sh_offset += sizeof(shdr);
271 memset(&shdr, 0, sizeof(shdr));
272 shdr.sh_type = SHT_STRTAB;
273 shdr.sh_name = 1;
274 shdr.sh_offset = 0x500;
275 shdr.sh_size = 0x100;
276 memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
277 memory->SetMemory(offset + 0x500, ".debug_frame");
278
279 sh_offset += sizeof(shdr);
280 memset(&shdr, 0, sizeof(shdr));
281 shdr.sh_type = SHT_PROGBITS;
282 shdr.sh_name = 0;
283 shdr.sh_addr = 0x600;
284 shdr.sh_offset = 0x600;
285 shdr.sh_size = 0x200;
286 memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
287
288 // Now add a single cie/fde.
289 uint64_t dwarf_offset = offset + 0x600;
290 if (class_type == ELFCLASS32) {
291 // CIE 32 information.
292 memory->SetData32(dwarf_offset, 0xfc);
293 memory->SetData32(dwarf_offset + 0x4, 0xffffffff);
294 memory->SetData8(dwarf_offset + 0x8, 1);
295 memory->SetData8(dwarf_offset + 0x9, '\0');
296 memory->SetData8(dwarf_offset + 0xa, 0x4);
297 memory->SetData8(dwarf_offset + 0xb, 0x4);
298 memory->SetData8(dwarf_offset + 0xc, 0x1);
299
300 // FDE 32 information.
301 memory->SetData32(dwarf_offset + 0x100, 0xfc);
302 memory->SetData32(dwarf_offset + 0x104, 0);
303 memory->SetData32(dwarf_offset + 0x108, pc);
304 memory->SetData32(dwarf_offset + 0x10c, size);
305 } else {
306 // CIE 64 information.
307 memory->SetData32(dwarf_offset, 0xffffffff);
308 memory->SetData64(dwarf_offset + 4, 0xf4);
309 memory->SetData64(dwarf_offset + 0xc, 0xffffffffffffffffULL);
310 memory->SetData8(dwarf_offset + 0x14, 1);
311 memory->SetData8(dwarf_offset + 0x15, '\0');
312 memory->SetData8(dwarf_offset + 0x16, 0x4);
313 memory->SetData8(dwarf_offset + 0x17, 0x4);
314 memory->SetData8(dwarf_offset + 0x18, 0x1);
315
316 // FDE 64 information.
317 memory->SetData32(dwarf_offset + 0x100, 0xffffffff);
318 memory->SetData64(dwarf_offset + 0x104, 0xf4);
319 memory->SetData64(dwarf_offset + 0x10c, 0);
320 memory->SetData64(dwarf_offset + 0x114, pc);
321 memory->SetData64(dwarf_offset + 0x11c, size);
322 }
323 }
324
PutElfFilesInMemory(MemoryFake * memory,FuzzedDataProvider * data_provider)325 void PutElfFilesInMemory(MemoryFake* memory, FuzzedDataProvider* data_provider) {
326 uint8_t elf_file_count = data_provider->ConsumeIntegralInRange<uint8_t>(0, kMaxJitElfFiles);
327 int entry_offset = 0;
328 int prev_jit_addr = 0;
329 for (uint8_t i = 0; i < elf_file_count; i++) {
330 uint64_t offset = data_provider->ConsumeIntegral<uint64_t>();
331 // Technically the max valid value is ELFCLASSNUM - 1 (2), but
332 // we want to test values outside of that range.
333 uint8_t class_type = data_provider->ConsumeIntegral<uint8_t>();
334 // Same here, EM_NUM is 253, max valid machine type is 252
335 uint8_t machine_type = data_provider->ConsumeIntegral<uint8_t>();
336 uint32_t pc = data_provider->ConsumeIntegral<uint32_t>();
337 uint32_t size = data_provider->ConsumeIntegral<uint32_t>();
338 bool sixty_four_bit = data_provider->ConsumeBool();
339 bool write_jit = data_provider->ConsumeBool();
340 if (sixty_four_bit) {
341 PutElfInMemory<Elf64_Ehdr, Elf64_Shdr>(memory, offset, class_type, machine_type, pc, size);
342 } else {
343 PutElfInMemory<Elf32_Ehdr, Elf32_Shdr>(memory, offset, class_type, machine_type, pc, size);
344 }
345 if (write_jit) {
346 bool use_pad = data_provider->ConsumeBool();
347 // It is possible this will overwrite part of the ELF.
348 // This provides an interesting test of how malformed ELF
349 // data is handled.
350 uint64_t cur_descriptor_addr = 0x11800 + entry_offset;
351 uint64_t cur_jit_addr = 0x200000 + entry_offset;
352 uint64_t next_jit_addr = cur_jit_addr + size;
353 if (sixty_four_bit) {
354 WriteDescriptor64(memory, 0x11800, cur_jit_addr);
355 WriteEntry64(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size);
356 } else {
357 // Loop back. Again, this may corrupt data,
358 // but that will allow for testing edge cases with
359 // malformed JIT data.
360 if (cur_jit_addr > UINT32_MAX) {
361 entry_offset = 0;
362 cur_jit_addr = 0x200000;
363 cur_descriptor_addr = 0x11800;
364 next_jit_addr = cur_jit_addr + size;
365 }
366 WriteDescriptor32(memory, cur_descriptor_addr, cur_jit_addr);
367 if (use_pad) {
368 WriteEntry32Pad(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size);
369 } else {
370 WriteEntry32Pack(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size);
371 }
372 }
373 entry_offset += size;
374 prev_jit_addr = cur_jit_addr;
375 }
376 }
377 }
378
GetStringList(FuzzedDataProvider * data_provider,uint max_str_len,uint max_strings)379 std::vector<std::string> GetStringList(FuzzedDataProvider* data_provider, uint max_str_len,
380 uint max_strings) {
381 uint str_count = data_provider->ConsumeIntegralInRange<uint>(0, max_strings);
382 std::vector<std::string> strings;
383 for (uint i = 0; i < str_count; i++) {
384 strings.push_back(data_provider->ConsumeRandomLengthString(max_str_len));
385 }
386 return strings;
387 }
388
GetDexFiles(FuzzedDataProvider * data_provider,std::shared_ptr<Memory> memory,uint max_library_length,uint max_libraries,ArchEnum arch)389 std::unique_ptr<DexFiles> GetDexFiles(FuzzedDataProvider* data_provider,
390 std::shared_ptr<Memory> memory, uint max_library_length,
391 uint max_libraries, ArchEnum arch) {
392 std::vector<std::string> search_libs =
393 GetStringList(data_provider, max_library_length, max_libraries);
394 if (search_libs.size() <= 0) {
395 return CreateDexFiles(arch, memory);
396 }
397
398 return CreateDexFiles(arch, memory, search_libs);
399 }
400