elfparser.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  1. /*
  2. * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. #include "elfparser.h"
  32. #include "cpputil.h"
  33. #include "se_trace.h"
  34. #include "se_memcpy.h"
  35. #include "global_data.h"
  36. #include <sys/mman.h>
  37. #include <vector>
  38. #include <tuple>
  39. namespace {
  40. /** the callback function to filter a section.
  41. *
  42. * @shstrtab: the section header string table
  43. * @shdr: the current section header to be examined
  44. * @user_data: user supplied data for the callback
  45. *
  46. * @return: true if current section header is what we are looking for.
  47. */
  48. typedef bool (* section_filter_f)(const char* shstrtab,
  49. const ElfW(Shdr)* shdr,
  50. const void* user_data);
  51. bool compare_section_name(const char* shstrtab,
  52. const ElfW(Shdr)* shdr,
  53. const void* user_data)
  54. {
  55. // `shstrtab + shdr->sh_name' is the section name.
  56. return (!strcmp(shstrtab + shdr->sh_name, (const char*)user_data));
  57. }
  58. bool compare_section_addr(const char* shstrtab,
  59. const ElfW(Shdr)* shdr,
  60. const void* user_data)
  61. {
  62. UNUSED(shstrtab);
  63. return (shdr->sh_addr == (ElfW(Addr))(size_t)user_data);
  64. }
  65. const ElfW(Shdr)* get_section(const ElfW(Ehdr) *elf_hdr,
  66. section_filter_f f,
  67. const void* user_data)
  68. {
  69. const ElfW(Shdr) *shdr = GET_PTR(ElfW(Shdr), elf_hdr, elf_hdr->e_shoff);
  70. assert(sizeof(ElfW(Shdr)) == elf_hdr->e_shentsize);
  71. // section header string table
  72. const char *shstrtab = GET_PTR(char, elf_hdr, shdr[elf_hdr->e_shstrndx].sh_offset);
  73. for (unsigned idx = 0; idx < elf_hdr->e_shnum; ++idx, ++shdr)
  74. {
  75. SE_TRACE(SE_TRACE_DEBUG, "section [%u] %s: sh_addr = %x, sh_size = %x, sh_offset = %x, sh_name = %x\n",
  76. idx, shstrtab + shdr->sh_name, shdr->sh_addr, shdr->sh_size, shdr->sh_offset, shdr->sh_name);
  77. if (f(shstrtab, shdr, user_data))
  78. return shdr;
  79. }
  80. return NULL;
  81. }
  82. const ElfW(Shdr)* get_section_by_name(const ElfW(Ehdr) *elf_hdr, const char *name)
  83. {
  84. return get_section(elf_hdr, compare_section_name, name);
  85. }
  86. const ElfW(Shdr)* get_section_by_addr(const ElfW(Ehdr) *elf_hdr, ElfW(Addr) start_addr)
  87. {
  88. return get_section(elf_hdr, compare_section_addr, (const void*)(size_t)start_addr);
  89. }
  90. template <typename T>
  91. const T* get_section_raw_data(const ElfW(Ehdr) *elf_hdr, ElfW(Addr) start_addr)
  92. {
  93. const ElfW(Shdr)* shdr = get_section_by_addr(elf_hdr, start_addr);
  94. if (shdr == NULL)
  95. return NULL;
  96. return GET_PTR(T, elf_hdr, shdr->sh_offset);
  97. }
  98. bool validate_elf_header(const ElfW(Ehdr) *elf_hdr)
  99. {
  100. // validate magic number
  101. if (memcmp(&elf_hdr->e_ident, ELFMAG, SELFMAG))
  102. return false;
  103. #if RTS_SYSTEM_WORDSIZE == 64
  104. if (ELFCLASS64 != elf_hdr->e_ident[EI_CLASS])
  105. return false;
  106. #else
  107. if (ELFCLASS32 != elf_hdr->e_ident[EI_CLASS])
  108. return false;
  109. #endif
  110. if (ELFDATA2LSB!= elf_hdr->e_ident[EI_DATA])
  111. return false;
  112. if (EV_CURRENT != elf_hdr->e_ident[EI_VERSION])
  113. return false;
  114. if (ET_DYN != elf_hdr->e_type)
  115. return false;
  116. if (sizeof(ElfW(Phdr)) != elf_hdr->e_phentsize)
  117. return false;
  118. return true;
  119. }
  120. bool parse_dyn(const ElfW(Ehdr) *elf_hdr, ElfW(Dyn)* dyn_info)
  121. {
  122. const ElfW(Phdr) *prg_hdr = GET_PTR(ElfW(Phdr), elf_hdr, elf_hdr->e_phoff);
  123. bool has_dyn = false;
  124. for (unsigned idx = 0; idx < elf_hdr->e_phnum; ++idx, ++prg_hdr)
  125. {
  126. if (PT_DYNAMIC == prg_hdr->p_type)
  127. {
  128. const ElfW(Dyn) *dyn_entry = GET_PTR(ElfW(Dyn), elf_hdr, prg_hdr->p_offset);
  129. // parse dynamic segment
  130. // An entry with a DT_NULL tag marks the end.
  131. while (dyn_entry->d_tag != DT_NULL)
  132. {
  133. SE_TRACE(SE_TRACE_DEBUG, "dynamic tag = %x, ptr = %x\n", dyn_entry->d_tag, dyn_entry->d_un.d_ptr);
  134. if (dyn_entry->d_tag < DT_NUM)
  135. {
  136. memcpy_s(&dyn_info[dyn_entry->d_tag], sizeof(ElfW(Dyn)), dyn_entry, sizeof(ElfW(Dyn)));
  137. }
  138. else if (dyn_entry->d_tag > DT_ADDRRNGLO && dyn_entry->d_tag <= DT_ADDRRNGHI)
  139. {
  140. memcpy_s(&dyn_info[DT_ADDRTAGIDX(dyn_entry->d_tag) + DT_NUM], sizeof(ElfW(Dyn)), dyn_entry, sizeof(ElfW(Dyn)));
  141. }
  142. dyn_entry++;
  143. has_dyn = true;
  144. }
  145. return has_dyn;
  146. }
  147. }
  148. return false;
  149. }
  150. /** Check whether there are undefined symbols and save the address
  151. * for a few reserved symbols.
  152. *
  153. * ELF format defined two symbol tables, `.symtab' and `.dynsym'.
  154. *
  155. * `.symtab' is non-allocable, and might be stripped.
  156. * `.dynsym' is allocable, and only contains global symbols.
  157. *
  158. * We only need to search `.dynsym' for undefined symbols.
  159. */
  160. bool check_symbol_table(const ElfW(Ehdr) *elf_hdr, const ElfW(Dyn) *dyn_info,
  161. map<string, uint64_t>& sym_table)
  162. {
  163. const ElfW(Shdr) *sh_symtab = get_section_by_addr(elf_hdr, dyn_info[DT_SYMTAB].d_un.d_ptr);
  164. if (sh_symtab == NULL)
  165. {
  166. // We must at least have "enclave_entry"
  167. SE_TRACE(SE_TRACE_WARNING, "There is no .dynsym section");
  168. return false;
  169. }
  170. if (sh_symtab->sh_entsize == 0)
  171. {
  172. SE_TRACE(SE_TRACE_WARNING, "In section .dynsym, sh_entsize is 0.");
  173. return false;
  174. }
  175. const ElfW(Sym) *symtab = GET_PTR(ElfW(Sym), elf_hdr, sh_symtab->sh_offset);
  176. uint32_t sym_num = (uint32_t)(sh_symtab->sh_size/sh_symtab->sh_entsize);
  177. const char *strtab = get_section_raw_data<char>(elf_hdr, dyn_info[DT_STRTAB].d_un.d_ptr);
  178. // We only store "enclave_entry", "g_global_data_sim" and "g_peak_heap_used".
  179. // To export new symbols, add them here.
  180. //
  181. // "g_global_data_sim" is needed so that we can check that whether
  182. // an simulated enclave is given when running an HW loader.
  183. const char* str[] = { "enclave_entry", "g_global_data_sim", "g_peak_heap_used", "g_global_data" };
  184. // The first entry is reserved, and must be all zeros
  185. for (uint32_t idx = 1; idx < sym_num; ++idx)
  186. {
  187. // st_name == 0 indicates the symble table entry has no name.
  188. if (symtab[idx].st_name == 0) continue;
  189. const char* sym = strtab + symtab[idx].st_name;
  190. if (sym == NULL)
  191. {
  192. SE_TRACE(SE_TRACE_WARNING, "Malformed enclave with NULL symbol name\n");
  193. return false;
  194. }
  195. if (SHN_UNDEF == symtab[idx].st_shndx
  196. && STB_WEAK != ELFW(ST_BIND)(symtab[idx].st_info))
  197. {
  198. SE_TRACE(SE_TRACE_WARNING, "symbol '%s' is undefined\n", sym);
  199. return false;
  200. }
  201. #define SYMBOL_NUM (ARRAY_LENGTH(str))
  202. for (size_t i = 0; i < SYMBOL_NUM; ++i)
  203. {
  204. if (0 == strcmp(str[i], sym))
  205. {
  206. sym_table[sym] = (uint64_t)symtab[idx].st_value;
  207. }
  208. }
  209. }
  210. // If the enclave if compiled/linked with -fpie/-pie, and setting the
  211. // enclave entry to `enclave_entry', the `st_name' for `enclave_entry'
  212. // will be 0 in `.dynsym'.
  213. map<string, uint64_t>::const_iterator it = sym_table.find("enclave_entry");
  214. if (it == sym_table.end())
  215. {
  216. sym_table["enclave_entry"] = (uint64_t)elf_hdr->e_entry;
  217. }
  218. return true;
  219. }
  220. bool do_validate_reltab(const ElfW(Rel) *reltab, size_t nr_rel)
  221. {
  222. if (reltab == NULL && nr_rel != 0) return false;
  223. #if RTS_SYSTEM_WORDSIZE == 64
  224. const ElfW(Rel) *rela = reltab;
  225. for (unsigned idx = 0; idx < nr_rel; idx++, rela++)
  226. {
  227. switch (ELF64_R_TYPE(rela->r_info))
  228. {
  229. case R_X86_64_RELATIVE:
  230. break;
  231. case R_X86_64_GLOB_DAT:
  232. case R_X86_64_JUMP_SLOT:
  233. case R_X86_64_64:
  234. break;
  235. case R_X86_64_NONE:
  236. break;
  237. case R_X86_64_DTPMOD64:
  238. case R_X86_64_DTPOFF64:
  239. case R_X86_64_TPOFF64:
  240. break;
  241. #else
  242. const ElfW(Rel) *rel = reltab;
  243. for (unsigned idx = 0; idx < nr_rel; idx++, rel++)
  244. {
  245. switch (ELF32_R_TYPE(rel->r_info))
  246. {
  247. case R_386_RELATIVE: /* B+A */
  248. break;
  249. case R_386_GLOB_DAT:
  250. case R_386_JMP_SLOT: /* S */
  251. break;
  252. case R_386_32: /* S+A */
  253. break;
  254. case R_386_PC32: /* S+A-P */
  255. break;
  256. case R_386_NONE:
  257. break;
  258. case R_386_TLS_DTPMOD32:
  259. break;
  260. case R_386_TLS_DTPOFF32:
  261. break;
  262. case R_386_TLS_TPOFF:
  263. break;
  264. case R_386_TLS_TPOFF32:
  265. break;
  266. #endif
  267. default: /* unsupported relocs */
  268. SE_TRACE(SE_TRACE_WARNING, "unsupported relocation type detected\n");
  269. return false;
  270. }
  271. }
  272. return true;
  273. }
  274. bool validate_reltabs(const ElfW(Ehdr) *elf_hdr, const ElfW(Dyn) *dyn_info)
  275. {
  276. #if RTS_SYSTEM_WORDSIZE == 64
  277. // The relocation struct must be rela on x64.
  278. if (dyn_info[DT_REL].d_un.d_ptr)
  279. {
  280. SE_TRACE(SE_TRACE_WARNING, "Rel struct detected on x64\n");
  281. return false;
  282. }
  283. #else
  284. // The relocation struct must be rel on x86.
  285. if (dyn_info[DT_RELA].d_un.d_ptr)
  286. {
  287. SE_TRACE(SE_TRACE_WARNING, "Rela struct detected on x86\n");
  288. return false;
  289. }
  290. #endif
  291. const ElfW(Rel) *reltab = get_section_raw_data<ElfW(Rel)>(elf_hdr, dyn_info[RTS_DT_REL].d_un.d_ptr);
  292. const ElfW(Word) reltab_sz = (ElfW(Word))dyn_info[RTS_DT_RELSZ].d_un.d_val;
  293. const ElfW(Rel) *jmpreltab = get_section_raw_data<ElfW(Rel)>(elf_hdr, dyn_info[DT_JMPREL].d_un.d_ptr);
  294. const ElfW(Word) jmpreltab_sz = (ElfW(Word))dyn_info[DT_PLTRELSZ].d_un.d_val;
  295. return (do_validate_reltab(reltab, reltab_sz / sizeof(ElfW(Rel)))
  296. && do_validate_reltab(jmpreltab, jmpreltab_sz / sizeof(ElfW(Rel))));
  297. }
  298. bool has_ctor_section(const ElfW(Ehdr) *elf_hdr)
  299. {
  300. const ElfW(Shdr) *shdr = get_section_by_name(elf_hdr, ".ctors");
  301. if (NULL == shdr) return false;
  302. se_trace(SE_TRACE_ERROR, "ERROR: .ctors section is found, global initializers will not be invoked correctly!\n");
  303. return true;
  304. }
  305. inline bool is_tls_segment(const ElfW(Phdr)* prg_hdr)
  306. {
  307. return (PT_TLS == prg_hdr->p_type);
  308. }
  309. bool get_meta_property(const uint8_t *start_addr, const ElfW(Ehdr) *elf_hdr, uint64_t &meta_offset, uint64_t &meta_block_size)
  310. {
  311. const ElfW(Shdr)* shdr = get_section_by_name(elf_hdr, ".note.sgxmeta");
  312. if (shdr == NULL)
  313. {
  314. se_trace(SE_TRACE_ERROR, "ERROR: The enclave image should have '.note.sgxmeta' section\n");
  315. return false;
  316. }
  317. /* We require that enclaves should have .note.sgxmeta section to store the metadata information
  318. * We limit this section is used for metadata only and ISV should not extend this section.
  319. *
  320. * .note.sgxmeta layout:
  321. *
  322. * | namesz |
  323. * | metadata size |
  324. * | type |
  325. * | name |
  326. * | metadata |
  327. */
  328. const ElfW(Note) *note = GET_PTR(ElfW(Note), start_addr, shdr->sh_offset);
  329. assert(note != NULL);
  330. if (shdr->sh_size != ROUND_TO(sizeof(ElfW(Note)) + note->namesz + note->descsz, shdr->sh_addralign ))
  331. {
  332. se_trace(SE_TRACE_ERROR, "ERROR: The '.note.sgxmeta' section size is not correct.\n");
  333. return false;
  334. }
  335. const char * meta_name = "sgx_metadata";
  336. if (note->namesz != (strlen(meta_name)+1) || memcmp(GET_PTR(void, start_addr, shdr->sh_offset + sizeof(ElfW(Note))), meta_name, note->namesz))
  337. {
  338. se_trace(SE_TRACE_ERROR, "ERROR: The note in the '.note.sgxmeta' section must be named as \"sgx_metadata\"\n");
  339. return false;
  340. }
  341. meta_offset = static_cast<uint64_t>(shdr->sh_offset + sizeof(ElfW(Note)) + note->namesz);
  342. meta_block_size = note->descsz;
  343. return true;
  344. }
  345. bool validate_segment(const ElfW(Ehdr) *elf_hdr, uint64_t len)
  346. {
  347. const ElfW(Phdr) *prg_hdr = GET_PTR(ElfW(Phdr), elf_hdr, elf_hdr->e_phoff);
  348. assert(sizeof(ElfW(Phdr)) == elf_hdr->e_phentsize);
  349. std::vector< std::pair<ElfW(Addr), ElfW(Addr)> > load_seg(elf_hdr->e_phnum, std::make_pair(0, 0));
  350. int k = 0;
  351. for (int idx = 0; idx < elf_hdr->e_phnum; idx++, prg_hdr++)
  352. {
  353. /* Validate the size of the buffer */
  354. if (len < (uint64_t)prg_hdr->p_offset + prg_hdr->p_filesz)
  355. return false;
  356. if (PT_LOAD == prg_hdr->p_type)
  357. {
  358. // The default align is max page size. On x86-64, the max page size is 2M, but EPC page size is 4K,
  359. // so in x86-64, we just treat it as EPC page size. The (2M - 4K) size is not eadded. We leave it
  360. // as a hole.
  361. if (!IS_PAGE_ALIGNED(prg_hdr->p_align))
  362. {
  363. SE_TRACE(SE_TRACE_WARNING, "A segment is not PAGE aligned, alignment = %x\n", prg_hdr->p_align);
  364. return false;
  365. }
  366. // Verify the overlap of segment. we don't verify here, because a well compiled file has no overlapped segment.
  367. load_seg[k].first = prg_hdr->p_vaddr;
  368. load_seg[k].second = ROUND_TO(prg_hdr->p_vaddr + prg_hdr->p_memsz, prg_hdr->p_align) - 1;
  369. for (int j = 0; j < k; j++)
  370. {
  371. if (is_overlap(load_seg[k], load_seg[j]))
  372. {
  373. SE_TRACE(SE_TRACE_WARNING, "there is overlap segment [%x : %x] [%x : %x]\n",
  374. load_seg[k].first, load_seg[k].second, load_seg[j].first, load_seg[j].second);
  375. return false;
  376. }
  377. }
  378. k++;
  379. }
  380. }
  381. return true;
  382. }
  383. bool get_bin_fmt(const ElfW(Ehdr) *elf_hdr, bin_fmt_t& bf)
  384. {
  385. switch(elf_hdr->e_machine)
  386. {
  387. #if RTS_SYSTEM_WORDSIZE == 32
  388. case EM_386:
  389. bf = BF_ELF32;
  390. return true;
  391. #endif
  392. #if RTS_SYSTEM_WORDSIZE == 64
  393. case EM_X86_64:
  394. bf = BF_ELF64;
  395. return true;
  396. #endif
  397. }
  398. return false;
  399. }
  400. si_flags_t page_attr_to_si_flags(uint32_t page_attr)
  401. {
  402. si_flags_t res = SI_FLAG_REG;
  403. if (page_attr & PF_R)
  404. res |= SI_FLAG_R;
  405. if (page_attr & PF_W)
  406. res |= SI_FLAG_W;
  407. if (page_attr & PF_X)
  408. res |= SI_FLAG_X;
  409. return res;
  410. }
  411. Section* build_section(const uint8_t* raw_data, uint64_t size, uint64_t virtual_size,
  412. uint64_t rva, uint32_t page_attr)
  413. {
  414. si_flags_t sf = page_attr_to_si_flags(page_attr);
  415. if (sf != SI_FLAG_REG)
  416. return new Section(raw_data, size, virtual_size, rva, sf);
  417. return NULL;
  418. }
  419. bool build_regular_sections(const uint8_t* start_addr,
  420. vector<Section *>& sections,
  421. const Section*& tls_sec,
  422. uint64_t& metadata_offset,
  423. uint64_t& metadata_block_size)
  424. {
  425. const ElfW(Ehdr) *elf_hdr = (const ElfW(Ehdr) *)start_addr;
  426. const ElfW(Phdr) *prg_hdr = GET_PTR(ElfW(Phdr), start_addr, elf_hdr->e_phoff);
  427. uint64_t virtual_size = 0, alignment = 0, aligned_virtual_size = 0;
  428. if (get_meta_property(start_addr, elf_hdr, metadata_offset, metadata_block_size) == false)
  429. return false;
  430. for (unsigned idx = 0; idx < elf_hdr->e_phnum; ++idx, ++prg_hdr)
  431. {
  432. Section* sec = NULL;
  433. switch (prg_hdr->p_type)
  434. {
  435. case PT_LOAD:
  436. sec = build_section(GET_PTR(uint8_t, start_addr, prg_hdr->p_offset),
  437. (uint64_t)prg_hdr->p_filesz, (uint64_t)prg_hdr->p_memsz,
  438. (uint64_t)prg_hdr->p_vaddr, (uint32_t) prg_hdr->p_flags);
  439. break;
  440. case PT_TLS:
  441. virtual_size = (uint64_t)prg_hdr->p_memsz;
  442. alignment = (uint64_t)prg_hdr->p_align;
  443. /* according to ELF spec, alignment equals zero or one means no align requirement */
  444. if (alignment == 0 || alignment == 1)
  445. aligned_virtual_size = virtual_size;
  446. else
  447. aligned_virtual_size = (virtual_size + alignment - 1) & (~(alignment - 1));
  448. sec = build_section(GET_PTR(uint8_t, start_addr, prg_hdr->p_offset),
  449. (uint64_t)prg_hdr->p_filesz, aligned_virtual_size,
  450. (uint64_t)prg_hdr->p_vaddr, (uint32_t) prg_hdr->p_flags);
  451. break;
  452. default:
  453. continue;
  454. }
  455. if (sec == NULL)
  456. return false;
  457. /* We've filtered segments that are not of PT_LOAD or PT_TLS type. */
  458. if (!is_tls_segment(prg_hdr))
  459. {
  460. /* A PT_LOAD segment. */
  461. sections.push_back(sec);
  462. continue;
  463. }
  464. /* It is a TLS segment. */
  465. tls_sec = sec;
  466. }
  467. return true;
  468. }
  469. const Section* get_max_rva_section(const vector<Section*> sections)
  470. {
  471. size_t sec_size = sections.size();
  472. if (sec_size == 0)
  473. return NULL;
  474. const Section* psec = sections[0];
  475. for (size_t idx = 1; idx < sec_size; ++idx)
  476. {
  477. if (sections[idx]->get_rva() > psec->get_rva())
  478. psec = sections[idx];
  479. }
  480. return psec;
  481. }
  482. }
  483. ElfParser::ElfParser (const uint8_t* start_addr, uint64_t len)
  484. :m_start_addr(start_addr), m_len(len), m_bin_fmt(BF_UNKNOWN),
  485. m_tls_section(NULL), m_metadata_offset(0), m_metadata_block_size(0)
  486. {
  487. memset(&m_dyn_info, 0, sizeof(m_dyn_info));
  488. }
  489. sgx_status_t ElfParser::run_parser()
  490. {
  491. /* We only need to run the parser once. */
  492. if (m_sections.size() != 0) return SGX_SUCCESS;
  493. const ElfW(Ehdr) *elf_hdr = (const ElfW(Ehdr) *)m_start_addr;
  494. if (elf_hdr == NULL || m_len < sizeof(ElfW(Ehdr)))
  495. return SGX_ERROR_INVALID_ENCLAVE;
  496. /* Check elf header*/
  497. if (!validate_elf_header(elf_hdr))
  498. return SGX_ERROR_INVALID_ENCLAVE;
  499. /* Get and check machine mode */
  500. if (!get_bin_fmt(elf_hdr, m_bin_fmt))
  501. return SGX_ERROR_MODE_INCOMPATIBLE;
  502. /* Check if there is any overlap segment, and make sure the segment is 1 page aligned;
  503. * TLS segment must exist.
  504. */
  505. if (!validate_segment(elf_hdr, m_len))
  506. return SGX_ERROR_INVALID_ENCLAVE;
  507. if (!parse_dyn(elf_hdr, &m_dyn_info[0]))
  508. return SGX_ERROR_INVALID_ENCLAVE;
  509. /* Check if there is any undefined symbol */
  510. if (!check_symbol_table(elf_hdr, m_dyn_info, m_sym_table))
  511. {
  512. return SGX_ERROR_UNDEFINED_SYMBOL;
  513. }
  514. /* Check if there is unexpected relocation type */
  515. if (!validate_reltabs(elf_hdr, m_dyn_info))
  516. return SGX_ERROR_INVALID_ENCLAVE;
  517. /* Check if there is .ctor section */
  518. if (has_ctor_section(elf_hdr))
  519. return SGX_ERROR_INVALID_ENCLAVE;
  520. /* build regular sections */
  521. if (build_regular_sections(m_start_addr, m_sections, m_tls_section, m_metadata_offset, m_metadata_block_size))
  522. return SGX_SUCCESS;
  523. else
  524. return SGX_ERROR_INVALID_ENCLAVE;
  525. }
  526. ElfParser::~ElfParser()
  527. {
  528. delete_ptrs_from_container(m_sections);
  529. if (m_tls_section) delete m_tls_section;
  530. }
  531. bin_fmt_t ElfParser::get_bin_format() const
  532. {
  533. return m_bin_fmt;
  534. }
  535. uint64_t ElfParser::get_enclave_max_size() const
  536. {
  537. if(m_bin_fmt == BF_ELF64)
  538. return ENCLAVE_MAX_SIZE_64;
  539. else
  540. return ENCLAVE_MAX_SIZE_32;
  541. }
  542. uint64_t ElfParser::get_metadata_offset() const
  543. {
  544. return m_metadata_offset;
  545. }
  546. uint64_t ElfParser::get_metadata_block_size() const
  547. {
  548. return m_metadata_block_size;
  549. }
  550. const uint8_t* ElfParser::get_start_addr() const
  551. {
  552. return m_start_addr;
  553. }
  554. const vector<Section *>& ElfParser::get_sections() const
  555. {
  556. return m_sections;
  557. }
  558. const Section* ElfParser::get_tls_section() const
  559. {
  560. return m_tls_section;
  561. }
  562. uint64_t ElfParser::get_symbol_rva(const char* name) const
  563. {
  564. map<string, uint64_t>::const_iterator it = m_sym_table.find(name);
  565. if (it != m_sym_table.end())
  566. return it->second;
  567. else
  568. return 0;
  569. }
  570. bool ElfParser::has_text_reloc() const
  571. {
  572. if (m_dyn_info[DT_TEXTREL].d_tag)
  573. {
  574. return true;
  575. }
  576. return false;
  577. }
  578. bool ElfParser::get_reloc_bitmap(vector<uint8_t>& bitmap)
  579. {
  580. // Clear the `bitmap' so that it is in a known state
  581. bitmap.clear();
  582. if (!m_dyn_info[DT_TEXTREL].d_tag)
  583. return true;
  584. const ElfW(Ehdr) *elf_hdr = (const ElfW(Ehdr) *)m_start_addr;
  585. const ElfW(Rel) *rel[4] = { NULL, NULL, NULL, NULL };
  586. if (m_dyn_info[DT_JMPREL].d_tag)
  587. {
  588. rel[2] = get_section_raw_data<ElfW(Rel)>(elf_hdr, m_dyn_info[DT_JMPREL].d_un.d_ptr);
  589. rel[3] = GET_PTR(const ElfW(Rel), rel[2], m_dyn_info[DT_PLTRELSZ].d_un.d_val);
  590. }
  591. if (m_dyn_info[RTS_DT_REL].d_tag)
  592. {
  593. rel[0] = get_section_raw_data<ElfW(Rel)>(elf_hdr, m_dyn_info[RTS_DT_REL].d_un.d_ptr);
  594. rel[1] = GET_PTR(const ElfW(Rel), rel[0], m_dyn_info[RTS_DT_RELSZ].d_un.d_val);
  595. assert(sizeof(ElfW(Rel)) == m_dyn_info[RTS_DT_RELENT].d_un.d_val);
  596. }
  597. // The enclave size mapped in memory is calculated by
  598. // sec->get_rva() + sec->virtual_size();
  599. // where the `sec' is the section with maximum RVA value.
  600. uint64_t image_size = 0;
  601. const Section* max_rva_sec = get_max_rva_section(this->m_sections);
  602. if (max_rva_sec == NULL)
  603. return false;
  604. image_size = max_rva_sec->get_rva() + max_rva_sec->virtual_size();
  605. // NOTE:
  606. // Current enclave size is not beyond 64G, so the type-casting from (uint64>>15) to (size_t) is OK.
  607. // In the future, if the max enclave size is extended to beyond 1<<49, this type-casting will not work.
  608. // It only impacts the enclave signing process. (32bit signing tool to sign 64 bit enclaves)
  609. // allocate bitmap
  610. bitmap.resize((size_t)((((image_size + (SE_PAGE_SIZE - 1)) >> SE_PAGE_SHIFT) + 7) / 8));
  611. for (unsigned idx = 0; idx < ARRAY_LENGTH(rel); idx += 2)
  612. {
  613. const ElfW(Rel) *rel_entry = rel[idx], *rel_end = rel[idx+1];
  614. if (NULL == rel_entry)
  615. continue;
  616. for (; rel_entry < rel_end; rel_entry++)
  617. {
  618. #if RTS_SYSTEM_WORDSIZE == 64
  619. if (ELF64_R_TYPE(rel_entry->r_info) == R_X86_64_NONE)
  620. #else
  621. if (ELF32_R_TYPE(rel_entry->r_info) == R_386_NONE)
  622. #endif
  623. continue;
  624. ElfW(Addr) reloc_addr = rel_entry->r_offset;
  625. uint64_t page_frame = (uint64_t)(reloc_addr >> SE_PAGE_SHIFT);
  626. // NOTE:
  627. // Current enclave size is not beyond 64G, so the type-casting from (uint64>>15) to (size_t) is OK.
  628. // In the future, if the max enclave size is extended to beyond 1<<49, this type-casting will not work.
  629. // It only impacts the enclave signing process. (32bit signing tool to sign 64 bit enclaves)
  630. // If there is more than one relocation in one page, then "|" works as there
  631. // is only one relocation in one page.
  632. bitmap[(size_t)(page_frame/8)] = (uint8_t)(bitmap[(size_t)(page_frame/8)] | (uint8_t)(1 << (page_frame % 8)));
  633. // Check if the relocation across boundary
  634. if ((reloc_addr & (SE_PAGE_SIZE - 1)) > (SE_PAGE_SIZE - sizeof(sys_word_t)))
  635. {
  636. page_frame++;
  637. bitmap[(size_t)(page_frame/8)] = (uint8_t)(bitmap[(size_t)(page_frame/8)] | (uint8_t)(1 << (page_frame % 8)));
  638. }
  639. }
  640. }
  641. return true;
  642. }
  643. void ElfParser::get_reloc_entry_offset(const char* sec_name, vector<uint64_t>& offsets)
  644. {
  645. if (sec_name == NULL)
  646. return;
  647. const ElfW(Ehdr) *ehdr = (const ElfW(Ehdr) *)m_start_addr;
  648. const ElfW(Shdr) *shdr = get_section_by_name(ehdr, sec_name);
  649. if (shdr == NULL)
  650. return;
  651. /* find the start and end offset of the target section */
  652. const uint64_t start = shdr->sh_addr;
  653. const uint64_t end = start + shdr->sh_size;
  654. offsets.clear();
  655. SE_TRACE(SE_TRACE_DEBUG, "found section '%s' - offset %#lx, size %#lx\n",
  656. sec_name, (long)start, (long)shdr->sh_size);
  657. /* iterate sections to find the relocs */
  658. shdr = GET_PTR(ElfW(Shdr), m_start_addr, ehdr->e_shoff);
  659. for (unsigned idx = 0; idx < ehdr->e_shnum; ++idx, ++shdr)
  660. {
  661. if (shdr->sh_type != SHT_RELA &&
  662. shdr->sh_type != SHT_REL)
  663. continue;
  664. uint64_t rel_size = shdr->sh_size;
  665. uint64_t rel_offset = shdr->sh_offset;
  666. uint64_t nr_rel = rel_size / shdr->sh_entsize;
  667. /* for each reloc, check its target address */
  668. const ElfW(Rel) *rel = GET_PTR(ElfW(Rel), m_start_addr, rel_offset);
  669. for (; nr_rel > 0; --nr_rel, ++rel)
  670. {
  671. if (rel->r_offset >= start && rel->r_offset < end)
  672. {
  673. uint64_t offset = DIFF64(rel, m_start_addr);
  674. SE_TRACE(SE_TRACE_DEBUG, "found one reloc at offset %#lx\n", offset);
  675. offsets.push_back(offset);
  676. }
  677. }
  678. }
  679. }
  680. #include "se_page_attr.h"
  681. #include "update_global_data.hxx"
  682. uint32_t ElfParser::get_global_data_size()
  683. {
  684. return (uint32_t)sizeof(global_data_t);
  685. }
  686. bool ElfParser::update_global_data(const metadata_t *const metadata,
  687. const create_param_t* const create_param,
  688. uint8_t *data,
  689. uint32_t *data_size)
  690. {
  691. if(*data_size < sizeof(global_data_t))
  692. {
  693. *data_size = sizeof(global_data_t);
  694. return false;
  695. }
  696. *data_size = sizeof(global_data_t);
  697. return do_update_global_data(metadata, create_param, (global_data_t *)data);
  698. }
  699. sgx_status_t ElfParser::modify_info(enclave_diff_info_t *enclave_diff_info)
  700. {
  701. UNUSED(enclave_diff_info);
  702. return SGX_SUCCESS;
  703. }
  704. sgx_status_t ElfParser::get_info(enclave_diff_info_t *enclave_diff_info)
  705. {
  706. UNUSED(enclave_diff_info);
  707. return SGX_SUCCESS;
  708. }
  709. void ElfParser::get_executable_sections(vector<const char *>& xsec_names) const
  710. {
  711. xsec_names.clear();
  712. const ElfW(Ehdr) *elf_hdr = (const ElfW(Ehdr) *)m_start_addr;
  713. const ElfW(Shdr) *shdr = GET_PTR(ElfW(Shdr), elf_hdr, elf_hdr->e_shoff);
  714. const char *shstrtab = GET_PTR(char, elf_hdr, shdr[elf_hdr->e_shstrndx].sh_offset);
  715. for (unsigned idx = 0; idx < elf_hdr->e_shnum; ++idx, ++shdr)
  716. {
  717. if ((shdr->sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR)
  718. xsec_names.push_back(shstrtab + shdr->sh_name);
  719. }
  720. return;
  721. }
  722. bool ElfParser::set_memory_protection(uint64_t enclave_base_addr, bool is_after_initialization)
  723. {
  724. uint64_t len = 0;
  725. int ret = 0;
  726. uint64_t rva = 0;
  727. uint64_t rva_end = 0;
  728. uint64_t last_section_end = 0;
  729. int prot = 0;
  730. unsigned int i = 0;
  731. //for sections
  732. std::vector<Section*> sections = get_sections();
  733. for(i = 0; i < sections.size() ; i++)
  734. {
  735. //require the sec_info.rva be page aligned, we need handle the first page.
  736. //the first page;
  737. uint64_t offset = (sections[i]->get_rva() & (SE_PAGE_SIZE -1));
  738. uint64_t size = SE_PAGE_SIZE - offset;
  739. //the raw data may be smaller than the size, we get the min of them
  740. if(sections[i]->raw_data_size() < size)
  741. size = sections[i]->raw_data_size();
  742. len = SE_PAGE_SIZE;
  743. //if there is more pages, then calc the next paged aligned pages
  744. if((sections[i]->virtual_size() + offset) > SE_PAGE_SIZE)
  745. {
  746. uint64_t raw_data_size = sections[i]->raw_data_size() - size;
  747. //we need use (SE_PAGE_SIZE - offset), because (SE_PAGE_SIZE - offset) may larger than size
  748. uint64_t virtual_size = sections[i]->virtual_size() - (SE_PAGE_SIZE - offset);
  749. len += ROUND_TO_PAGE(raw_data_size);
  750. if(ROUND_TO_PAGE(virtual_size) > ROUND_TO_PAGE(raw_data_size))
  751. {
  752. len += ROUND_TO_PAGE(virtual_size) - ROUND_TO_PAGE(raw_data_size);
  753. }
  754. }
  755. rva = TRIM_TO_PAGE(sections[i]->get_rva()) + enclave_base_addr;
  756. prot = (int)(sections[i]->get_si_flags()&SI_MASK_MEM_ATTRIBUTE);
  757. ret = mprotect((void*)rva, (size_t)len, prot);
  758. if(ret != 0)
  759. {
  760. return false;
  761. }
  762. //there is a gap between sections, need to set those to NONE access
  763. if(last_section_end != 0)
  764. {
  765. prot = (int)(SI_FLAG_NONE & SI_MASK_MEM_ATTRIBUTE);
  766. ret = mprotect((void*)last_section_end, (size_t)(rva - last_section_end), prot);
  767. if(ret != 0)
  768. {
  769. return false;
  770. }
  771. }
  772. last_section_end = rva + len;
  773. }
  774. if(is_after_initialization == false)
  775. {
  776. return true;
  777. }
  778. const ElfW(Ehdr) *elf_hdr = (const ElfW(Ehdr) *)m_start_addr;
  779. const ElfW(Phdr) *prg_hdr = GET_PTR(ElfW(Phdr), elf_hdr, elf_hdr->e_phoff);
  780. for (int idx = 0; idx < elf_hdr->e_phnum; idx++, prg_hdr++)
  781. {
  782. if(prg_hdr->p_type == PT_DYNAMIC ||
  783. prg_hdr->p_type == PT_GNU_RELRO)
  784. {
  785. rva = TRIM_TO_PAGE(enclave_base_addr + prg_hdr->p_vaddr);
  786. rva_end = ROUND_TO(enclave_base_addr + prg_hdr->p_vaddr + prg_hdr->p_memsz, prg_hdr->p_align);
  787. len = rva_end - rva;
  788. prot = (int)(page_attr_to_si_flags(prg_hdr->p_flags) & SI_MASK_MEM_ATTRIBUTE);
  789. ret = mprotect((void*)rva, (size_t)len, prot);
  790. if(ret != 0)
  791. {
  792. return false;
  793. }
  794. }
  795. }
  796. return true;
  797. }
  798. void ElfParser::get_pages_to_protect(uint64_t enclave_base_addr, std::vector<std::tuple<uint64_t, uint64_t, uint32_t>>& pages_to_protect) const
  799. {
  800. uint64_t len = 0;
  801. uint64_t rva = 0;
  802. uint64_t rva_end = 0;
  803. const ElfW(Ehdr) *elf_hdr = (const ElfW(Ehdr) *)m_start_addr;
  804. const ElfW(Phdr) *prg_hdr = GET_PTR(ElfW(Phdr), elf_hdr, elf_hdr->e_phoff);
  805. for (int idx = 0; idx < elf_hdr->e_phnum; idx++, prg_hdr++)
  806. {
  807. if( (prg_hdr->p_type == PT_GNU_RELRO) ||
  808. ((prg_hdr->p_type == PT_LOAD) && has_text_reloc() && ((prg_hdr->p_flags & PF_W) == 0)) )
  809. {
  810. uint32_t perm = 0;
  811. rva = TRIM_TO_PAGE(enclave_base_addr + prg_hdr->p_vaddr);
  812. rva_end = ROUND_TO_PAGE(enclave_base_addr + prg_hdr->p_vaddr + prg_hdr->p_memsz);
  813. len = rva_end - rva;
  814. if (prg_hdr->p_flags & PF_R)
  815. perm |= SI_FLAG_R;
  816. if (prg_hdr->p_flags & PF_X)
  817. perm |= SI_FLAG_X;
  818. pages_to_protect.push_back(std::make_tuple(rva, len, perm));
  819. }
  820. }
  821. }
  822. bool ElfParser::is_enclave_encrypted() const
  823. {
  824. // if enclave is encrypted, enclave must contain section .pcltbl
  825. const char* sec_name = ".pcltbl";
  826. const ElfW(Ehdr) *ehdr = (const ElfW(Ehdr) *)m_start_addr;
  827. return (NULL != get_section_by_name(ehdr, sec_name));
  828. }
  829. bool ElfParser::has_init_section() const
  830. {
  831. const char * sec_name = ".init";
  832. const ElfW(Ehdr) *elf_hdr = (const ElfW(Ehdr) *)m_start_addr;
  833. return (NULL != get_section_by_name(elf_hdr, sec_name));
  834. }