17509ff7cSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 27509ff7cSJens Wiklander /* 37509ff7cSJens Wiklander * Copyright (c) 2019, Linaro Limited 47509ff7cSJens Wiklander */ 57509ff7cSJens Wiklander 67509ff7cSJens Wiklander #include <assert.h> 75548a710SJerome Forissier #include <compiler.h> 855e64090SJens Wiklander #include <confine_array_index.h> 97509ff7cSJens Wiklander #include <elf32.h> 107509ff7cSJens Wiklander #include <elf64.h> 117509ff7cSJens Wiklander #include <elf_common.h> 127509ff7cSJens Wiklander #include <string.h> 137509ff7cSJens Wiklander #include <tee_api_types.h> 147509ff7cSJens Wiklander #include <util.h> 157509ff7cSJens Wiklander 167509ff7cSJens Wiklander #include "sys.h" 177509ff7cSJens Wiklander #include "ta_elf.h" 187509ff7cSJens Wiklander 199f392760SJerome Forissier static uint32_t elf_hash(const char *name) 209f392760SJerome Forissier { 219f392760SJerome Forissier const unsigned char *p = (const unsigned char *)name; 229f392760SJerome Forissier uint32_t h = 0; 239f392760SJerome Forissier uint32_t g = 0; 249f392760SJerome Forissier 259f392760SJerome Forissier while (*p) { 269f392760SJerome Forissier h = (h << 4) + *p++; 279f392760SJerome Forissier g = h & 0xf0000000; 289f392760SJerome Forissier if (g) 299f392760SJerome Forissier h ^= g >> 24; 309f392760SJerome Forissier h &= ~g; 319f392760SJerome Forissier } 329f392760SJerome Forissier return h; 339f392760SJerome Forissier } 349f392760SJerome Forissier 3597c5ac19SJens Wiklander static bool __resolve_sym(struct ta_elf *elf, unsigned int st_bind, 3697c5ac19SJens Wiklander unsigned int st_type, size_t st_shndx, 3797c5ac19SJens Wiklander size_t st_name, size_t st_value, const char *name, 38*cf830b2bSJerome Forissier vaddr_t *val, bool weak_ok) 397509ff7cSJens Wiklander { 40*cf830b2bSJerome Forissier bool bind_ok = false; 41*cf830b2bSJerome Forissier 427509ff7cSJens Wiklander if (!st_name) 437509ff7cSJens Wiklander return false; 447509ff7cSJens Wiklander if (st_name > elf->dynstr_size) 4597c5ac19SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Symbol name out of range"); 467509ff7cSJens Wiklander if (strcmp(name, elf->dynstr + st_name)) 477509ff7cSJens Wiklander return false; 48*cf830b2bSJerome Forissier if (st_bind == STB_GLOBAL || (weak_ok && st_bind == STB_WEAK)) 49*cf830b2bSJerome Forissier bind_ok = true; 50*cf830b2bSJerome Forissier if (!bind_ok) 51*cf830b2bSJerome Forissier return false; 52*cf830b2bSJerome Forissier if (st_bind == STB_WEAK && st_shndx == SHN_UNDEF) { 53*cf830b2bSJerome Forissier if (val) 54*cf830b2bSJerome Forissier *val = 0; 55*cf830b2bSJerome Forissier return true; 56*cf830b2bSJerome Forissier } 57*cf830b2bSJerome Forissier if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX) 58*cf830b2bSJerome Forissier return false; 597509ff7cSJens Wiklander 6097c5ac19SJens Wiklander if (st_value > (elf->max_addr - elf->load_addr)) 6197c5ac19SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Symbol location out of range"); 6297c5ac19SJens Wiklander 6397c5ac19SJens Wiklander switch (st_type) { 64bb8cd6f0SJerome Forissier case STT_NOTYPE: 6597c5ac19SJens Wiklander case STT_OBJECT: 6697c5ac19SJens Wiklander case STT_FUNC: 677509ff7cSJens Wiklander *val = st_value + elf->load_addr; 6897c5ac19SJens Wiklander break; 6997c5ac19SJens Wiklander default: 7097c5ac19SJens Wiklander err(TEE_ERROR_NOT_SUPPORTED, "Symbol type not supported"); 7197c5ac19SJens Wiklander } 7297c5ac19SJens Wiklander 737509ff7cSJens Wiklander return true; 747509ff7cSJens Wiklander } 757509ff7cSJens Wiklander 76ebef121cSJerome Forissier static TEE_Result resolve_sym_helper(uint32_t hash, const char *name, 77*cf830b2bSJerome Forissier vaddr_t *val, struct ta_elf *elf, 78*cf830b2bSJerome Forissier bool weak_ok) 797509ff7cSJens Wiklander { 809f392760SJerome Forissier /* 819f392760SJerome Forissier * Using uint32_t here for convenience because both Elf64_Word 829f392760SJerome Forissier * and Elf32_Word are 32-bit types 839f392760SJerome Forissier */ 849f392760SJerome Forissier uint32_t *hashtab = elf->hashtab; 859f392760SJerome Forissier uint32_t nbuckets = hashtab[0]; 869f392760SJerome Forissier uint32_t nchains = hashtab[1]; 879f392760SJerome Forissier uint32_t *bucket = &hashtab[2]; 889f392760SJerome Forissier uint32_t *chain = &bucket[nbuckets]; 89ebef121cSJerome Forissier size_t n = 0; 909f392760SJerome Forissier 917509ff7cSJens Wiklander if (elf->is_32bit) { 927509ff7cSJens Wiklander Elf32_Sym *sym = elf->dynsymtab; 937509ff7cSJens Wiklander 949f392760SJerome Forissier for (n = bucket[hash % nbuckets]; n; n = chain[n]) { 958dbe2cbdSJens Wiklander if (n >= nchains || n >= elf->num_dynsyms) 965c0860dbSJens Wiklander err(TEE_ERROR_BAD_FORMAT, 975c0860dbSJens Wiklander "Index out of range"); 9855e64090SJens Wiklander /* 9955e64090SJens Wiklander * We're loading values from sym[] which later 10055e64090SJens Wiklander * will be used to load something. 10155e64090SJens Wiklander * => Spectre V1 pattern, need to cap the index 10255e64090SJens Wiklander * against speculation. 10355e64090SJens Wiklander */ 10455e64090SJens Wiklander n = confine_array_index(n, elf->num_dynsyms); 1057509ff7cSJens Wiklander if (__resolve_sym(elf, 1067509ff7cSJens Wiklander ELF32_ST_BIND(sym[n].st_info), 10797c5ac19SJens Wiklander ELF32_ST_TYPE(sym[n].st_info), 1087509ff7cSJens Wiklander sym[n].st_shndx, 1097509ff7cSJens Wiklander sym[n].st_name, 110*cf830b2bSJerome Forissier sym[n].st_value, name, val, weak_ok)) 111c86f218cSJens Wiklander return TEE_SUCCESS; 1127509ff7cSJens Wiklander } 1137509ff7cSJens Wiklander } else { 1147509ff7cSJens Wiklander Elf64_Sym *sym = elf->dynsymtab; 1157509ff7cSJens Wiklander 1169f392760SJerome Forissier for (n = bucket[hash % nbuckets]; n; n = chain[n]) { 1178dbe2cbdSJens Wiklander if (n >= nchains || n >= elf->num_dynsyms) 1185c0860dbSJens Wiklander err(TEE_ERROR_BAD_FORMAT, 1195c0860dbSJens Wiklander "Index out of range"); 12055e64090SJens Wiklander /* 12155e64090SJens Wiklander * We're loading values from sym[] which later 12255e64090SJens Wiklander * will be used to load something. 12355e64090SJens Wiklander * => Spectre V1 pattern, need to cap the index 12455e64090SJens Wiklander * against speculation. 12555e64090SJens Wiklander */ 12655e64090SJens Wiklander n = confine_array_index(n, elf->num_dynsyms); 1277509ff7cSJens Wiklander if (__resolve_sym(elf, 1287509ff7cSJens Wiklander ELF64_ST_BIND(sym[n].st_info), 12997c5ac19SJens Wiklander ELF64_ST_TYPE(sym[n].st_info), 1307509ff7cSJens Wiklander sym[n].st_shndx, 1317509ff7cSJens Wiklander sym[n].st_name, 132*cf830b2bSJerome Forissier sym[n].st_value, name, val, weak_ok)) 133c86f218cSJens Wiklander return TEE_SUCCESS; 1347509ff7cSJens Wiklander } 1357509ff7cSJens Wiklander } 136ebef121cSJerome Forissier 137ebef121cSJerome Forissier return TEE_ERROR_ITEM_NOT_FOUND; 1387509ff7cSJens Wiklander } 139c86f218cSJens Wiklander 140*cf830b2bSJerome Forissier /* 141*cf830b2bSJerome Forissier * Look for named symbol in @elf, or all modules if @elf == NULL. Global symbols 142*cf830b2bSJerome Forissier * are searched first, then weak ones. Last option, when at least one weak but 143*cf830b2bSJerome Forissier * undefined symbol exists, resolve to zero. Otherwise return 144*cf830b2bSJerome Forissier * TEE_ERROR_ITEM_NOT_FOUND. 145*cf830b2bSJerome Forissier */ 146ebef121cSJerome Forissier TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val, 147ebef121cSJerome Forissier struct ta_elf *elf) 148ebef121cSJerome Forissier { 149ebef121cSJerome Forissier uint32_t hash = elf_hash(name); 150ebef121cSJerome Forissier 151*cf830b2bSJerome Forissier if (elf) { 152*cf830b2bSJerome Forissier /* Search global symbols */ 153*cf830b2bSJerome Forissier if (!resolve_sym_helper(hash, name, val, elf, 154*cf830b2bSJerome Forissier false /* !weak_ok */)) 155ebef121cSJerome Forissier return TEE_SUCCESS; 156*cf830b2bSJerome Forissier /* Search weak symbols */ 157*cf830b2bSJerome Forissier if (!resolve_sym_helper(hash, name, val, elf, 158*cf830b2bSJerome Forissier true /* weak_ok */)) 159*cf830b2bSJerome Forissier return TEE_SUCCESS; 160*cf830b2bSJerome Forissier } 161*cf830b2bSJerome Forissier 162*cf830b2bSJerome Forissier TAILQ_FOREACH(elf, &main_elf_queue, link) { 163*cf830b2bSJerome Forissier if (!resolve_sym_helper(hash, name, val, elf, 164*cf830b2bSJerome Forissier false /* !weak_ok */)) 165*cf830b2bSJerome Forissier return TEE_SUCCESS; 166*cf830b2bSJerome Forissier if (!resolve_sym_helper(hash, name, val, elf, 167*cf830b2bSJerome Forissier true /* weak_ok */)) 168*cf830b2bSJerome Forissier return TEE_SUCCESS; 169*cf830b2bSJerome Forissier } 170ebef121cSJerome Forissier 171c86f218cSJens Wiklander return TEE_ERROR_ITEM_NOT_FOUND; 172c86f218cSJens Wiklander } 173c86f218cSJens Wiklander 174c86f218cSJens Wiklander static void resolve_sym(const char *name, vaddr_t *val) 175c86f218cSJens Wiklander { 176ebef121cSJerome Forissier TEE_Result res = ta_elf_resolve_sym(name, val, NULL); 177c86f218cSJens Wiklander 178c86f218cSJens Wiklander if (res) 179c86f218cSJens Wiklander err(res, "Symbol %s not found", name); 1807509ff7cSJens Wiklander } 1817509ff7cSJens Wiklander 1827509ff7cSJens Wiklander static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms, 1837509ff7cSJens Wiklander const char *str_tab, size_t str_tab_size, 1847509ff7cSJens Wiklander Elf32_Rel *rel, Elf32_Addr *where) 1857509ff7cSJens Wiklander { 1867509ff7cSJens Wiklander size_t sym_idx = 0; 1877509ff7cSJens Wiklander const char *name = NULL; 1887509ff7cSJens Wiklander vaddr_t val = 0; 1897509ff7cSJens Wiklander size_t name_idx = 0; 1907509ff7cSJens Wiklander 1917509ff7cSJens Wiklander sym_idx = ELF32_R_SYM(rel->r_info); 192447354c6SJens Wiklander if (sym_idx >= num_syms) 193e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); 19455e64090SJens Wiklander sym_idx = confine_array_index(sym_idx, num_syms); 1957509ff7cSJens Wiklander 1967509ff7cSJens Wiklander name_idx = sym_tab[sym_idx].st_name; 197447354c6SJens Wiklander if (name_idx >= str_tab_size) 198e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Name index out of range"); 1997509ff7cSJens Wiklander name = str_tab + name_idx; 2007509ff7cSJens Wiklander 2017509ff7cSJens Wiklander resolve_sym(name, &val); 2027509ff7cSJens Wiklander *where = val; 2037509ff7cSJens Wiklander } 2047509ff7cSJens Wiklander 2057509ff7cSJens Wiklander static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx) 2067509ff7cSJens Wiklander { 2077509ff7cSJens Wiklander Elf32_Shdr *shdr = elf->shdr; 2087509ff7cSJens Wiklander Elf32_Rel *rel = NULL; 2097509ff7cSJens Wiklander Elf32_Rel *rel_end = NULL; 2107509ff7cSJens Wiklander size_t sym_tab_idx = 0; 2117509ff7cSJens Wiklander Elf32_Sym *sym_tab = NULL; 2127509ff7cSJens Wiklander size_t num_syms = 0; 2137509ff7cSJens Wiklander size_t sh_end = 0; 2147509ff7cSJens Wiklander const char *str_tab = NULL; 2157509ff7cSJens Wiklander size_t str_tab_size = 0; 2167509ff7cSJens Wiklander 2177509ff7cSJens Wiklander assert(shdr[rel_sidx].sh_type == SHT_REL); 2187509ff7cSJens Wiklander 2197509ff7cSJens Wiklander assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel)); 2207509ff7cSJens Wiklander 2217509ff7cSJens Wiklander sym_tab_idx = shdr[rel_sidx].sh_link; 2227509ff7cSJens Wiklander if (sym_tab_idx) { 2237509ff7cSJens Wiklander size_t str_tab_idx = 0; 2247509ff7cSJens Wiklander 225447354c6SJens Wiklander if (sym_tab_idx >= elf->e_shnum) 226dcf64f87SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range"); 22755e64090SJens Wiklander sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum); 2287509ff7cSJens Wiklander 2297509ff7cSJens Wiklander assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym)); 2307509ff7cSJens Wiklander 2317509ff7cSJens Wiklander /* Check the address is inside ELF memory */ 2327509ff7cSJens Wiklander if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, 2337509ff7cSJens Wiklander shdr[sym_tab_idx].sh_size, &sh_end)) 234e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Overflow"); 235447354c6SJens Wiklander if (sh_end >= (elf->max_addr - elf->load_addr)) 236dcf64f87SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range"); 2377509ff7cSJens Wiklander 2387509ff7cSJens Wiklander sym_tab = (Elf32_Sym *)(elf->load_addr + 2397509ff7cSJens Wiklander shdr[sym_tab_idx].sh_addr); 2407509ff7cSJens Wiklander 2417509ff7cSJens Wiklander num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym); 2427509ff7cSJens Wiklander 2437509ff7cSJens Wiklander str_tab_idx = shdr[sym_tab_idx].sh_link; 2447509ff7cSJens Wiklander if (str_tab_idx) { 24555e64090SJens Wiklander if (str_tab_idx >= elf->e_shnum) 246e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 247dcf64f87SJens Wiklander "STRTAB index out of range"); 24855e64090SJens Wiklander str_tab_idx = confine_array_index(str_tab_idx, 24955e64090SJens Wiklander elf->e_shnum); 25055e64090SJens Wiklander 2517509ff7cSJens Wiklander /* Check the address is inside ELF memory */ 2527509ff7cSJens Wiklander if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, 2537509ff7cSJens Wiklander shdr[str_tab_idx].sh_size, &sh_end)) 254e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Overflow"); 255447354c6SJens Wiklander if (sh_end >= (elf->max_addr - elf->load_addr)) 256e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 257dcf64f87SJens Wiklander "STRTAB out of range"); 2587509ff7cSJens Wiklander 2597509ff7cSJens Wiklander str_tab = (const char *)(elf->load_addr + 2607509ff7cSJens Wiklander shdr[str_tab_idx].sh_addr); 2617509ff7cSJens Wiklander str_tab_size = shdr[str_tab_idx].sh_size; 2627509ff7cSJens Wiklander } 2637509ff7cSJens Wiklander } 2647509ff7cSJens Wiklander 2657509ff7cSJens Wiklander /* Check the address is inside TA memory */ 266447354c6SJens Wiklander if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, 267447354c6SJens Wiklander shdr[rel_sidx].sh_size, &sh_end)) 268e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Overflow"); 269447354c6SJens Wiklander if (sh_end >= (elf->max_addr - elf->load_addr)) 270dcf64f87SJens Wiklander err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range"); 2717509ff7cSJens Wiklander rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr); 2727509ff7cSJens Wiklander 2737509ff7cSJens Wiklander rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel); 2747509ff7cSJens Wiklander for (; rel < rel_end; rel++) { 2757509ff7cSJens Wiklander Elf32_Addr *where = NULL; 2767509ff7cSJens Wiklander size_t sym_idx = 0; 2777509ff7cSJens Wiklander 2787509ff7cSJens Wiklander /* Check the address is inside TA memory */ 279447354c6SJens Wiklander if (rel->r_offset >= (elf->max_addr - elf->load_addr)) 280e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 281447354c6SJens Wiklander "Relocation offset out of range"); 2827509ff7cSJens Wiklander where = (Elf32_Addr *)(elf->load_addr + rel->r_offset); 2837509ff7cSJens Wiklander 2847509ff7cSJens Wiklander switch (ELF32_R_TYPE(rel->r_info)) { 2857509ff7cSJens Wiklander case R_ARM_ABS32: 2867509ff7cSJens Wiklander sym_idx = ELF32_R_SYM(rel->r_info); 287447354c6SJens Wiklander if (sym_idx >= num_syms) 288e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 289447354c6SJens Wiklander "Symbol index out of range"); 2907509ff7cSJens Wiklander if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { 2917509ff7cSJens Wiklander /* Symbol is external */ 2927509ff7cSJens Wiklander e32_process_dyn_rel(sym_tab, num_syms, str_tab, 2937509ff7cSJens Wiklander str_tab_size, rel, where); 2947509ff7cSJens Wiklander } else { 2957509ff7cSJens Wiklander *where += elf->load_addr + 2967509ff7cSJens Wiklander sym_tab[sym_idx].st_value; 2977509ff7cSJens Wiklander } 2987509ff7cSJens Wiklander break; 2997509ff7cSJens Wiklander case R_ARM_REL32: 3007509ff7cSJens Wiklander sym_idx = ELF32_R_SYM(rel->r_info); 301447354c6SJens Wiklander if (sym_idx >= num_syms) 302e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 303447354c6SJens Wiklander "Symbol index out of range"); 3047509ff7cSJens Wiklander *where += sym_tab[sym_idx].st_value - rel->r_offset; 3057509ff7cSJens Wiklander break; 3067509ff7cSJens Wiklander case R_ARM_RELATIVE: 3077509ff7cSJens Wiklander *where += elf->load_addr; 3087509ff7cSJens Wiklander break; 3097509ff7cSJens Wiklander case R_ARM_GLOB_DAT: 3107509ff7cSJens Wiklander case R_ARM_JUMP_SLOT: 3117509ff7cSJens Wiklander e32_process_dyn_rel(sym_tab, num_syms, str_tab, 3127509ff7cSJens Wiklander str_tab_size, rel, where); 3137509ff7cSJens Wiklander break; 3147509ff7cSJens Wiklander default: 3157509ff7cSJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d", 3167509ff7cSJens Wiklander ELF32_R_TYPE(rel->r_info)); 3177509ff7cSJens Wiklander } 3187509ff7cSJens Wiklander } 3197509ff7cSJens Wiklander } 3207509ff7cSJens Wiklander 3217509ff7cSJens Wiklander #ifdef ARM64 3227509ff7cSJens Wiklander static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms, 3237509ff7cSJens Wiklander const char *str_tab, size_t str_tab_size, 3247509ff7cSJens Wiklander Elf64_Rela *rela, Elf64_Addr *where) 3257509ff7cSJens Wiklander { 3267509ff7cSJens Wiklander size_t sym_idx = 0; 3277509ff7cSJens Wiklander const char *name = NULL; 3287509ff7cSJens Wiklander uintptr_t val = 0; 3297509ff7cSJens Wiklander size_t name_idx = 0; 3307509ff7cSJens Wiklander 3317509ff7cSJens Wiklander sym_idx = ELF64_R_SYM(rela->r_info); 332447354c6SJens Wiklander if (sym_idx >= num_syms) 333e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); 33455e64090SJens Wiklander sym_idx = confine_array_index(sym_idx, num_syms); 3357509ff7cSJens Wiklander 3367509ff7cSJens Wiklander name_idx = sym_tab[sym_idx].st_name; 337447354c6SJens Wiklander if (name_idx >= str_tab_size) 338e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Name index out of range"); 3397509ff7cSJens Wiklander name = str_tab + name_idx; 3407509ff7cSJens Wiklander 3417509ff7cSJens Wiklander resolve_sym(name, &val); 3427509ff7cSJens Wiklander *where = val; 3437509ff7cSJens Wiklander } 3447509ff7cSJens Wiklander 3457509ff7cSJens Wiklander static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx) 3467509ff7cSJens Wiklander { 3477509ff7cSJens Wiklander Elf64_Shdr *shdr = elf->shdr; 3487509ff7cSJens Wiklander Elf64_Rela *rela = NULL; 3497509ff7cSJens Wiklander Elf64_Rela *rela_end = NULL; 3507509ff7cSJens Wiklander size_t sym_tab_idx = 0; 3517509ff7cSJens Wiklander Elf64_Sym *sym_tab = NULL; 3527509ff7cSJens Wiklander size_t num_syms = 0; 3537509ff7cSJens Wiklander size_t sh_end = 0; 3547509ff7cSJens Wiklander const char *str_tab = NULL; 3557509ff7cSJens Wiklander size_t str_tab_size = 0; 3567509ff7cSJens Wiklander 3577509ff7cSJens Wiklander assert(shdr[rel_sidx].sh_type == SHT_RELA); 3587509ff7cSJens Wiklander 3597509ff7cSJens Wiklander assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela)); 3607509ff7cSJens Wiklander 3617509ff7cSJens Wiklander sym_tab_idx = shdr[rel_sidx].sh_link; 3627509ff7cSJens Wiklander if (sym_tab_idx) { 3637509ff7cSJens Wiklander size_t str_tab_idx = 0; 3647509ff7cSJens Wiklander 365447354c6SJens Wiklander if (sym_tab_idx >= elf->e_shnum) 366dcf64f87SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range"); 36755e64090SJens Wiklander sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum); 3687509ff7cSJens Wiklander 3697509ff7cSJens Wiklander assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym)); 3707509ff7cSJens Wiklander 3717509ff7cSJens Wiklander /* Check the address is inside TA memory */ 3727509ff7cSJens Wiklander if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, 3737509ff7cSJens Wiklander shdr[sym_tab_idx].sh_size, &sh_end)) 374e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Overflow"); 375447354c6SJens Wiklander if (sh_end >= (elf->max_addr - elf->load_addr)) 376dcf64f87SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range"); 3777509ff7cSJens Wiklander 3787509ff7cSJens Wiklander sym_tab = (Elf64_Sym *)(elf->load_addr + 3797509ff7cSJens Wiklander shdr[sym_tab_idx].sh_addr); 3807509ff7cSJens Wiklander 3817509ff7cSJens Wiklander num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym); 3827509ff7cSJens Wiklander 3837509ff7cSJens Wiklander str_tab_idx = shdr[sym_tab_idx].sh_link; 3847509ff7cSJens Wiklander if (str_tab_idx) { 38555e64090SJens Wiklander if (str_tab_idx >= elf->e_shnum) 386e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 387dcf64f87SJens Wiklander "STRTAB index out of range"); 38855e64090SJens Wiklander str_tab_idx = confine_array_index(str_tab_idx, 38955e64090SJens Wiklander elf->e_shnum); 39055e64090SJens Wiklander 3917509ff7cSJens Wiklander /* Check the address is inside ELF memory */ 3927509ff7cSJens Wiklander if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, 3937509ff7cSJens Wiklander shdr[str_tab_idx].sh_size, &sh_end)) 394e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Overflow"); 395447354c6SJens Wiklander if (sh_end >= (elf->max_addr - elf->load_addr)) 396e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 397dcf64f87SJens Wiklander "STRTAB out of range"); 3987509ff7cSJens Wiklander 3997509ff7cSJens Wiklander str_tab = (const char *)(elf->load_addr + 4007509ff7cSJens Wiklander shdr[str_tab_idx].sh_addr); 4017509ff7cSJens Wiklander str_tab_size = shdr[str_tab_idx].sh_size; 4027509ff7cSJens Wiklander } 4037509ff7cSJens Wiklander } 4047509ff7cSJens Wiklander 4057509ff7cSJens Wiklander /* Check the address is inside TA memory */ 406447354c6SJens Wiklander if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, 407447354c6SJens Wiklander shdr[rel_sidx].sh_size, &sh_end)) 408e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Overflow"); 409447354c6SJens Wiklander if (sh_end >= (elf->max_addr - elf->load_addr)) 410dcf64f87SJens Wiklander err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range"); 4117509ff7cSJens Wiklander rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr); 4127509ff7cSJens Wiklander 4137509ff7cSJens Wiklander rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela); 4147509ff7cSJens Wiklander for (; rela < rela_end; rela++) { 4157509ff7cSJens Wiklander Elf64_Addr *where = NULL; 4167509ff7cSJens Wiklander size_t sym_idx = 0; 4177509ff7cSJens Wiklander 4187509ff7cSJens Wiklander /* Check the address is inside TA memory */ 419447354c6SJens Wiklander if (rela->r_offset >= (elf->max_addr - elf->load_addr)) 420e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 421447354c6SJens Wiklander "Relocation offset out of range"); 4227509ff7cSJens Wiklander 4237509ff7cSJens Wiklander where = (Elf64_Addr *)(elf->load_addr + rela->r_offset); 4247509ff7cSJens Wiklander 4257509ff7cSJens Wiklander switch (ELF64_R_TYPE(rela->r_info)) { 4267509ff7cSJens Wiklander case R_AARCH64_ABS64: 4277509ff7cSJens Wiklander sym_idx = ELF64_R_SYM(rela->r_info); 428447354c6SJens Wiklander if (sym_idx >= num_syms) 429e97bbbb2SJens Wiklander err(TEE_ERROR_BAD_FORMAT, 430447354c6SJens Wiklander "Symbol index out of range"); 43155e64090SJens Wiklander sym_idx = confine_array_index(sym_idx, num_syms); 4327509ff7cSJens Wiklander if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { 4337509ff7cSJens Wiklander /* Symbol is external */ 4347509ff7cSJens Wiklander e64_process_dyn_rela(sym_tab, num_syms, str_tab, 4357509ff7cSJens Wiklander str_tab_size, rela, where); 4367509ff7cSJens Wiklander } else { 4377509ff7cSJens Wiklander *where = rela->r_addend + elf->load_addr + 4387509ff7cSJens Wiklander sym_tab[sym_idx].st_value; 4397509ff7cSJens Wiklander } 4407509ff7cSJens Wiklander break; 4417509ff7cSJens Wiklander case R_AARCH64_RELATIVE: 4427509ff7cSJens Wiklander *where = rela->r_addend + elf->load_addr; 4437509ff7cSJens Wiklander break; 4447509ff7cSJens Wiklander case R_AARCH64_GLOB_DAT: 4457509ff7cSJens Wiklander case R_AARCH64_JUMP_SLOT: 4467509ff7cSJens Wiklander e64_process_dyn_rela(sym_tab, num_syms, str_tab, 4477509ff7cSJens Wiklander str_tab_size, rela, where); 4487509ff7cSJens Wiklander break; 4497509ff7cSJens Wiklander default: 4507509ff7cSJens Wiklander err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd", 4517509ff7cSJens Wiklander ELF64_R_TYPE(rela->r_info)); 4527509ff7cSJens Wiklander } 4537509ff7cSJens Wiklander } 4547509ff7cSJens Wiklander } 4557509ff7cSJens Wiklander #else /*ARM64*/ 4565548a710SJerome Forissier static void __noreturn e64_relocate(struct ta_elf *elf __unused, 4577509ff7cSJens Wiklander unsigned int rel_sidx __unused) 4587509ff7cSJens Wiklander { 4597509ff7cSJens Wiklander err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported"); 4607509ff7cSJens Wiklander } 4617509ff7cSJens Wiklander #endif /*ARM64*/ 4627509ff7cSJens Wiklander 4637509ff7cSJens Wiklander void ta_elf_relocate(struct ta_elf *elf) 4647509ff7cSJens Wiklander { 4657509ff7cSJens Wiklander size_t n = 0; 4667509ff7cSJens Wiklander 4677509ff7cSJens Wiklander if (elf->is_32bit) { 4687509ff7cSJens Wiklander Elf32_Shdr *shdr = elf->shdr; 4697509ff7cSJens Wiklander 4707509ff7cSJens Wiklander for (n = 0; n < elf->e_shnum; n++) 4717509ff7cSJens Wiklander if (shdr[n].sh_type == SHT_REL) 4727509ff7cSJens Wiklander e32_relocate(elf, n); 4737509ff7cSJens Wiklander } else { 4747509ff7cSJens Wiklander Elf64_Shdr *shdr = elf->shdr; 4757509ff7cSJens Wiklander 4767509ff7cSJens Wiklander for (n = 0; n < elf->e_shnum; n++) 4777509ff7cSJens Wiklander if (shdr[n].sh_type == SHT_RELA) 4787509ff7cSJens Wiklander e64_relocate(elf, n); 4797509ff7cSJens Wiklander 4807509ff7cSJens Wiklander } 4817509ff7cSJens Wiklander } 482