1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <compiler.h> 8 #include <elf32.h> 9 #include <elf64.h> 10 #include <elf_common.h> 11 #include <string.h> 12 #include <tee_api_types.h> 13 #include <util.h> 14 15 #include "sys.h" 16 #include "ta_elf.h" 17 18 static uint32_t elf_hash(const char *name) 19 { 20 const unsigned char *p = (const unsigned char *)name; 21 uint32_t h = 0; 22 uint32_t g = 0; 23 24 while (*p) { 25 h = (h << 4) + *p++; 26 g = h & 0xf0000000; 27 if (g) 28 h ^= g >> 24; 29 h &= ~g; 30 } 31 return h; 32 } 33 34 static bool __resolve_sym(struct ta_elf *elf, unsigned int bind, 35 size_t st_shndx, size_t st_name, size_t st_value, 36 const char *name, vaddr_t *val) 37 { 38 if (bind != STB_GLOBAL) 39 return false; 40 if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX) 41 return false; 42 if (!st_name) 43 return false; 44 if (st_name > elf->dynstr_size) 45 err(TEE_ERROR_BAD_FORMAT, "Symbol out of range"); 46 47 if (strcmp(name, elf->dynstr + st_name)) 48 return false; 49 50 *val = st_value + elf->load_addr; 51 return true; 52 } 53 54 static TEE_Result resolve_sym_helper(uint32_t hash, const char *name, 55 vaddr_t *val, struct ta_elf *elf) 56 { 57 /* 58 * Using uint32_t here for convenience because both Elf64_Word 59 * and Elf32_Word are 32-bit types 60 */ 61 uint32_t *hashtab = elf->hashtab; 62 uint32_t nbuckets = hashtab[0]; 63 uint32_t nchains = hashtab[1]; 64 uint32_t *bucket = &hashtab[2]; 65 uint32_t *chain = &bucket[nbuckets]; 66 size_t n = 0; 67 68 if (elf->is_32bit) { 69 Elf32_Sym *sym = elf->dynsymtab; 70 71 for (n = bucket[hash % nbuckets]; n; n = chain[n]) { 72 if (n >= nchains || n >= elf->num_dynsyms) 73 err(TEE_ERROR_BAD_FORMAT, 74 "Index out of range"); 75 if (__resolve_sym(elf, 76 ELF32_ST_BIND(sym[n].st_info), 77 sym[n].st_shndx, 78 sym[n].st_name, 79 sym[n].st_value, name, val)) 80 return TEE_SUCCESS; 81 } 82 } else { 83 Elf64_Sym *sym = elf->dynsymtab; 84 85 for (n = bucket[hash % nbuckets]; n; n = chain[n]) { 86 if (n >= nchains || n >= elf->num_dynsyms) 87 err(TEE_ERROR_BAD_FORMAT, 88 "Index out of range"); 89 if (__resolve_sym(elf, 90 ELF64_ST_BIND(sym[n].st_info), 91 sym[n].st_shndx, 92 sym[n].st_name, 93 sym[n].st_value, name, val)) 94 return TEE_SUCCESS; 95 } 96 } 97 98 return TEE_ERROR_ITEM_NOT_FOUND; 99 } 100 101 TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val, 102 struct ta_elf *elf) 103 { 104 uint32_t hash = elf_hash(name); 105 106 if (elf) 107 return resolve_sym_helper(hash, name, val, elf); 108 109 TAILQ_FOREACH(elf, &main_elf_queue, link) 110 if (!resolve_sym_helper(hash, name, val, elf)) 111 return TEE_SUCCESS; 112 113 return TEE_ERROR_ITEM_NOT_FOUND; 114 } 115 116 static void resolve_sym(const char *name, vaddr_t *val) 117 { 118 TEE_Result res = ta_elf_resolve_sym(name, val, NULL); 119 120 if (res) 121 err(res, "Symbol %s not found", name); 122 } 123 124 static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms, 125 const char *str_tab, size_t str_tab_size, 126 Elf32_Rel *rel, Elf32_Addr *where) 127 { 128 size_t sym_idx = 0; 129 const char *name = NULL; 130 vaddr_t val = 0; 131 size_t name_idx = 0; 132 133 sym_idx = ELF32_R_SYM(rel->r_info); 134 if (sym_idx >= num_syms) 135 err(TEE_ERROR_GENERIC, "Symbol index out of range"); 136 137 name_idx = sym_tab[sym_idx].st_name; 138 if (name_idx >= str_tab_size) 139 err(TEE_ERROR_GENERIC, "Name index out of range"); 140 name = str_tab + name_idx; 141 142 resolve_sym(name, &val); 143 *where = val; 144 } 145 146 static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx) 147 { 148 Elf32_Shdr *shdr = elf->shdr; 149 Elf32_Rel *rel = NULL; 150 Elf32_Rel *rel_end = NULL; 151 size_t sym_tab_idx = 0; 152 Elf32_Sym *sym_tab = NULL; 153 size_t num_syms = 0; 154 size_t sh_end = 0; 155 const char *str_tab = NULL; 156 size_t str_tab_size = 0; 157 158 assert(shdr[rel_sidx].sh_type == SHT_REL); 159 160 assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel)); 161 162 sym_tab_idx = shdr[rel_sidx].sh_link; 163 if (sym_tab_idx) { 164 size_t str_tab_idx = 0; 165 166 if (sym_tab_idx >= elf->e_shnum) 167 err(TEE_ERROR_GENERIC, "Symtab index out of range"); 168 169 assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym)); 170 171 /* Check the address is inside ELF memory */ 172 if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, 173 shdr[sym_tab_idx].sh_size, &sh_end)) 174 err(TEE_ERROR_SECURITY, "Overflow"); 175 if (sh_end >= (elf->max_addr - elf->load_addr)) 176 err(TEE_ERROR_GENERIC, "Symbol table out of range"); 177 178 sym_tab = (Elf32_Sym *)(elf->load_addr + 179 shdr[sym_tab_idx].sh_addr); 180 181 num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym); 182 183 str_tab_idx = shdr[sym_tab_idx].sh_link; 184 if (str_tab_idx) { 185 /* Check the address is inside ELF memory */ 186 if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, 187 shdr[str_tab_idx].sh_size, &sh_end)) 188 err(TEE_ERROR_SECURITY, "Overflow"); 189 if (sh_end >= (elf->max_addr - elf->load_addr)) 190 err(TEE_ERROR_GENERIC, 191 "String table out of range"); 192 193 str_tab = (const char *)(elf->load_addr + 194 shdr[str_tab_idx].sh_addr); 195 str_tab_size = shdr[str_tab_idx].sh_size; 196 } 197 } 198 199 /* Check the address is inside TA memory */ 200 if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, 201 shdr[rel_sidx].sh_size, &sh_end)) 202 err(TEE_ERROR_SECURITY, "Overflow"); 203 if (sh_end >= (elf->max_addr - elf->load_addr)) 204 err(TEE_ERROR_GENERIC, "Relocation table out of range"); 205 rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr); 206 207 rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel); 208 for (; rel < rel_end; rel++) { 209 Elf32_Addr *where = NULL; 210 size_t sym_idx = 0; 211 212 /* Check the address is inside TA memory */ 213 if (rel->r_offset >= (elf->max_addr - elf->load_addr)) 214 err(TEE_ERROR_GENERIC, 215 "Relocation offset out of range"); 216 where = (Elf32_Addr *)(elf->load_addr + rel->r_offset); 217 218 switch (ELF32_R_TYPE(rel->r_info)) { 219 case R_ARM_ABS32: 220 sym_idx = ELF32_R_SYM(rel->r_info); 221 if (sym_idx >= num_syms) 222 err(TEE_ERROR_GENERIC, 223 "Symbol index out of range"); 224 if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { 225 /* Symbol is external */ 226 e32_process_dyn_rel(sym_tab, num_syms, str_tab, 227 str_tab_size, rel, where); 228 } else { 229 *where += elf->load_addr + 230 sym_tab[sym_idx].st_value; 231 } 232 break; 233 case R_ARM_REL32: 234 sym_idx = ELF32_R_SYM(rel->r_info); 235 if (sym_idx >= num_syms) 236 err(TEE_ERROR_GENERIC, 237 "Symbol index out of range"); 238 *where += sym_tab[sym_idx].st_value - rel->r_offset; 239 break; 240 case R_ARM_RELATIVE: 241 *where += elf->load_addr; 242 break; 243 case R_ARM_GLOB_DAT: 244 case R_ARM_JUMP_SLOT: 245 e32_process_dyn_rel(sym_tab, num_syms, str_tab, 246 str_tab_size, rel, where); 247 break; 248 default: 249 err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d", 250 ELF32_R_TYPE(rel->r_info)); 251 } 252 } 253 } 254 255 #ifdef ARM64 256 static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms, 257 const char *str_tab, size_t str_tab_size, 258 Elf64_Rela *rela, Elf64_Addr *where) 259 { 260 size_t sym_idx = 0; 261 const char *name = NULL; 262 uintptr_t val = 0; 263 size_t name_idx = 0; 264 265 sym_idx = ELF64_R_SYM(rela->r_info); 266 if (sym_idx >= num_syms) 267 err(TEE_ERROR_GENERIC, "Symbol index out of range"); 268 269 name_idx = sym_tab[sym_idx].st_name; 270 if (name_idx >= str_tab_size) 271 err(TEE_ERROR_GENERIC, "Name index out of range"); 272 name = str_tab + name_idx; 273 274 resolve_sym(name, &val); 275 *where = val; 276 } 277 278 static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx) 279 { 280 Elf64_Shdr *shdr = elf->shdr; 281 Elf64_Rela *rela = NULL; 282 Elf64_Rela *rela_end = NULL; 283 size_t sym_tab_idx = 0; 284 Elf64_Sym *sym_tab = NULL; 285 size_t num_syms = 0; 286 size_t sh_end = 0; 287 const char *str_tab = NULL; 288 size_t str_tab_size = 0; 289 290 assert(shdr[rel_sidx].sh_type == SHT_RELA); 291 292 assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela)); 293 294 sym_tab_idx = shdr[rel_sidx].sh_link; 295 if (sym_tab_idx) { 296 size_t str_tab_idx = 0; 297 298 if (sym_tab_idx >= elf->e_shnum) 299 err(TEE_ERROR_GENERIC, "Symtab index out of range"); 300 301 assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym)); 302 303 /* Check the address is inside TA memory */ 304 if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, 305 shdr[sym_tab_idx].sh_size, &sh_end)) 306 err(TEE_ERROR_SECURITY, "Overflow"); 307 if (sh_end >= (elf->max_addr - elf->load_addr)) 308 err(TEE_ERROR_GENERIC, "Symbol table out of range"); 309 310 sym_tab = (Elf64_Sym *)(elf->load_addr + 311 shdr[sym_tab_idx].sh_addr); 312 313 num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym); 314 315 str_tab_idx = shdr[sym_tab_idx].sh_link; 316 if (str_tab_idx) { 317 /* Check the address is inside ELF memory */ 318 if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, 319 shdr[str_tab_idx].sh_size, &sh_end)) 320 err(TEE_ERROR_SECURITY, "Overflow"); 321 if (sh_end >= (elf->max_addr - elf->load_addr)) 322 err(TEE_ERROR_GENERIC, 323 "String table out of range"); 324 325 str_tab = (const char *)(elf->load_addr + 326 shdr[str_tab_idx].sh_addr); 327 str_tab_size = shdr[str_tab_idx].sh_size; 328 } 329 } 330 331 /* Check the address is inside TA memory */ 332 if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, 333 shdr[rel_sidx].sh_size, &sh_end)) 334 err(TEE_ERROR_SECURITY, "Overflow"); 335 if (sh_end >= (elf->max_addr - elf->load_addr)) 336 err(TEE_ERROR_GENERIC, "Relocation table out of range"); 337 rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr); 338 339 rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela); 340 for (; rela < rela_end; rela++) { 341 Elf64_Addr *where = NULL; 342 size_t sym_idx = 0; 343 344 /* Check the address is inside TA memory */ 345 if (rela->r_offset >= (elf->max_addr - elf->load_addr)) 346 err(TEE_ERROR_GENERIC, 347 "Relocation offset out of range"); 348 349 where = (Elf64_Addr *)(elf->load_addr + rela->r_offset); 350 351 switch (ELF64_R_TYPE(rela->r_info)) { 352 case R_AARCH64_ABS64: 353 sym_idx = ELF64_R_SYM(rela->r_info); 354 if (sym_idx >= num_syms) 355 err(TEE_ERROR_GENERIC, 356 "Symbol index out of range"); 357 if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { 358 /* Symbol is external */ 359 e64_process_dyn_rela(sym_tab, num_syms, str_tab, 360 str_tab_size, rela, where); 361 } else { 362 *where = rela->r_addend + elf->load_addr + 363 sym_tab[sym_idx].st_value; 364 } 365 break; 366 case R_AARCH64_RELATIVE: 367 *where = rela->r_addend + elf->load_addr; 368 break; 369 case R_AARCH64_GLOB_DAT: 370 case R_AARCH64_JUMP_SLOT: 371 e64_process_dyn_rela(sym_tab, num_syms, str_tab, 372 str_tab_size, rela, where); 373 break; 374 default: 375 err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd", 376 ELF64_R_TYPE(rela->r_info)); 377 } 378 } 379 } 380 #else /*ARM64*/ 381 static void __noreturn e64_relocate(struct ta_elf *elf __unused, 382 unsigned int rel_sidx __unused) 383 { 384 err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported"); 385 } 386 #endif /*ARM64*/ 387 388 void ta_elf_relocate(struct ta_elf *elf) 389 { 390 size_t n = 0; 391 392 if (elf->is_32bit) { 393 Elf32_Shdr *shdr = elf->shdr; 394 395 for (n = 0; n < elf->e_shnum; n++) 396 if (shdr[n].sh_type == SHT_REL) 397 e32_relocate(elf, n); 398 } else { 399 Elf64_Shdr *shdr = elf->shdr; 400 401 for (n = 0; n < elf->e_shnum; n++) 402 if (shdr[n].sh_type == SHT_RELA) 403 e64_relocate(elf, n); 404 405 } 406 } 407