1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #undef NDEBUG
6 #include <assert.h>
7 #include <cstring>
8 #include <cstdlib>
9 #include <cstdio>
10 #include "elfxx.h"
11 #include "mozilla/CheckedInt.h"
12 
13 #define ver "1"
14 #define elfhack_data ".elfhack.data.v" ver
15 #define elfhack_text ".elfhack.text.v" ver
16 
17 #ifndef R_ARM_V4BX
18 #  define R_ARM_V4BX 0x28
19 #endif
20 #ifndef R_ARM_CALL
21 #  define R_ARM_CALL 0x1c
22 #endif
23 #ifndef R_ARM_JUMP24
24 #  define R_ARM_JUMP24 0x1d
25 #endif
26 #ifndef R_ARM_THM_JUMP24
27 #  define R_ARM_THM_JUMP24 0x1e
28 #endif
29 
30 char* rundir = nullptr;
31 
32 template <typename T>
33 struct wrapped {
34   T value;
35 };
36 
37 class Elf_Addr_Traits {
38  public:
39   typedef wrapped<Elf32_Addr> Type32;
40   typedef wrapped<Elf64_Addr> Type64;
41 
42   template <class endian, typename R, typename T>
swap(T & t,R & r)43   static inline void swap(T& t, R& r) {
44     r.value = endian::swap(t.value);
45   }
46 };
47 
48 typedef serializable<Elf_Addr_Traits> Elf_Addr;
49 
50 class ElfRelHack_Section : public ElfSection {
51  public:
ElfRelHack_Section(Elf_Shdr & s)52   ElfRelHack_Section(Elf_Shdr& s)
53       : ElfSection(s, nullptr, nullptr),
54         block_size((8 * s.sh_entsize - 1) * s.sh_entsize) {
55     name = elfhack_data;
56   };
57 
serialize(std::ofstream & file,unsigned char ei_class,unsigned char ei_data)58   void serialize(std::ofstream& file, unsigned char ei_class,
59                  unsigned char ei_data) {
60     for (std::vector<Elf64_Addr>::iterator i = relr.begin(); i != relr.end();
61          ++i) {
62       Elf_Addr out;
63       out.value = *i;
64       out.serialize(file, ei_class, ei_data);
65     }
66   }
67 
isRelocatable()68   bool isRelocatable() { return true; }
69 
push_back(Elf64_Addr offset)70   void push_back(Elf64_Addr offset) {
71     // The format used for the packed relocations is SHT_RELR, described in
72     // https://groups.google.com/g/generic-abi/c/bX460iggiKg/m/Jnz1lgLJAgAJ
73     // The gist of it is that an address is recorded, and the following words,
74     // if their LSB is 1, represent a bitmap of word-size-spaced relocations
75     // at the addresses that follow. There can be multiple such bitmaps, such
76     // that very long streaks of (possibly spaced) relocations can be recorded
77     // in a very compact way.
78     for (;;) {
79       // [block_start; block_start + block_size] represents the range of offsets
80       // the current bitmap can record. If the offset doesn't fall in that
81       // range, or if doesn't align properly to be recorded, we record the
82       // bitmap, and slide the block corresponding to a new bitmap. If the
83       // offset doesn't fall in the range for the new bitmap, or if there wasn't
84       // an active bitmap in the first place, we record the offset and start a
85       // new bitmap for the block that follows it.
86       if (!block_start || offset < block_start ||
87           offset >= block_start + block_size ||
88           (offset - block_start) % shdr.sh_entsize) {
89         if (bitmap) {
90           relr.push_back((bitmap << 1) | 1);
91           block_start += block_size;
92           bitmap = 0;
93           continue;
94         }
95         relr.push_back(offset);
96         block_start = offset + shdr.sh_entsize;
97         break;
98       }
99       bitmap |= 1ULL << ((offset - block_start) / shdr.sh_entsize);
100       break;
101     }
102     shdr.sh_size = relr.size() * shdr.sh_entsize;
103   }
104 
105  private:
106   std::vector<Elf64_Addr> relr;
107   size_t block_size;
108   Elf64_Addr block_start = 0;
109   Elf64_Addr bitmap = 0;
110 };
111 
112 class ElfRelHackCode_Section : public ElfSection {
113  public:
ElfRelHackCode_Section(Elf_Shdr & s,Elf & e,ElfRelHack_Section & relhack_section,unsigned int init,unsigned int mprotect_cb,unsigned int sysconf_cb)114   ElfRelHackCode_Section(Elf_Shdr& s, Elf& e,
115                          ElfRelHack_Section& relhack_section, unsigned int init,
116                          unsigned int mprotect_cb, unsigned int sysconf_cb)
117       : ElfSection(s, nullptr, nullptr),
118         parent(e),
119         relhack_section(relhack_section),
120         init(init),
121         init_trampoline(nullptr),
122         mprotect_cb(mprotect_cb),
123         sysconf_cb(sysconf_cb) {
124     std::string file(rundir);
125     file += "/inject/";
126     switch (parent.getMachine()) {
127       case EM_386:
128         file += "x86";
129         break;
130       case EM_X86_64:
131         file += "x86_64";
132         break;
133       case EM_ARM:
134         file += "arm";
135         break;
136       case EM_AARCH64:
137         file += "aarch64";
138         break;
139       default:
140         throw std::runtime_error("unsupported architecture");
141     }
142     file += ".o";
143     std::ifstream inject(file.c_str(), std::ios::in | std::ios::binary);
144     elf = new Elf(inject);
145     if (elf->getType() != ET_REL)
146       throw std::runtime_error("object for injected code is not ET_REL");
147     if (elf->getMachine() != parent.getMachine())
148       throw std::runtime_error(
149           "architecture of object for injected code doesn't match");
150 
151     ElfSymtab_Section* symtab = nullptr;
152 
153     // Find the symbol table.
154     for (ElfSection* section = elf->getSection(1); section != nullptr;
155          section = section->getNext()) {
156       if (section->getType() == SHT_SYMTAB)
157         symtab = (ElfSymtab_Section*)section;
158     }
159     if (symtab == nullptr)
160       throw std::runtime_error(
161           "Couldn't find a symbol table for the injected code");
162 
163     relro = parent.getSegmentByType(PT_GNU_RELRO);
164 
165     // Find the init symbol
166     entry_point = -1;
167     std::string symbol = "init";
168     if (!init) symbol += "_noinit";
169     if (relro) symbol += "_relro";
170     Elf_SymValue* sym = symtab->lookup(symbol.c_str());
171     if (!sym)
172       throw std::runtime_error(
173           "Couldn't find an 'init' symbol in the injected code");
174 
175     entry_point = sym->value.getValue();
176 
177     // Get all relevant sections from the injected code object.
178     add_code_section(sym->value.getSection());
179 
180     // If the original init function is located too far away, we're going to
181     // need to use a trampoline. See comment in inject.c.
182     // Theoretically, we should check for (init - instr) > 0xffffff, where instr
183     // is the virtual address of the instruction that calls the original init,
184     // but we don't have it at this point, so punt to just init.
185     if (init > 0xffffff && parent.getMachine() == EM_ARM) {
186       Elf_SymValue* trampoline = symtab->lookup("init_trampoline");
187       if (!trampoline) {
188         throw std::runtime_error(
189             "Couldn't find an 'init_trampoline' symbol in the injected code");
190       }
191 
192       init_trampoline = trampoline->value.getSection();
193       add_code_section(init_trampoline);
194     }
195 
196     // Adjust code sections offsets according to their size
197     std::vector<ElfSection*>::iterator c = code.begin();
198     (*c)->getShdr().sh_addr = 0;
199     for (ElfSection* last = *(c++); c != code.end(); ++c) {
200       unsigned int addr = last->getShdr().sh_addr + last->getSize();
201       if (addr & ((*c)->getAddrAlign() - 1))
202         addr = (addr | ((*c)->getAddrAlign() - 1)) + 1;
203       (*c)->getShdr().sh_addr = addr;
204       // We need to align this section depending on the greater
205       // alignment required by code sections.
206       if (shdr.sh_addralign < (*c)->getAddrAlign())
207         shdr.sh_addralign = (*c)->getAddrAlign();
208       last = *c;
209     }
210     shdr.sh_size = code.back()->getAddr() + code.back()->getSize();
211     data = static_cast<char*>(malloc(shdr.sh_size));
212     if (!data) {
213       throw std::runtime_error("Could not malloc ElfSection data");
214     }
215     char* buf = data;
216     for (c = code.begin(); c != code.end(); ++c) {
217       memcpy(buf, (*c)->getData(), (*c)->getSize());
218       buf += (*c)->getSize();
219     }
220     name = elfhack_text;
221   }
222 
~ElfRelHackCode_Section()223   ~ElfRelHackCode_Section() { delete elf; }
224 
serialize(std::ofstream & file,unsigned char ei_class,unsigned char ei_data)225   void serialize(std::ofstream& file, unsigned char ei_class,
226                  unsigned char ei_data) override {
227     // Readjust code offsets
228     for (std::vector<ElfSection*>::iterator c = code.begin(); c != code.end();
229          ++c)
230       (*c)->getShdr().sh_addr += getAddr();
231 
232     // Apply relocations
233     for (std::vector<ElfSection*>::iterator c = code.begin(); c != code.end();
234          ++c) {
235       for (ElfSection* rel = elf->getSection(1); rel != nullptr;
236            rel = rel->getNext())
237         if (((rel->getType() == SHT_REL) || (rel->getType() == SHT_RELA)) &&
238             (rel->getInfo().section == *c)) {
239           if (rel->getType() == SHT_REL)
240             apply_relocations((ElfRel_Section<Elf_Rel>*)rel, *c);
241           else
242             apply_relocations((ElfRel_Section<Elf_Rela>*)rel, *c);
243         }
244     }
245 
246     ElfSection::serialize(file, ei_class, ei_data);
247   }
248 
isRelocatable()249   bool isRelocatable() override { return false; }
250 
getEntryPoint()251   unsigned int getEntryPoint() { return entry_point; }
252 
insertBefore(ElfSection * section,bool dirty=true)253   void insertBefore(ElfSection* section, bool dirty = true) override {
254     // Adjust the address so that this section is adjacent to the one it's
255     // being inserted before. This avoids creating holes which subsequently
256     // might lead the PHDR-adjusting code to create unnecessary additional
257     // PT_LOADs.
258     shdr.sh_addr =
259         (section->getAddr() - shdr.sh_size) & ~(shdr.sh_addralign - 1);
260     ElfSection::insertBefore(section, dirty);
261   }
262 
263  private:
add_code_section(ElfSection * section)264   void add_code_section(ElfSection* section) {
265     if (section) {
266       /* Don't add section if it's already been added in the past */
267       for (auto s = code.begin(); s != code.end(); ++s) {
268         if (section == *s) return;
269       }
270       code.push_back(section);
271       find_code(section);
272     }
273   }
274 
275   /* Look at the relocations associated to the given section to find other
276    * sections that it requires */
find_code(ElfSection * section)277   void find_code(ElfSection* section) {
278     for (ElfSection* s = elf->getSection(1); s != nullptr; s = s->getNext()) {
279       if (((s->getType() == SHT_REL) || (s->getType() == SHT_RELA)) &&
280           (s->getInfo().section == section)) {
281         if (s->getType() == SHT_REL)
282           scan_relocs_for_code((ElfRel_Section<Elf_Rel>*)s);
283         else
284           scan_relocs_for_code((ElfRel_Section<Elf_Rela>*)s);
285       }
286     }
287   }
288 
289   template <typename Rel_Type>
scan_relocs_for_code(ElfRel_Section<Rel_Type> * rel)290   void scan_relocs_for_code(ElfRel_Section<Rel_Type>* rel) {
291     ElfSymtab_Section* symtab = (ElfSymtab_Section*)rel->getLink();
292     for (auto r = rel->rels.begin(); r != rel->rels.end(); ++r) {
293       ElfSection* section =
294           symtab->syms[ELF64_R_SYM(r->r_info)].value.getSection();
295       add_code_section(section);
296     }
297   }
298 
299   // TODO: sort out which non-aarch64 relocation types should be using
300   //  `value` (even though in practice it's either 0 or the same as addend)
301   class pc32_relocation {
302    public:
operator ()(unsigned int base_addr,Elf64_Off offset,Elf64_Sxword addend,unsigned int addr,Elf64_Word value)303     Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
304                           Elf64_Sxword addend, unsigned int addr,
305                           Elf64_Word value) {
306       return addr + addend - offset - base_addr;
307     }
308   };
309 
310   class arm_plt32_relocation {
311    public:
operator ()(unsigned int base_addr,Elf64_Off offset,Elf64_Sxword addend,unsigned int addr,Elf64_Word value)312     Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
313                           Elf64_Sxword addend, unsigned int addr,
314                           Elf64_Word value) {
315       // We don't care about sign_extend because the only case where this is
316       // going to be used only jumps forward.
317       Elf32_Addr tmp = (Elf32_Addr)(addr - offset - base_addr) >> 2;
318       tmp = (addend + tmp) & 0x00ffffff;
319       return (addend & 0xff000000) | tmp;
320     }
321   };
322 
323   class arm_thm_jump24_relocation {
324    public:
operator ()(unsigned int base_addr,Elf64_Off offset,Elf64_Sxword addend,unsigned int addr,Elf64_Word value)325     Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
326                           Elf64_Sxword addend, unsigned int addr,
327                           Elf64_Word value) {
328       /* Follows description of b.w and bl instructions as per
329          ARM Architecture Reference Manual ARM® v7-A and ARM® v7-R edition,
330          A8.6.16 We limit ourselves to Encoding T4 of b.w and Encoding T1 of bl.
331          We don't care about sign_extend because the only case where this is
332          going to be used only jumps forward. */
333       Elf32_Addr tmp = (Elf32_Addr)(addr - offset - base_addr);
334       unsigned int word0 = addend & 0xffff, word1 = addend >> 16;
335 
336       /* Encoding T4 of B.W is 10x1 ; Encoding T1 of BL is 11x1. */
337       unsigned int type = (word1 & 0xd000) >> 12;
338       if (((word0 & 0xf800) != 0xf000) || ((type & 0x9) != 0x9))
339         throw std::runtime_error(
340             "R_ARM_THM_JUMP24/R_ARM_THM_CALL relocation only supported for B.W "
341             "<label> and BL <label>");
342 
343       /* When the target address points to ARM code, switch a BL to a
344        * BLX. This however can't be done with a B.W without adding a
345        * trampoline, which is not supported as of now. */
346       if ((addr & 0x1) == 0) {
347         if (type == 0x9)
348           throw std::runtime_error(
349               "R_ARM_THM_JUMP24/R_ARM_THM_CALL relocation only supported for "
350               "BL <label> when label points to ARM code");
351         /* The address of the target is always relative to a 4-bytes
352          * aligned address, so if the address of the BL instruction is
353          * not 4-bytes aligned, adjust for it. */
354         if ((base_addr + offset) & 0x2) tmp += 2;
355         /* Encoding T2 of BLX is 11x0. */
356         type = 0xc;
357       }
358 
359       unsigned int s = (word0 & (1 << 10)) >> 10;
360       unsigned int j1 = (word1 & (1 << 13)) >> 13;
361       unsigned int j2 = (word1 & (1 << 11)) >> 11;
362       unsigned int i1 = j1 ^ s ? 0 : 1;
363       unsigned int i2 = j2 ^ s ? 0 : 1;
364 
365       tmp += ((s << 24) | (i1 << 23) | (i2 << 22) | ((word0 & 0x3ff) << 12) |
366               ((word1 & 0x7ff) << 1));
367 
368       s = (tmp & (1 << 24)) >> 24;
369       j1 = ((tmp & (1 << 23)) >> 23) ^ !s;
370       j2 = ((tmp & (1 << 22)) >> 22) ^ !s;
371 
372       return 0xf000 | (s << 10) | ((tmp & (0x3ff << 12)) >> 12) | (type << 28) |
373              (j1 << 29) | (j2 << 27) | ((tmp & 0xffe) << 15);
374     }
375   };
376 
377   class gotoff_relocation {
378    public:
operator ()(unsigned int base_addr,Elf64_Off offset,Elf64_Sxword addend,unsigned int addr,Elf64_Word value)379     Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
380                           Elf64_Sxword addend, unsigned int addr,
381                           Elf64_Word value) {
382       return addr + addend;
383     }
384   };
385 
386   template <int start, int end>
387   class abs_lo12_nc_relocation {
388    public:
operator ()(unsigned int base_addr,Elf64_Off offset,Elf64_Sxword addend,unsigned int addr,Elf64_Word value)389     Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
390                           Elf64_Sxword addend, unsigned int addr,
391                           Elf64_Word value) {
392       // Fill the bits [end:start] of the immediate value in an ADD, LDR or STR
393       // instruction, at bits [21:10].
394       // per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture
395       // profile C5.6.4, C5.6.83 or C5.6.178 and ELF for the ARM® 64-bit
396       // Architecture (AArch64) 4.6.6, Table 4-9.
397       Elf64_Word mask = (1 << (end + 1)) - 1;
398       return value | (((((addr + addend) & mask) >> start) & 0xfff) << 10);
399     }
400   };
401 
402   class adr_prel_pg_hi21_relocation {
403    public:
operator ()(unsigned int base_addr,Elf64_Off offset,Elf64_Sxword addend,unsigned int addr,Elf64_Word value)404     Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
405                           Elf64_Sxword addend, unsigned int addr,
406                           Elf64_Word value) {
407       // Fill the bits [32:12] of the immediate value in a ADRP instruction,
408       // at bits [23:5]+[30:29].
409       // per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture
410       // profile C5.6.10 and ELF for the ARM® 64-bit Architecture
411       // (AArch64) 4.6.6, Table 4-9.
412       Elf64_Word imm = ((addr + addend) >> 12) - ((base_addr + offset) >> 12);
413       Elf64_Word immLo = (imm & 0x3) << 29;
414       Elf64_Word immHi = (imm & 0x1ffffc) << 3;
415       return value & 0x9f00001f | immLo | immHi;
416     }
417   };
418 
419   class call26_relocation {
420    public:
operator ()(unsigned int base_addr,Elf64_Off offset,Elf64_Sxword addend,unsigned int addr,Elf64_Word value)421     Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
422                           Elf64_Sxword addend, unsigned int addr,
423                           Elf64_Word value) {
424       // Fill the bits [27:2] of the immediate value in a BL instruction,
425       // at bits [25:0].
426       // per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture
427       // profile C5.6.26 and ELF for the ARM® 64-bit Architecture
428       // (AArch64) 4.6.6, Table 4-10.
429       return value | (((addr + addend - offset - base_addr) & 0x0ffffffc) >> 2);
430     }
431   };
432 
433   template <class relocation_type>
apply_relocation(ElfSection * the_code,char * base,Elf_Rel * r,unsigned int addr)434   void apply_relocation(ElfSection* the_code, char* base, Elf_Rel* r,
435                         unsigned int addr) {
436     relocation_type relocation;
437     Elf32_Addr value;
438     memcpy(&value, base + r->r_offset, 4);
439     value = relocation(the_code->getAddr(), r->r_offset, value, addr, value);
440     memcpy(base + r->r_offset, &value, 4);
441   }
442 
443   template <class relocation_type>
apply_relocation(ElfSection * the_code,char * base,Elf_Rela * r,unsigned int addr)444   void apply_relocation(ElfSection* the_code, char* base, Elf_Rela* r,
445                         unsigned int addr) {
446     relocation_type relocation;
447     Elf64_Word value;
448     memcpy(&value, base + r->r_offset, 4);
449     Elf32_Addr new_value =
450         relocation(the_code->getAddr(), r->r_offset, r->r_addend, addr, value);
451     memcpy(base + r->r_offset, &new_value, 4);
452   }
453 
454   template <typename Rel_Type>
apply_relocations(ElfRel_Section<Rel_Type> * rel,ElfSection * the_code)455   void apply_relocations(ElfRel_Section<Rel_Type>* rel, ElfSection* the_code) {
456     assert(rel->getType() == Rel_Type::sh_type);
457     char* buf = data + (the_code->getAddr() - code.front()->getAddr());
458     // TODO: various checks on the sections
459     ElfSymtab_Section* symtab = (ElfSymtab_Section*)rel->getLink();
460     for (typename std::vector<Rel_Type>::iterator r = rel->rels.begin();
461          r != rel->rels.end(); ++r) {
462       // TODO: various checks on the symbol
463       const char* name = symtab->syms[ELF64_R_SYM(r->r_info)].name;
464       unsigned int addr;
465       if (symtab->syms[ELF64_R_SYM(r->r_info)].value.getSection() == nullptr) {
466         if (strcmp(name, "relhack") == 0) {
467           addr = relhack_section.getAddr();
468         } else if (strcmp(name, "elf_header") == 0) {
469           // TODO: change this ungly hack to something better
470           ElfSection* ehdr = parent.getSection(1)->getPrevious()->getPrevious();
471           addr = ehdr->getAddr();
472         } else if (strcmp(name, "original_init") == 0) {
473           if (init_trampoline) {
474             addr = init_trampoline->getAddr();
475           } else {
476             addr = init;
477           }
478         } else if (strcmp(name, "real_original_init") == 0) {
479           addr = init;
480         } else if (relro && strcmp(name, "mprotect_cb") == 0) {
481           addr = mprotect_cb;
482         } else if (relro && strcmp(name, "sysconf_cb") == 0) {
483           addr = sysconf_cb;
484         } else if (relro && strcmp(name, "relro_start") == 0) {
485           addr = relro->getAddr();
486         } else if (relro && strcmp(name, "relro_end") == 0) {
487           addr = (relro->getAddr() + relro->getMemSize());
488         } else if (strcmp(name, "_GLOBAL_OFFSET_TABLE_") == 0) {
489           // We actually don't need a GOT, but need it as a reference for
490           // GOTOFF relocations. We'll just use the start of the ELF file
491           addr = 0;
492         } else if (strcmp(name, "") == 0) {
493           // This is for R_ARM_V4BX, until we find something better
494           addr = -1;
495         } else {
496           throw std::runtime_error("Unsupported symbol in relocation");
497         }
498       } else {
499         ElfSection* section =
500             symtab->syms[ELF64_R_SYM(r->r_info)].value.getSection();
501         assert((section->getType() == SHT_PROGBITS) &&
502                (section->getFlags() & SHF_EXECINSTR));
503         addr = symtab->syms[ELF64_R_SYM(r->r_info)].value.getValue();
504       }
505       // Do the relocation
506 #define REL(machine, type) (EM_##machine | (R_##machine##_##type << 8))
507       switch (elf->getMachine() | (ELF64_R_TYPE(r->r_info) << 8)) {
508         case REL(X86_64, PC32):
509         case REL(X86_64, PLT32):
510         case REL(386, PC32):
511         case REL(386, GOTPC):
512         case REL(ARM, GOTPC):
513         case REL(ARM, REL32):
514         case REL(AARCH64, PREL32):
515           apply_relocation<pc32_relocation>(the_code, buf, &*r, addr);
516           break;
517         case REL(ARM, CALL):
518         case REL(ARM, JUMP24):
519         case REL(ARM, PLT32):
520           apply_relocation<arm_plt32_relocation>(the_code, buf, &*r, addr);
521           break;
522         case REL(ARM, THM_PC22 /* THM_CALL */):
523         case REL(ARM, THM_JUMP24):
524           apply_relocation<arm_thm_jump24_relocation>(the_code, buf, &*r, addr);
525           break;
526         case REL(386, GOTOFF):
527         case REL(ARM, GOTOFF):
528           apply_relocation<gotoff_relocation>(the_code, buf, &*r, addr);
529           break;
530         case REL(AARCH64, ADD_ABS_LO12_NC):
531           apply_relocation<abs_lo12_nc_relocation<0, 11>>(the_code, buf, &*r,
532                                                           addr);
533           break;
534         case REL(AARCH64, ADR_PREL_PG_HI21):
535           apply_relocation<adr_prel_pg_hi21_relocation>(the_code, buf, &*r,
536                                                         addr);
537           break;
538         case REL(AARCH64, LDST32_ABS_LO12_NC):
539           apply_relocation<abs_lo12_nc_relocation<2, 11>>(the_code, buf, &*r,
540                                                           addr);
541           break;
542         case REL(AARCH64, LDST64_ABS_LO12_NC):
543           apply_relocation<abs_lo12_nc_relocation<3, 11>>(the_code, buf, &*r,
544                                                           addr);
545           break;
546         case REL(AARCH64, CALL26):
547           apply_relocation<call26_relocation>(the_code, buf, &*r, addr);
548           break;
549         case REL(ARM, V4BX):
550           // Ignore R_ARM_V4BX relocations
551           break;
552         default:
553           throw std::runtime_error("Unsupported relocation type");
554       }
555     }
556   }
557 
558   Elf *elf, &parent;
559   ElfRelHack_Section& relhack_section;
560   std::vector<ElfSection*> code;
561   unsigned int init;
562   ElfSection* init_trampoline;
563   unsigned int mprotect_cb;
564   unsigned int sysconf_cb;
565   int entry_point;
566   ElfSegment* relro;
567 };
568 
get_addend(Elf_Rel * rel,Elf * elf)569 unsigned int get_addend(Elf_Rel* rel, Elf* elf) {
570   ElfLocation loc(rel->r_offset, elf);
571   Elf_Addr addr(loc.getBuffer(), Elf_Addr::size(elf->getClass()),
572                 elf->getClass(), elf->getData());
573   return addr.value;
574 }
575 
get_addend(Elf_Rela * rel,Elf * elf)576 unsigned int get_addend(Elf_Rela* rel, Elf* elf) { return rel->r_addend; }
577 
set_relative_reloc(Elf_Rel * rel,Elf * elf,unsigned int value)578 void set_relative_reloc(Elf_Rel* rel, Elf* elf, unsigned int value) {
579   ElfLocation loc(rel->r_offset, elf);
580   Elf_Addr addr;
581   addr.value = value;
582   addr.serialize(const_cast<char*>(loc.getBuffer()),
583                  Elf_Addr::size(elf->getClass()), elf->getClass(),
584                  elf->getData());
585 }
586 
set_relative_reloc(Elf_Rela * rel,Elf * elf,unsigned int value)587 void set_relative_reloc(Elf_Rela* rel, Elf* elf, unsigned int value) {
588   // ld puts the value of relocated relocations both in the addend and
589   // at r_offset. For consistency, keep it that way.
590   set_relative_reloc((Elf_Rel*)rel, elf, value);
591   rel->r_addend = value;
592 }
593 
maybe_split_segment(Elf * elf,ElfSegment * segment)594 void maybe_split_segment(Elf* elf, ElfSegment* segment) {
595   std::list<ElfSection*>::iterator it = segment->begin();
596   for (ElfSection* last = *(it++); it != segment->end(); last = *(it++)) {
597     // When two consecutive non-SHT_NOBITS sections are apart by more
598     // than the alignment of the section, the second can be moved closer
599     // to the first, but this requires the segment to be split.
600     if (((*it)->getType() != SHT_NOBITS) && (last->getType() != SHT_NOBITS) &&
601         ((*it)->getOffset() - last->getOffset() - last->getSize() >
602          segment->getAlign())) {
603       // Probably very wrong.
604       Elf_Phdr phdr;
605       phdr.p_type = PT_LOAD;
606       phdr.p_vaddr = 0;
607       phdr.p_paddr = phdr.p_vaddr + segment->getVPDiff();
608       phdr.p_flags = segment->getFlags();
609       phdr.p_align = segment->getAlign();
610       phdr.p_filesz = (Elf64_Xword)-1LL;
611       phdr.p_memsz = (Elf64_Xword)-1LL;
612       ElfSegment* newSegment = new ElfSegment(&phdr);
613       elf->insertSegmentAfter(segment, newSegment);
614       for (; it != segment->end(); ++it) {
615         newSegment->addSection(*it);
616       }
617       for (it = newSegment->begin(); it != newSegment->end(); ++it) {
618         segment->removeSection(*it);
619       }
620       break;
621     }
622   }
623 }
624 
625 // EH_FRAME constants
626 static const unsigned char DW_EH_PE_absptr = 0x00;
627 static const unsigned char DW_EH_PE_omit = 0xff;
628 
629 // Data size
630 static const unsigned char DW_EH_PE_LEB128 = 0x01;
631 static const unsigned char DW_EH_PE_data2 = 0x02;
632 static const unsigned char DW_EH_PE_data4 = 0x03;
633 static const unsigned char DW_EH_PE_data8 = 0x04;
634 
635 // Data signedness
636 static const unsigned char DW_EH_PE_signed = 0x08;
637 
638 // Modifiers
639 static const unsigned char DW_EH_PE_pcrel = 0x10;
640 
641 // Return the data size part of the encoding value
encoding_data_size(unsigned char encoding)642 static unsigned char encoding_data_size(unsigned char encoding) {
643   return encoding & 0x07;
644 }
645 
646 // Advance `step` bytes in the buffer at `data` with size `size`, returning
647 // the advanced buffer pointer and remaining size.
648 // Returns true if step <= size.
advance_buffer(char ** data,size_t * size,size_t step)649 static bool advance_buffer(char** data, size_t* size, size_t step) {
650   if (step > *size) return false;
651 
652   *data += step;
653   *size -= step;
654   return true;
655 }
656 
657 // Advance in the given buffer, skipping the full length of the variable-length
658 // encoded LEB128 type in CIE/FDE data.
skip_LEB128(char ** data,size_t * size)659 static bool skip_LEB128(char** data, size_t* size) {
660   if (!*size) return false;
661 
662   while (*size && (*(*data)++ & (char)0x80)) {
663     (*size)--;
664   }
665   return true;
666 }
667 
668 // Advance in the given buffer, skipping the full length of a pointer encoded
669 // with the given encoding.
skip_eh_frame_pointer(char ** data,size_t * size,unsigned char encoding)670 static bool skip_eh_frame_pointer(char** data, size_t* size,
671                                   unsigned char encoding) {
672   switch (encoding_data_size(encoding)) {
673     case DW_EH_PE_data2:
674       return advance_buffer(data, size, 2);
675     case DW_EH_PE_data4:
676       return advance_buffer(data, size, 4);
677     case DW_EH_PE_data8:
678       return advance_buffer(data, size, 8);
679     case DW_EH_PE_LEB128:
680       return skip_LEB128(data, size);
681   }
682   throw std::runtime_error("unreachable");
683 }
684 
685 // Specialized implementations for adjust_eh_frame_pointer().
686 template <typename T>
adjust_eh_frame_sized_pointer(char ** data,size_t * size,ElfSection * eh_frame,unsigned int origAddr,Elf * elf)687 static bool adjust_eh_frame_sized_pointer(char** data, size_t* size,
688                                           ElfSection* eh_frame,
689                                           unsigned int origAddr, Elf* elf) {
690   if (*size < sizeof(T)) return false;
691 
692   serializable<FixedSizeData<T>> pointer(*data, *size, elf->getClass(),
693                                          elf->getData());
694   mozilla::CheckedInt<T> value = pointer.value;
695   if (origAddr < eh_frame->getAddr()) {
696     unsigned int diff = eh_frame->getAddr() - origAddr;
697     value -= diff;
698   } else {
699     unsigned int diff = origAddr - eh_frame->getAddr();
700     value += diff;
701   }
702   if (!value.isValid())
703     throw std::runtime_error("Overflow while adjusting eh_frame");
704   pointer.value = value.value();
705   pointer.serialize(*data, *size, elf->getClass(), elf->getData());
706   return advance_buffer(data, size, sizeof(T));
707 }
708 
709 // In the given eh_frame section, adjust the pointer with the given encoding,
710 // pointed to by the given buffer (`data`, `size`), considering the eh_frame
711 // section was originally at `origAddr`. Also advances in the buffer.
adjust_eh_frame_pointer(char ** data,size_t * size,unsigned char encoding,ElfSection * eh_frame,unsigned int origAddr,Elf * elf)712 static bool adjust_eh_frame_pointer(char** data, size_t* size,
713                                     unsigned char encoding,
714                                     ElfSection* eh_frame, unsigned int origAddr,
715                                     Elf* elf) {
716   if ((encoding & 0x70) != DW_EH_PE_pcrel)
717     return skip_eh_frame_pointer(data, size, encoding);
718 
719   if (encoding & DW_EH_PE_signed) {
720     switch (encoding_data_size(encoding)) {
721       case DW_EH_PE_data2:
722         return adjust_eh_frame_sized_pointer<int16_t>(data, size, eh_frame,
723                                                       origAddr, elf);
724       case DW_EH_PE_data4:
725         return adjust_eh_frame_sized_pointer<int32_t>(data, size, eh_frame,
726                                                       origAddr, elf);
727       case DW_EH_PE_data8:
728         return adjust_eh_frame_sized_pointer<int64_t>(data, size, eh_frame,
729                                                       origAddr, elf);
730     }
731   } else {
732     switch (encoding_data_size(encoding)) {
733       case DW_EH_PE_data2:
734         return adjust_eh_frame_sized_pointer<uint16_t>(data, size, eh_frame,
735                                                        origAddr, elf);
736       case DW_EH_PE_data4:
737         return adjust_eh_frame_sized_pointer<uint32_t>(data, size, eh_frame,
738                                                        origAddr, elf);
739       case DW_EH_PE_data8:
740         return adjust_eh_frame_sized_pointer<uint64_t>(data, size, eh_frame,
741                                                        origAddr, elf);
742     }
743   }
744 
745   throw std::runtime_error("Unsupported eh_frame pointer encoding");
746 }
747 
748 // The eh_frame section may contain "PC"-relative pointers. If we move the
749 // section, those need to be adjusted. Other type of pointers are relative to
750 // sections we don't touch.
adjust_eh_frame(ElfSection * eh_frame,unsigned int origAddr,Elf * elf)751 static void adjust_eh_frame(ElfSection* eh_frame, unsigned int origAddr,
752                             Elf* elf) {
753   if (eh_frame->getAddr() == origAddr)  // nothing to do;
754     return;
755 
756   char* data = const_cast<char*>(eh_frame->getData());
757   size_t size = eh_frame->getSize();
758   unsigned char LSDAencoding = DW_EH_PE_omit;
759   unsigned char FDEencoding = DW_EH_PE_absptr;
760   bool hasZ = false;
761 
762   // Decoding of eh_frame based on https://www.airs.com/blog/archives/460
763   while (size) {
764     if (size < sizeof(uint32_t)) goto malformed;
765 
766     serializable<FixedSizeData<uint32_t>> entryLength(
767         data, size, elf->getClass(), elf->getData());
768     if (!advance_buffer(&data, &size, sizeof(uint32_t))) goto malformed;
769 
770     char* cursor = data;
771     size_t length = entryLength.value;
772 
773     if (length == 0) {
774       continue;
775     }
776 
777     if (size < sizeof(uint32_t)) goto malformed;
778 
779     serializable<FixedSizeData<uint32_t>> id(data, size, elf->getClass(),
780                                              elf->getData());
781     if (!advance_buffer(&cursor, &length, sizeof(uint32_t))) goto malformed;
782 
783     if (id.value == 0) {
784       // This is a Common Information Entry
785       if (length < 2) goto malformed;
786       // Reset LSDA and FDE encodings, and hasZ for subsequent FDEs.
787       LSDAencoding = DW_EH_PE_omit;
788       FDEencoding = DW_EH_PE_absptr;
789       hasZ = false;
790       // CIE version. Should only be 1 or 3.
791       char version = *cursor++;
792       length--;
793       if (version != 1 && version != 3) {
794         throw std::runtime_error("Unsupported eh_frame version");
795       }
796       // NUL terminated string.
797       const char* augmentationString = cursor;
798       size_t l = strnlen(augmentationString, length - 1);
799       if (l == length - 1) goto malformed;
800       if (!advance_buffer(&cursor, &length, l + 1)) goto malformed;
801       // Skip code alignment factor (LEB128)
802       if (!skip_LEB128(&cursor, &length)) goto malformed;
803       // Skip data alignment factor (LEB128)
804       if (!skip_LEB128(&cursor, &length)) goto malformed;
805       // Skip return address register (single byte in CIE version 1, LEB128
806       // in CIE version 3)
807       if (version == 1) {
808         if (!advance_buffer(&cursor, &length, 1)) goto malformed;
809       } else {
810         if (!skip_LEB128(&cursor, &length)) goto malformed;
811       }
812       // Past this, it's data driven by the contents of the augmentation string.
813       for (size_t i = 0; i < l; i++) {
814         if (!length) goto malformed;
815         switch (augmentationString[i]) {
816           case 'z':
817             if (!skip_LEB128(&cursor, &length)) goto malformed;
818             hasZ = true;
819             break;
820           case 'L':
821             LSDAencoding = *cursor++;
822             length--;
823             break;
824           case 'R':
825             FDEencoding = *cursor++;
826             length--;
827             break;
828           case 'P': {
829             unsigned char encoding = (unsigned char)*cursor++;
830             length--;
831             if (!adjust_eh_frame_pointer(&cursor, &length, encoding, eh_frame,
832                                          origAddr, elf))
833               goto malformed;
834           } break;
835           default:
836             goto malformed;
837         }
838       }
839     } else {
840       // This is a Frame Description Entry
841       // Starting address
842       if (!adjust_eh_frame_pointer(&cursor, &length, FDEencoding, eh_frame,
843                                    origAddr, elf))
844         goto malformed;
845 
846       if (LSDAencoding != DW_EH_PE_omit) {
847         // Skip number of bytes, same size as the starting address.
848         if (!skip_eh_frame_pointer(&cursor, &length, FDEencoding))
849           goto malformed;
850         if (hasZ) {
851           if (!skip_LEB128(&cursor, &length)) goto malformed;
852         }
853         // pointer to the LSDA.
854         if (!adjust_eh_frame_pointer(&cursor, &length, LSDAencoding, eh_frame,
855                                      origAddr, elf))
856           goto malformed;
857       }
858     }
859 
860     data += entryLength.value;
861     size -= entryLength.value;
862   }
863   return;
864 
865 malformed:
866   throw std::runtime_error("malformed .eh_frame");
867 }
868 
869 template <typename Rel_Type>
do_relocation_section(Elf * elf,unsigned int rel_type,unsigned int rel_type2,bool force)870 int do_relocation_section(Elf* elf, unsigned int rel_type,
871                           unsigned int rel_type2, bool force) {
872   ElfDynamic_Section* dyn = elf->getDynSection();
873   if (dyn == nullptr) {
874     fprintf(stderr, "Couldn't find SHT_DYNAMIC section\n");
875     return -1;
876   }
877 
878   ElfRel_Section<Rel_Type>* section =
879       (ElfRel_Section<Rel_Type>*)dyn->getSectionForType(Rel_Type::d_tag);
880   if (section == nullptr) {
881     fprintf(stderr, "No relocations\n");
882     return -1;
883   }
884   assert(section->getType() == Rel_Type::sh_type);
885 
886   Elf64_Shdr relhack64_section = {0,
887                                   SHT_PROGBITS,
888                                   SHF_ALLOC,
889                                   0,
890                                   (Elf64_Off)-1LL,
891                                   0,
892                                   SHN_UNDEF,
893                                   0,
894                                   Elf_Addr::size(elf->getClass()),
895                                   Elf_Addr::size(elf->getClass())};
896   Elf64_Shdr relhackcode64_section = {0,
897                                       SHT_PROGBITS,
898                                       SHF_ALLOC | SHF_EXECINSTR,
899                                       0,
900                                       (Elf64_Off)-1LL,
901                                       0,
902                                       SHN_UNDEF,
903                                       0,
904                                       1,
905                                       0};
906 
907   unsigned int entry_sz = Elf_Addr::size(elf->getClass());
908 
909   // The injected code needs to be executed before any init code in the
910   // binary. There are three possible cases:
911   // - The binary has no init code at all. In this case, we will add a
912   //   DT_INIT entry pointing to the injected code.
913   // - The binary has a DT_INIT entry. In this case, we will interpose:
914   //   we change DT_INIT to point to the injected code, and have the
915   //   injected code call the original DT_INIT entry point.
916   // - The binary has no DT_INIT entry, but has a DT_INIT_ARRAY. In this
917   //   case, we interpose as well, by replacing the first entry in the
918   //   array to point to the injected code, and have the injected code
919   //   call the original first entry.
920   // The binary may have .ctors instead of DT_INIT_ARRAY, for its init
921   // functions, but this falls into the second case above, since .ctors
922   // are actually run by DT_INIT code.
923   ElfValue* value = dyn->getValueForType(DT_INIT);
924   unsigned int original_init = value ? value->getValue() : 0;
925   ElfSection* init_array = nullptr;
926   if (!value || !value->getValue()) {
927     value = dyn->getValueForType(DT_INIT_ARRAYSZ);
928     if (value && value->getValue() >= entry_sz)
929       init_array = dyn->getSectionForType(DT_INIT_ARRAY);
930   }
931 
932   Elf_Shdr relhack_section(relhack64_section);
933   Elf_Shdr relhackcode_section(relhackcode64_section);
934   ElfRelHack_Section* relhack = new ElfRelHack_Section(relhack_section);
935 
936   ElfSymtab_Section* symtab = (ElfSymtab_Section*)section->getLink();
937   Elf_SymValue* sym = symtab->lookup("__cxa_pure_virtual");
938 
939   std::vector<Rel_Type> new_rels;
940   std::vector<Rel_Type> init_array_relocs;
941   size_t init_array_insert = 0;
942   for (typename std::vector<Rel_Type>::iterator i = section->rels.begin();
943        i != section->rels.end(); ++i) {
944     // We don't need to keep R_*_NONE relocations
945     if (!ELF64_R_TYPE(i->r_info)) continue;
946     ElfLocation loc(i->r_offset, elf);
947     // __cxa_pure_virtual is a function used in vtables to point at pure
948     // virtual methods. The __cxa_pure_virtual function usually abort()s.
949     // These functions are however normally never called. In the case
950     // where they would, jumping to the null address instead of calling
951     // __cxa_pure_virtual is going to work just as well. So we can remove
952     // relocations for the __cxa_pure_virtual symbol and null out the
953     // content at the offset pointed by the relocation.
954     if (sym) {
955       if (sym->defined) {
956         // If we are statically linked to libstdc++, the
957         // __cxa_pure_virtual symbol is defined in our lib, and we
958         // have relative relocations (rel_type) for it.
959         if (ELF64_R_TYPE(i->r_info) == rel_type) {
960           Elf_Addr addr(loc.getBuffer(), entry_sz, elf->getClass(),
961                         elf->getData());
962           if (addr.value == sym->value.getValue()) {
963             memset((char*)loc.getBuffer(), 0, entry_sz);
964             continue;
965           }
966         }
967       } else {
968         // If we are dynamically linked to libstdc++, the
969         // __cxa_pure_virtual symbol is undefined in our lib, and we
970         // have absolute relocations (rel_type2) for it.
971         if ((ELF64_R_TYPE(i->r_info) == rel_type2) &&
972             (sym == &symtab->syms[ELF64_R_SYM(i->r_info)])) {
973           memset((char*)loc.getBuffer(), 0, entry_sz);
974           continue;
975         }
976       }
977     }
978     // Keep track of the relocations associated with the init_array section.
979     if (init_array && i->r_offset >= init_array->getAddr() &&
980         i->r_offset < init_array->getAddr() + init_array->getSize()) {
981       init_array_relocs.push_back(*i);
982       init_array_insert = new_rels.size();
983     } else if (!(loc.getSection()->getFlags() & SHF_WRITE) ||
984                (ELF64_R_TYPE(i->r_info) != rel_type)) {
985       // Don't pack relocations happening in non writable sections.
986       // Our injected code is likely not to be allowed to write there.
987       new_rels.push_back(*i);
988     } else if (i->r_offset & 1) {
989       // RELR packing doesn't support relocations at an odd address, but
990       // there shouldn't be any.
991       new_rels.push_back(*i);
992     } else {
993       // With Elf_Rel, the value pointed by the relocation offset is the addend.
994       // With Elf_Rela, the addend is in the relocation entry, but the elfhacked
995       // relocation info doesn't contain it. Elfhack relies on the value pointed
996       // by the relocation offset to also contain the addend. Which is true with
997       // BFD ld and gold, but not lld, which leaves that nulled out. So if that
998       // value is nulled out, we update it to the addend.
999       Elf_Addr addr(loc.getBuffer(), entry_sz, elf->getClass(), elf->getData());
1000       unsigned int addend = get_addend(&*i, elf);
1001       if (addr.value == 0) {
1002         addr.value = addend;
1003         addr.serialize(const_cast<char*>(loc.getBuffer()), entry_sz,
1004                        elf->getClass(), elf->getData());
1005       } else if (addr.value != addend) {
1006         fprintf(stderr,
1007                 "Relocation addend inconsistent with content. Skipping\n");
1008         return -1;
1009       }
1010       relhack->push_back(i->r_offset);
1011     }
1012   }
1013   // Last entry must be a nullptr
1014   relhack->push_back(0);
1015 
1016   if (init_array) {
1017     // Some linkers create a DT_INIT_ARRAY section that, for all purposes,
1018     // is empty: it only contains 0x0 or 0xffffffff pointers with no
1019     // relocations. In some other cases, there can be null pointers with no
1020     // relocations in the middle of the section. Example: crtend_so.o in the
1021     // Android NDK contains a sized .init_array with a null pointer and no
1022     // relocation, which ends up in all Android libraries, and in some cases it
1023     // ends up in the middle of the final .init_array section. If we have such a
1024     // reusable slot at the beginning of .init_array, we just use it. It we have
1025     // one in the middle of .init_array, we slide its content to move the "hole"
1026     // at the beginning and use it there (we need our injected code to run
1027     // before any other). Otherwise, replace the first entry and keep the
1028     // original pointer.
1029     std::sort(init_array_relocs.begin(), init_array_relocs.end(),
1030               [](Rel_Type& a, Rel_Type& b) { return a.r_offset < b.r_offset; });
1031     size_t expected = init_array->getAddr();
1032     const size_t zero = 0;
1033     const size_t all = SIZE_MAX;
1034     const char* data = init_array->getData();
1035     size_t length = Elf_Addr::size(elf->getClass());
1036     size_t off = 0;
1037     for (; off < init_array_relocs.size(); off++) {
1038       auto& r = init_array_relocs[off];
1039       if (r.r_offset >= expected + length &&
1040           (memcmp(data + off * length, &zero, length) == 0 ||
1041            memcmp(data + off * length, &all, length) == 0)) {
1042         // We found a hole, move the preceding entries.
1043         while (off) {
1044           auto& p = init_array_relocs[--off];
1045           if (ELF64_R_TYPE(p.r_info) == rel_type) {
1046             unsigned int addend = get_addend(&p, elf);
1047             p.r_offset += length;
1048             set_relative_reloc(&p, elf, addend);
1049           } else {
1050             fprintf(stderr,
1051                     "Unsupported relocation type in DT_INIT_ARRAY. Skipping\n");
1052             return -1;
1053           }
1054         }
1055         break;
1056       }
1057       expected = r.r_offset + length;
1058     }
1059 
1060     if (off == 0) {
1061       // We either found a hole above, and can now use the first entry,
1062       // or the init_array section is effectively empty (see further above)
1063       // and we also can use the first entry.
1064       // Either way, code further below will take care of actually setting
1065       // the right r_info and r_added for the relocation.
1066       Rel_Type rel;
1067       rel.r_offset = init_array->getAddr();
1068       init_array_relocs.insert(init_array_relocs.begin(), rel);
1069     } else {
1070       // Use relocated value of DT_INIT_ARRAY's first entry for the
1071       // function to be called by the injected code.
1072       auto& rel = init_array_relocs[0];
1073       unsigned int addend = get_addend(&rel, elf);
1074       if (ELF64_R_TYPE(rel.r_info) == rel_type) {
1075         original_init = addend;
1076       } else if (ELF64_R_TYPE(rel.r_info) == rel_type2) {
1077         ElfSymtab_Section* symtab = (ElfSymtab_Section*)section->getLink();
1078         original_init =
1079             symtab->syms[ELF64_R_SYM(rel.r_info)].value.getValue() + addend;
1080       } else {
1081         fprintf(stderr,
1082                 "Unsupported relocation type for DT_INIT_ARRAY's first entry. "
1083                 "Skipping\n");
1084         return -1;
1085       }
1086     }
1087 
1088     new_rels.insert(std::next(new_rels.begin(), init_array_insert),
1089                     init_array_relocs.begin(), init_array_relocs.end());
1090   }
1091 
1092   unsigned int mprotect_cb = 0;
1093   unsigned int sysconf_cb = 0;
1094   // If there is a relro segment, our injected code will run after the linker
1095   // sets the corresponding pages read-only. We need to make our code change
1096   // that to read-write before applying relocations, which means it needs to
1097   // call mprotect. To do that, we need to find a reference to the mprotect
1098   // symbol. In case the library already has one, we use that, but otherwise, we
1099   // add the symbol. Then the injected code needs to be able to call the
1100   // corresponding function, which means it needs access to a pointer to it. We
1101   // get such a pointer by making the linker apply a relocation for the symbol
1102   // at an address our code can read. The problem here is that there is not much
1103   // relocated space where we can put such a pointer, so we abuse the bss
1104   // section temporarily (it will be restored to a null value before any code
1105   // can actually use it)
1106   if (elf->getSegmentByType(PT_GNU_RELRO)) {
1107     ElfSection* gnu_versym = dyn->getSectionForType(DT_VERSYM);
1108     auto lookup = [&symtab, &gnu_versym](const char* symbol) {
1109       Elf_SymValue* sym_value = symtab->lookup(symbol, STT(FUNC));
1110       if (!sym_value) {
1111         symtab->syms.emplace_back();
1112         sym_value = &symtab->syms.back();
1113         symtab->grow(symtab->syms.size() * symtab->getEntSize());
1114         sym_value->name =
1115             ((ElfStrtab_Section*)symtab->getLink())->getStr(symbol);
1116         sym_value->info = ELF64_ST_INFO(STB_GLOBAL, STT_FUNC);
1117         sym_value->other = STV_DEFAULT;
1118         new (&sym_value->value) ElfLocation(nullptr, 0, ElfLocation::ABSOLUTE);
1119         sym_value->size = 0;
1120         sym_value->defined = false;
1121 
1122         // The DT_VERSYM data (in the .gnu.version section) has the same number
1123         // of entries as the symbols table. Since we added one entry there, we
1124         // need to add one entry here. Zeroes in the extra data means no version
1125         // for that symbol, which is the simplest thing to do.
1126         if (gnu_versym) {
1127           gnu_versym->grow(gnu_versym->getSize() + gnu_versym->getEntSize());
1128         }
1129       }
1130       return sym_value;
1131     };
1132 
1133     Elf_SymValue* mprotect = lookup("mprotect");
1134     Elf_SymValue* sysconf = lookup("sysconf");
1135 
1136     // Add relocations for the mprotect and sysconf symbols.
1137     auto add_relocation_to = [&new_rels, &symtab, rel_type2](
1138                                  Elf_SymValue* symbol, unsigned int location) {
1139       new_rels.emplace_back();
1140       Rel_Type& rel = new_rels.back();
1141       memset(&rel, 0, sizeof(rel));
1142       rel.r_info = ELF64_R_INFO(
1143           std::distance(symtab->syms.begin(),
1144                         std::vector<Elf_SymValue>::iterator(symbol)),
1145           rel_type2);
1146       rel.r_offset = location;
1147       return location;
1148     };
1149 
1150     // Find the beginning of the bss section, and use an aligned location in
1151     // there for the relocation.
1152     for (ElfSection* s = elf->getSection(1); s != nullptr; s = s->getNext()) {
1153       if (s->getType() != SHT_NOBITS ||
1154           (s->getFlags() & (SHF_TLS | SHF_WRITE)) != SHF_WRITE) {
1155         continue;
1156       }
1157       size_t ptr_size = Elf_Addr::size(elf->getClass());
1158       size_t usable_start = (s->getAddr() + ptr_size - 1) & ~(ptr_size - 1);
1159       size_t usable_end = (s->getAddr() + s->getSize()) & ~(ptr_size - 1);
1160       if (usable_end - usable_start >= 2 * ptr_size) {
1161         mprotect_cb = add_relocation_to(mprotect, usable_start);
1162         sysconf_cb = add_relocation_to(sysconf, usable_start + ptr_size);
1163         break;
1164       }
1165     }
1166 
1167     if (mprotect_cb == 0 || sysconf_cb == 0) {
1168       fprintf(stderr, "Couldn't find .bss. Skipping\n");
1169       return -1;
1170     }
1171   }
1172 
1173   size_t old_size = section->getSize();
1174 
1175   section->rels.assign(new_rels.begin(), new_rels.end());
1176   section->shrink(new_rels.size() * section->getEntSize());
1177 
1178   ElfRelHackCode_Section* relhackcode =
1179       new ElfRelHackCode_Section(relhackcode_section, *elf, *relhack,
1180                                  original_init, mprotect_cb, sysconf_cb);
1181   // Find the first executable section, and insert the relhack code before
1182   // that. The relhack data is inserted between .rel.dyn and .rel.plt.
1183   ElfSection* first_executable = nullptr;
1184   for (ElfSection* s = elf->getSection(1); s != nullptr; s = s->getNext()) {
1185     if (s->getFlags() & SHF_EXECINSTR) {
1186       first_executable = s;
1187       break;
1188     }
1189   }
1190 
1191   if (!first_executable) {
1192     fprintf(stderr, "Couldn't find executable section. Skipping\n");
1193     return -1;
1194   }
1195 
1196   relhack->insertBefore(section);
1197   relhackcode->insertBefore(first_executable);
1198 
1199   // Don't try further if we can't gain from the relocation section size change.
1200   // We account for the fact we're going to split the PT_LOAD before the
1201   // injected code section, so the overhead of the page alignment for section
1202   // needs to be accounted for.
1203   size_t align = first_executable->getSegmentByType(PT_LOAD)->getAlign();
1204   size_t new_size = relhack->getSize() + section->getSize() +
1205                     relhackcode->getSize() +
1206                     (relhackcode->getAddr() & (align - 1));
1207   if (!force && (new_size >= old_size || old_size - new_size < align)) {
1208     fprintf(stderr, "No gain. Skipping\n");
1209     return -1;
1210   }
1211 
1212   // .eh_frame/.eh_frame_hdr may be between the relocation sections and the
1213   // executable sections. When that happens, we may end up creating a separate
1214   // PT_LOAD for just both of them because they are not considered relocatable.
1215   // But they are, in fact, kind of relocatable, albeit with some manual work.
1216   // Which we'll do here.
1217   ElfSegment* eh_frame_segment = elf->getSegmentByType(PT_GNU_EH_FRAME);
1218   ElfSection* eh_frame_hdr =
1219       eh_frame_segment ? eh_frame_segment->getFirstSection() : nullptr;
1220   // The .eh_frame section usually follows the eh_frame_hdr section.
1221   ElfSection* eh_frame = eh_frame_hdr ? eh_frame_hdr->getNext() : nullptr;
1222   ElfSection* first = eh_frame_hdr;
1223   ElfSection* second = eh_frame;
1224   if (eh_frame && strcmp(eh_frame->getName(), ".eh_frame")) {
1225     // But sometimes it appears *before* the eh_frame_hdr section.
1226     eh_frame = eh_frame_hdr->getPrevious();
1227     first = eh_frame;
1228     second = eh_frame_hdr;
1229   }
1230   if (eh_frame_hdr && (!eh_frame || strcmp(eh_frame->getName(), ".eh_frame"))) {
1231     throw std::runtime_error(
1232         "Expected to find an .eh_frame section adjacent to .eh_frame_hdr");
1233   }
1234   if (eh_frame && first->getAddr() > relhack->getAddr() &&
1235       second->getAddr() < first_executable->getAddr()) {
1236     // The distance between both sections needs to be preserved because
1237     // eh_frame_hdr contains relative offsets to eh_frame. Well, they could be
1238     // relocated too, but it's not worth the effort for the few number of bytes
1239     // this would save.
1240     unsigned int distance = second->getAddr() - first->getAddr();
1241     unsigned int origAddr = eh_frame->getAddr();
1242     ElfSection* previous = first->getPrevious();
1243     first->getShdr().sh_addr = (previous->getAddr() + previous->getSize() +
1244                                 first->getAddrAlign() - 1) &
1245                                ~(first->getAddrAlign() - 1);
1246     second->getShdr().sh_addr =
1247         (first->getAddr() + std::min(first->getSize(), distance) +
1248          second->getAddrAlign() - 1) &
1249         ~(second->getAddrAlign() - 1);
1250     // Re-adjust to keep the original distance.
1251     // If the first section has a smaller alignment requirement than the second,
1252     // the second will be farther away, so we need to adjust the first.
1253     // If the second section has a smaller alignment requirement than the first,
1254     // it will already be at the right distance.
1255     first->getShdr().sh_addr = second->getAddr() - distance;
1256     assert(distance == second->getAddr() - first->getAddr());
1257     first->markDirty();
1258     adjust_eh_frame(eh_frame, origAddr, elf);
1259   }
1260 
1261   // Adjust PT_LOAD segments
1262   for (ElfSegment* segment = elf->getSegmentByType(PT_LOAD); segment;
1263        segment = elf->getSegmentByType(PT_LOAD, segment)) {
1264     maybe_split_segment(elf, segment);
1265   }
1266 
1267   // Ensure Elf sections will be at their final location.
1268   elf->normalize();
1269   ElfLocation* init =
1270       new ElfLocation(relhackcode, relhackcode->getEntryPoint());
1271   if (init_array) {
1272     // Adjust the first DT_INIT_ARRAY entry to point at the injected code
1273     // by transforming its relocation into a relative one pointing to the
1274     // address of the injected code.
1275     Rel_Type* rel = &section->rels[init_array_insert];
1276     rel->r_info = ELF64_R_INFO(0, rel_type);  // Set as a relative relocation
1277     set_relative_reloc(rel, elf, init->getValue());
1278   } else if (!dyn->setValueForType(DT_INIT, init)) {
1279     fprintf(stderr, "Can't grow .dynamic section to set DT_INIT. Skipping\n");
1280     return -1;
1281   }
1282   // TODO: adjust the value according to the remaining number of relative
1283   // relocations
1284   if (dyn->getValueForType(Rel_Type::d_tag_count))
1285     dyn->setValueForType(Rel_Type::d_tag_count, new ElfPlainValue(0));
1286 
1287   return 0;
1288 }
1289 
backup_file(const char * name)1290 static inline int backup_file(const char* name) {
1291   std::string fname(name);
1292   fname += ".bak";
1293   return rename(name, fname.c_str());
1294 }
1295 
do_file(const char * name,bool backup=false,bool force=false)1296 void do_file(const char* name, bool backup = false, bool force = false) {
1297   std::ifstream file(name, std::ios::in | std::ios::binary);
1298   Elf elf(file);
1299   unsigned int size = elf.getSize();
1300   fprintf(stderr, "%s: ", name);
1301   if (elf.getType() != ET_DYN) {
1302     fprintf(stderr, "Not a shared object. Skipping\n");
1303     return;
1304   }
1305 
1306   for (ElfSection* section = elf.getSection(1); section != nullptr;
1307        section = section->getNext()) {
1308     if (section->getName() &&
1309         (strncmp(section->getName(), ".elfhack.", 9) == 0)) {
1310       fprintf(stderr, "Already elfhacked. Skipping\n");
1311       return;
1312     }
1313   }
1314 
1315   int exit = -1;
1316   switch (elf.getMachine()) {
1317     case EM_386:
1318       exit =
1319           do_relocation_section<Elf_Rel>(&elf, R_386_RELATIVE, R_386_32, force);
1320       break;
1321     case EM_X86_64:
1322       exit = do_relocation_section<Elf_Rela>(&elf, R_X86_64_RELATIVE,
1323                                              R_X86_64_64, force);
1324       break;
1325     case EM_ARM:
1326       exit = do_relocation_section<Elf_Rel>(&elf, R_ARM_RELATIVE, R_ARM_ABS32,
1327                                             force);
1328       break;
1329     case EM_AARCH64:
1330       exit = do_relocation_section<Elf_Rela>(&elf, R_AARCH64_RELATIVE,
1331                                              R_AARCH64_ABS64, force);
1332       break;
1333     default:
1334       throw std::runtime_error("unsupported architecture");
1335   }
1336   if (exit == 0) {
1337     if (!force && (elf.getSize() >= size)) {
1338       fprintf(stderr, "No gain. Skipping\n");
1339     } else if (backup && backup_file(name) != 0) {
1340       fprintf(stderr, "Couln't create backup file\n");
1341     } else {
1342       std::ofstream ofile(name,
1343                           std::ios::out | std::ios::binary | std::ios::trunc);
1344       elf.write(ofile);
1345       fprintf(stderr, "Reduced by %d bytes\n", size - elf.getSize());
1346     }
1347   }
1348 }
1349 
undo_file(const char * name,bool backup=false)1350 void undo_file(const char* name, bool backup = false) {
1351   std::ifstream file(name, std::ios::in | std::ios::binary);
1352   Elf elf(file);
1353   unsigned int size = elf.getSize();
1354   fprintf(stderr, "%s: ", name);
1355   if (elf.getType() != ET_DYN) {
1356     fprintf(stderr, "Not a shared object. Skipping\n");
1357     return;
1358   }
1359 
1360   ElfSection *data = nullptr, *text = nullptr;
1361   for (ElfSection* section = elf.getSection(1); section != nullptr;
1362        section = section->getNext()) {
1363     if (section->getName() && (strcmp(section->getName(), elfhack_data) == 0))
1364       data = section;
1365     if (section->getName() && (strcmp(section->getName(), elfhack_text) == 0))
1366       text = section;
1367   }
1368 
1369   if (!data || !text) {
1370     fprintf(stderr, "Not elfhacked. Skipping\n");
1371     return;
1372   }
1373 
1374   // When both elfhack sections are in the same segment, try to merge
1375   // the segment that contains them both and the following segment.
1376   // When the elfhack sections are in separate segments, try to merge
1377   // those segments.
1378   ElfSegment* first = data->getSegmentByType(PT_LOAD);
1379   ElfSegment* second = text->getSegmentByType(PT_LOAD);
1380   if (first == second) {
1381     second = elf.getSegmentByType(PT_LOAD, first);
1382   }
1383 
1384   // Only merge the segments when their flags match.
1385   if (second->getFlags() != first->getFlags()) {
1386     fprintf(stderr, "Couldn't merge PT_LOAD segments. Skipping\n");
1387     return;
1388   }
1389   // Move sections from the second PT_LOAD to the first, and remove the
1390   // second PT_LOAD segment.
1391   for (std::list<ElfSection*>::iterator section = second->begin();
1392        section != second->end(); ++section)
1393     first->addSection(*section);
1394 
1395   elf.removeSegment(second);
1396   elf.normalize();
1397 
1398   if (backup && backup_file(name) != 0) {
1399     fprintf(stderr, "Couln't create backup file\n");
1400   } else {
1401     std::ofstream ofile(name,
1402                         std::ios::out | std::ios::binary | std::ios::trunc);
1403     elf.write(ofile);
1404     fprintf(stderr, "Grown by %d bytes\n", elf.getSize() - size);
1405   }
1406 }
1407 
main(int argc,char * argv[])1408 int main(int argc, char* argv[]) {
1409   int arg;
1410   bool backup = false;
1411   bool force = false;
1412   bool revert = false;
1413   char* lastSlash = rindex(argv[0], '/');
1414   if (lastSlash != nullptr) rundir = strndup(argv[0], lastSlash - argv[0]);
1415   for (arg = 1; arg < argc; arg++) {
1416     if (strcmp(argv[arg], "-f") == 0)
1417       force = true;
1418     else if (strcmp(argv[arg], "-b") == 0)
1419       backup = true;
1420     else if (strcmp(argv[arg], "-r") == 0)
1421       revert = true;
1422     else if (revert) {
1423       undo_file(argv[arg], backup);
1424     } else
1425       do_file(argv[arg], backup, force);
1426   }
1427 
1428   free(rundir);
1429   return 0;
1430 }
1431