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