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