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