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 <confine_array_index.h>
9 #include <elf32.h>
10 #include <elf64.h>
11 #include <elf_common.h>
12 #include <string.h>
13 #include <tee_api_types.h>
14 #include <util.h>
15
16 #include "sys.h"
17 #include "ta_elf.h"
18
elf_hash(const char * name)19 static uint32_t elf_hash(const char *name)
20 {
21 const unsigned char *p = (const unsigned char *)name;
22 uint32_t h = 0;
23 uint32_t g = 0;
24
25 while (*p) {
26 h = (h << 4) + *p++;
27 g = h & 0xf0000000;
28 if (g)
29 h ^= g >> 24;
30 h &= ~g;
31 }
32 return h;
33 }
34
gnu_hash(const char * name)35 static uint32_t gnu_hash(const char *name)
36 {
37 const unsigned char *p = (const unsigned char *)name;
38 uint32_t h = 5381;
39
40 while (*p)
41 h = (h << 5) + h + *p++;
42
43 return h;
44 }
45
sym_compare(struct ta_elf * elf,unsigned int st_bind,unsigned int st_type,size_t st_shndx,size_t st_name,size_t st_value,const char * name,vaddr_t * val,bool weak_ok)46 static bool sym_compare(struct ta_elf *elf, unsigned int st_bind,
47 unsigned int st_type, size_t st_shndx,
48 size_t st_name, size_t st_value, const char *name,
49 vaddr_t *val, bool weak_ok)
50 {
51 bool bind_ok = false;
52
53 if (!st_name)
54 return false;
55 if (st_name > elf->dynstr_size)
56 err(TEE_ERROR_BAD_FORMAT, "Symbol name out of range");
57 if (strcmp(name, elf->dynstr + st_name))
58 return false;
59 if (st_bind == STB_GLOBAL || (weak_ok && st_bind == STB_WEAK))
60 bind_ok = true;
61 if (!bind_ok)
62 return false;
63 if (st_bind == STB_WEAK && st_shndx == SHN_UNDEF) {
64 if (val)
65 *val = 0;
66 return true;
67 }
68 if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX)
69 return false;
70
71 switch (st_type) {
72 case STT_NOTYPE:
73 case STT_OBJECT:
74 case STT_FUNC:
75 if (st_value > (elf->max_addr - elf->load_addr))
76 err(TEE_ERROR_BAD_FORMAT,
77 "Symbol location out of range");
78 if (val)
79 *val = st_value + elf->load_addr;
80 break;
81 case STT_TLS:
82 if (val)
83 *val = st_value;
84 break;
85 default:
86 err(TEE_ERROR_NOT_SUPPORTED, "Symbol type not supported");
87 }
88
89 return true;
90 }
91
check_found_sym(struct ta_elf * elf,const char * name,vaddr_t * val,bool weak_ok,size_t n)92 static bool check_found_sym(struct ta_elf *elf, const char *name, vaddr_t *val,
93 bool weak_ok, size_t n)
94 {
95 Elf32_Sym *sym32 = NULL;
96 Elf64_Sym *sym64 = NULL;
97 unsigned int st_bind = 0;
98 unsigned int st_type = 0;
99 size_t st_shndx = 0;
100 size_t st_name = 0;
101 size_t st_value = 0;
102
103 if (n >= elf->num_dynsyms)
104 err(TEE_ERROR_BAD_FORMAT, "Index out of range");
105
106 /*
107 * We're loading values from sym[] which later
108 * will be used to load something.
109 * => Spectre V1 pattern, need to cap the index
110 * against speculation.
111 */
112 n = confine_array_index(n, elf->num_dynsyms);
113
114 if (elf->is_32bit) {
115 sym32 = elf->dynsymtab;
116 st_bind = ELF32_ST_BIND(sym32[n].st_info);
117 st_type = ELF32_ST_TYPE(sym32[n].st_info);
118 st_shndx = sym32[n].st_shndx;
119 st_name = sym32[n].st_name;
120 st_value = sym32[n].st_value;
121 } else {
122 sym64 = elf->dynsymtab;
123 st_bind = ELF64_ST_BIND(sym64[n].st_info);
124 st_type = ELF64_ST_TYPE(sym64[n].st_info);
125 st_shndx = sym64[n].st_shndx;
126 st_name = sym64[n].st_name;
127 st_value = sym64[n].st_value;
128 }
129
130 return sym_compare(elf, st_bind, st_type, st_shndx, st_name, st_value,
131 name, val, weak_ok);
132 }
133
resolve_sym_helper(const char * name,vaddr_t * val,struct ta_elf * elf,bool weak_ok)134 static TEE_Result resolve_sym_helper(const char *name, vaddr_t *val,
135 struct ta_elf *elf, bool weak_ok)
136 {
137 uint32_t n = 0;
138 uint32_t hash = 0;
139
140 if (elf->gnu_hashtab) {
141 struct gnu_hashtab *h = elf->gnu_hashtab;
142 uint32_t *end = (void *)((uint8_t *)elf->gnu_hashtab +
143 elf->gnu_hashtab_size);
144 uint32_t *bucket = NULL;
145 uint32_t *chain = NULL;
146 uint32_t hashval = 0;
147
148 hash = gnu_hash(name);
149
150 if (elf->is_32bit) {
151 uint32_t *bloom = (void *)(h + 1);
152 uint32_t word = bloom[(hash / 32) % h->bloom_size];
153 uint32_t mask = BIT32(hash % 32) |
154 BIT32((hash >> h->bloom_shift) % 32);
155
156 if ((word & mask) != mask)
157 return TEE_ERROR_ITEM_NOT_FOUND;
158 bucket = bloom + h->bloom_size;
159 } else {
160 uint64_t *bloom = (void *)(h + 1);
161 uint64_t word = bloom[(hash / 64) % h->bloom_size];
162 uint64_t mask = BIT64(hash % 64) |
163 BIT64((hash >> h->bloom_shift) % 64);
164
165 if ((word & mask) != mask)
166 return TEE_ERROR_ITEM_NOT_FOUND;
167 bucket = (uint32_t *)(bloom + h->bloom_size);
168 }
169 chain = bucket + h->nbuckets;
170
171 n = bucket[hash % h->nbuckets];
172 if (n < h->symoffset)
173 return TEE_ERROR_ITEM_NOT_FOUND;
174
175 hash |= 1;
176 do {
177 size_t idx = n - h->symoffset;
178
179 if (chain + idx > end)
180 return TEE_ERROR_ITEM_NOT_FOUND;
181
182 hashval = chain[idx];
183
184 if ((hashval | 1) == hash &&
185 check_found_sym(elf, name, val, weak_ok, n))
186 return TEE_SUCCESS;
187
188 n++;
189 } while (!(hashval & 1));
190 } else if (elf->hashtab) {
191 /*
192 * Using uint32_t here for convenience because both Elf64_Word
193 * and Elf32_Word are 32-bit types
194 */
195 uint32_t *hashtab = elf->hashtab;
196 uint32_t nbuckets = hashtab[0];
197 uint32_t nchains = hashtab[1];
198 uint32_t *bucket = &hashtab[2];
199 uint32_t *chain = &bucket[nbuckets];
200
201 if (!nbuckets)
202 return TEE_ERROR_ITEM_NOT_FOUND;
203
204 hash = elf_hash(name);
205
206 for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
207 if (n >= nchains)
208 err(TEE_ERROR_BAD_FORMAT, "Index out of range");
209 if (check_found_sym(elf, name, val, weak_ok, n))
210 return TEE_SUCCESS;
211 }
212 }
213
214 return TEE_ERROR_ITEM_NOT_FOUND;
215 }
216
217 /*
218 * Look for named symbol in @elf, or all modules if @elf == NULL. Global symbols
219 * are searched first, then weak ones. Last option, when at least one weak but
220 * undefined symbol exists, resolve to zero. Otherwise return
221 * TEE_ERROR_ITEM_NOT_FOUND.
222 * @val (if != 0) receives the symbol value
223 * @found_elf (if != 0) receives the module where the symbol is found
224 */
ta_elf_resolve_sym(const char * name,vaddr_t * val,struct ta_elf ** found_elf,struct ta_elf * elf)225 TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val,
226 struct ta_elf **found_elf,
227 struct ta_elf *elf)
228 {
229 if (elf) {
230 /* Search global symbols */
231 if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */))
232 goto success;
233 /* Search weak symbols */
234 if (!resolve_sym_helper(name, val, elf, true /* weak_ok */))
235 goto success;
236 }
237
238 TAILQ_FOREACH(elf, &main_elf_queue, link) {
239 if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */))
240 goto success;
241 if (!resolve_sym_helper(name, val, elf, true /* weak_ok */))
242 goto success;
243 }
244
245 return TEE_ERROR_ITEM_NOT_FOUND;
246
247 success:
248 if (found_elf)
249 *found_elf = elf;
250 return TEE_SUCCESS;
251 }
252
e32_get_sym_name(const Elf32_Sym * sym_tab,size_t num_syms,const char * str_tab,size_t str_tab_size,Elf32_Rel * rel,const char ** name,bool * weak_undef)253 static void e32_get_sym_name(const Elf32_Sym *sym_tab, size_t num_syms,
254 const char *str_tab, size_t str_tab_size,
255 Elf32_Rel *rel, const char **name,
256 bool *weak_undef)
257 {
258 size_t sym_idx = 0;
259 size_t name_idx = 0;
260
261 sym_idx = ELF32_R_SYM(rel->r_info);
262 if (sym_idx >= num_syms)
263 err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range");
264 sym_idx = confine_array_index(sym_idx, num_syms);
265
266 name_idx = sym_tab[sym_idx].st_name;
267 if (name_idx >= str_tab_size)
268 err(TEE_ERROR_BAD_FORMAT, "Name index out of range");
269 *name = str_tab + name_idx;
270
271 if (!weak_undef)
272 return;
273 if (sym_tab[sym_idx].st_shndx == SHN_UNDEF &&
274 ELF32_ST_BIND(sym_tab[sym_idx].st_info) == STB_WEAK)
275 *weak_undef = true;
276 else
277 *weak_undef = false;
278 }
279
resolve_sym(const char * name,vaddr_t * val,struct ta_elf ** mod,bool err_if_not_found)280 static void resolve_sym(const char *name, vaddr_t *val, struct ta_elf **mod,
281 bool err_if_not_found)
282 {
283 TEE_Result res = ta_elf_resolve_sym(name, val, mod, NULL);
284
285 if (res) {
286 if (err_if_not_found)
287 err(res, "Symbol %s not found", name);
288 else if (val)
289 *val = 0;
290 }
291 }
292
e32_process_dyn_rel(const Elf32_Sym * sym_tab,size_t num_syms,const char * str_tab,size_t str_tab_size,Elf32_Rel * rel,Elf32_Addr * where)293 static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms,
294 const char *str_tab, size_t str_tab_size,
295 Elf32_Rel *rel, Elf32_Addr *where)
296 {
297 const char *name = NULL;
298 vaddr_t val = 0;
299 bool weak_undef = false;
300
301 e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name,
302 &weak_undef);
303 resolve_sym(name, &val, NULL, !weak_undef);
304 *where = val;
305 }
306
e32_tls_get_module(const Elf32_Sym * sym_tab,size_t num_syms,const char * str_tab,size_t str_tab_size,Elf32_Rel * rel,struct ta_elf ** mod)307 static void e32_tls_get_module(const Elf32_Sym *sym_tab, size_t num_syms,
308 const char *str_tab, size_t str_tab_size,
309 Elf32_Rel *rel, struct ta_elf **mod)
310 {
311 const char *name = NULL;
312 size_t sym_idx = 0;
313
314 sym_idx = ELF32_R_SYM(rel->r_info);
315 if (sym_idx >= num_syms)
316 err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range");
317 sym_idx = confine_array_index(sym_idx, num_syms);
318 if (!sym_idx || sym_tab[sym_idx].st_shndx != SHN_UNDEF) {
319 /* No symbol, or symbol is defined in current module */
320 return;
321 }
322
323 e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name,
324 NULL);
325 resolve_sym(name, NULL, mod, false);
326 }
327
e32_tls_resolve(const Elf32_Sym * sym_tab,size_t num_syms,const char * str_tab,size_t str_tab_size,Elf32_Rel * rel,vaddr_t * val)328 static void e32_tls_resolve(const Elf32_Sym *sym_tab, size_t num_syms,
329 const char *str_tab, size_t str_tab_size,
330 Elf32_Rel *rel, vaddr_t *val)
331 {
332 const char *name = NULL;
333
334 e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name,
335 NULL);
336 resolve_sym(name, val, NULL, false);
337 }
338
e32_relocate(struct ta_elf * elf,unsigned int rel_sidx)339 static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx)
340 {
341 Elf32_Shdr *shdr = elf->shdr;
342 Elf32_Rel *rel = NULL;
343 Elf32_Rel *rel_end = NULL;
344 size_t sym_tab_idx = 0;
345 Elf32_Sym *sym_tab = NULL;
346 size_t num_syms = 0;
347 size_t sh_end = 0;
348 const char *str_tab = NULL;
349 size_t str_tab_size = 0;
350
351 assert(shdr[rel_sidx].sh_type == SHT_REL);
352
353 assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel));
354
355 sym_tab_idx = shdr[rel_sidx].sh_link;
356 if (sym_tab_idx) {
357 size_t str_tab_idx = 0;
358
359 if (sym_tab_idx >= elf->e_shnum)
360 err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range");
361 sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum);
362
363 assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym));
364
365 /* Check the address is inside ELF memory */
366 if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
367 shdr[sym_tab_idx].sh_size, &sh_end))
368 err(TEE_ERROR_BAD_FORMAT, "Overflow");
369 if (sh_end >= (elf->max_addr - elf->load_addr))
370 err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range");
371
372 sym_tab = (Elf32_Sym *)(elf->load_addr +
373 shdr[sym_tab_idx].sh_addr);
374
375 num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym);
376
377 str_tab_idx = shdr[sym_tab_idx].sh_link;
378 if (str_tab_idx) {
379 if (str_tab_idx >= elf->e_shnum)
380 err(TEE_ERROR_BAD_FORMAT,
381 "STRTAB index out of range");
382 str_tab_idx = confine_array_index(str_tab_idx,
383 elf->e_shnum);
384
385 /* Check the address is inside ELF memory */
386 if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
387 shdr[str_tab_idx].sh_size, &sh_end))
388 err(TEE_ERROR_BAD_FORMAT, "Overflow");
389 if (sh_end >= (elf->max_addr - elf->load_addr))
390 err(TEE_ERROR_BAD_FORMAT,
391 "STRTAB out of range");
392
393 str_tab = (const char *)(elf->load_addr +
394 shdr[str_tab_idx].sh_addr);
395 str_tab_size = shdr[str_tab_idx].sh_size;
396 }
397 }
398
399 /* Check the address is inside TA memory */
400 if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr,
401 shdr[rel_sidx].sh_size, &sh_end))
402 err(TEE_ERROR_BAD_FORMAT, "Overflow");
403 if (sh_end >= (elf->max_addr - elf->load_addr))
404 err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range");
405 rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr);
406
407 rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel);
408 for (; rel < rel_end; rel++) {
409 struct ta_elf *mod = NULL;
410 Elf32_Addr *where = NULL;
411 size_t sym_idx = 0;
412 vaddr_t val = 0;
413
414 /* Check the address is inside TA memory */
415 if (rel->r_offset >= (elf->max_addr - elf->load_addr))
416 err(TEE_ERROR_BAD_FORMAT,
417 "Relocation offset out of range");
418 where = (Elf32_Addr *)(elf->load_addr + rel->r_offset);
419
420 switch (ELF32_R_TYPE(rel->r_info)) {
421 case R_ARM_NONE:
422 /*
423 * One would expect linker prevents such useless entry
424 * in the relocation table. We still handle this type
425 * here in case such entries exist.
426 */
427 break;
428 case R_ARM_ABS32:
429 sym_idx = ELF32_R_SYM(rel->r_info);
430 if (sym_idx >= num_syms)
431 err(TEE_ERROR_BAD_FORMAT,
432 "Symbol index out of range");
433 if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
434 /* Symbol is external */
435 e32_process_dyn_rel(sym_tab, num_syms, str_tab,
436 str_tab_size, rel, where);
437 } else {
438 *where += elf->load_addr +
439 sym_tab[sym_idx].st_value;
440 }
441 break;
442 case R_ARM_REL32:
443 sym_idx = ELF32_R_SYM(rel->r_info);
444 if (sym_idx >= num_syms)
445 err(TEE_ERROR_BAD_FORMAT,
446 "Symbol index out of range");
447 *where += sym_tab[sym_idx].st_value - rel->r_offset;
448 break;
449 case R_ARM_RELATIVE:
450 *where += elf->load_addr;
451 break;
452 case R_ARM_GLOB_DAT:
453 case R_ARM_JUMP_SLOT:
454 if (!sym_tab)
455 err(TEE_ERROR_BAD_FORMAT,
456 "Missing symbol table");
457 e32_process_dyn_rel(sym_tab, num_syms, str_tab,
458 str_tab_size, rel, where);
459 break;
460 case R_ARM_TLS_DTPMOD32:
461 if (!sym_tab)
462 err(TEE_ERROR_BAD_FORMAT,
463 "Missing symbol table");
464 mod = elf;
465 e32_tls_get_module(sym_tab, num_syms, str_tab,
466 str_tab_size, rel, &mod);
467 *where = mod->tls_mod_id;
468 break;
469 case R_ARM_TLS_DTPOFF32:
470 if (!sym_tab)
471 err(TEE_ERROR_BAD_FORMAT,
472 "Missing symbol table");
473 e32_tls_resolve(sym_tab, num_syms, str_tab,
474 str_tab_size, rel, &val);
475 *where = val;
476 break;
477 default:
478 err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d",
479 ELF32_R_TYPE(rel->r_info));
480 }
481 }
482 }
483
484 #if defined(ARM64) || defined(RV64)
e64_get_sym_name(const Elf64_Sym * sym_tab,size_t num_syms,const char * str_tab,size_t str_tab_size,Elf64_Rela * rela,const char ** name,bool * weak_undef)485 static void e64_get_sym_name(const Elf64_Sym *sym_tab, size_t num_syms,
486 const char *str_tab, size_t str_tab_size,
487 Elf64_Rela *rela, const char **name,
488 bool *weak_undef)
489 {
490 size_t sym_idx = 0;
491 size_t name_idx = 0;
492
493 sym_idx = ELF64_R_SYM(rela->r_info);
494 if (sym_idx >= num_syms)
495 err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range");
496 sym_idx = confine_array_index(sym_idx, num_syms);
497
498 name_idx = sym_tab[sym_idx].st_name;
499 if (name_idx >= str_tab_size)
500 err(TEE_ERROR_BAD_FORMAT, "Name index out of range");
501 *name = str_tab + name_idx;
502
503 if (sym_tab[sym_idx].st_shndx == SHN_UNDEF &&
504 ELF64_ST_BIND(sym_tab[sym_idx].st_info) == STB_WEAK)
505 *weak_undef = true;
506 else
507 *weak_undef = false;
508 }
509
e64_process_dyn_rela(const Elf64_Sym * sym_tab,size_t num_syms,const char * str_tab,size_t str_tab_size,Elf64_Rela * rela,Elf64_Addr * where)510 static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms,
511 const char *str_tab, size_t str_tab_size,
512 Elf64_Rela *rela, Elf64_Addr *where)
513 {
514 const char *name = NULL;
515 uintptr_t val = 0;
516 bool weak_undef = false;
517
518 e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela, &name,
519 &weak_undef);
520 resolve_sym(name, &val, NULL, !weak_undef);
521 *where = val;
522 }
523
524 #ifdef ARM64
e64_process_tls_tprel_rela(const Elf64_Sym * sym_tab,size_t num_syms,const char * str_tab,size_t str_tab_size,Elf64_Rela * rela,Elf64_Addr * where,struct ta_elf * elf)525 static void e64_process_tls_tprel_rela(const Elf64_Sym *sym_tab,
526 size_t num_syms, const char *str_tab,
527 size_t str_tab_size, Elf64_Rela *rela,
528 Elf64_Addr *where, struct ta_elf *elf)
529 {
530 struct ta_elf *mod = NULL;
531 bool weak_undef = false;
532 const char *name = NULL;
533 size_t sym_idx = 0;
534 vaddr_t symval = 0;
535
536 sym_idx = ELF64_R_SYM(rela->r_info);
537 if (sym_idx) {
538 e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela,
539 &name, &weak_undef);
540 resolve_sym(name, &symval, &mod, !weak_undef);
541 } else {
542 mod = elf;
543 }
544 *where = symval + mod->tls_tcb_offs + rela->r_addend;
545 }
546
547 struct tlsdesc {
548 long (*resolver)(struct tlsdesc *td);
549 long value;
550 };
551
552 /* Helper function written in assembly due to the calling convention */
553 long tlsdesc_resolve(struct tlsdesc *td);
554
e64_process_tlsdesc_rela(const Elf64_Sym * sym_tab,size_t num_syms,const char * str_tab,size_t str_tab_size,Elf64_Rela * rela,Elf64_Addr * where,struct ta_elf * elf)555 static void e64_process_tlsdesc_rela(const Elf64_Sym *sym_tab, size_t num_syms,
556 const char *str_tab, size_t str_tab_size,
557 Elf64_Rela *rela, Elf64_Addr *where,
558 struct ta_elf *elf)
559 {
560 /*
561 * @where points to a pair of 64-bit words in the GOT or PLT which is
562 * mapped to a struct tlsdesc:
563 *
564 * - resolver() must return the offset of the thread-local variable
565 * relative to TPIDR_EL0.
566 * - value is implementation-dependent. The TLS_TPREL handling code is
567 * re-used to get the desired offset so that tlsdesc_resolve() just
568 * needs to return this value.
569 *
570 * Both the TA and ldelf are AArch64 so it is OK to point to a function
571 * in ldelf.
572 */
573 *where = (Elf64_Addr)tlsdesc_resolve;
574 e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab, str_tab_size,
575 rela, where + 1, elf);
576 }
577 #endif /*ARM64*/
578
e64_relocate(struct ta_elf * elf,unsigned int rel_sidx)579 static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx)
580 {
581 Elf64_Shdr *shdr = elf->shdr;
582 Elf64_Rela *rela = NULL;
583 Elf64_Rela *rela_end = NULL;
584 size_t sym_tab_idx = 0;
585 Elf64_Sym *sym_tab = NULL;
586 size_t num_syms = 0;
587 size_t sh_end = 0;
588 const char *str_tab = NULL;
589 size_t str_tab_size = 0;
590
591 assert(shdr[rel_sidx].sh_type == SHT_RELA);
592
593 assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela));
594
595 sym_tab_idx = shdr[rel_sidx].sh_link;
596 if (sym_tab_idx) {
597 size_t str_tab_idx = 0;
598
599 if (sym_tab_idx >= elf->e_shnum)
600 err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range");
601 sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum);
602
603 assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym));
604
605 /* Check the address is inside TA memory */
606 if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
607 shdr[sym_tab_idx].sh_size, &sh_end))
608 err(TEE_ERROR_BAD_FORMAT, "Overflow");
609 if (sh_end >= (elf->max_addr - elf->load_addr))
610 err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range");
611
612 sym_tab = (Elf64_Sym *)(elf->load_addr +
613 shdr[sym_tab_idx].sh_addr);
614
615 num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym);
616
617 str_tab_idx = shdr[sym_tab_idx].sh_link;
618 if (str_tab_idx) {
619 if (str_tab_idx >= elf->e_shnum)
620 err(TEE_ERROR_BAD_FORMAT,
621 "STRTAB index out of range");
622 str_tab_idx = confine_array_index(str_tab_idx,
623 elf->e_shnum);
624
625 /* Check the address is inside ELF memory */
626 if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
627 shdr[str_tab_idx].sh_size, &sh_end))
628 err(TEE_ERROR_BAD_FORMAT, "Overflow");
629 if (sh_end >= (elf->max_addr - elf->load_addr))
630 err(TEE_ERROR_BAD_FORMAT,
631 "STRTAB out of range");
632
633 str_tab = (const char *)(elf->load_addr +
634 shdr[str_tab_idx].sh_addr);
635 str_tab_size = shdr[str_tab_idx].sh_size;
636 }
637 }
638
639 /* Check the address is inside TA memory */
640 if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr,
641 shdr[rel_sidx].sh_size, &sh_end))
642 err(TEE_ERROR_BAD_FORMAT, "Overflow");
643 if (sh_end >= (elf->max_addr - elf->load_addr))
644 err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range");
645 rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr);
646
647 rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela);
648 for (; rela < rela_end; rela++) {
649 Elf64_Addr *where = NULL;
650 size_t sym_idx __maybe_unused = 0;
651
652 /* Check the address is inside TA memory */
653 if (rela->r_offset >= (elf->max_addr - elf->load_addr))
654 err(TEE_ERROR_BAD_FORMAT,
655 "Relocation offset out of range");
656
657 where = (Elf64_Addr *)(elf->load_addr + rela->r_offset);
658
659 switch (ELF64_R_TYPE(rela->r_info)) {
660 #ifdef ARM64
661 case R_AARCH64_NONE:
662 /*
663 * One would expect linker prevents such useless entry
664 * in the relocation table. We still handle this type
665 * here in case such entries exist.
666 */
667 break;
668 case R_AARCH64_ABS64:
669 sym_idx = ELF64_R_SYM(rela->r_info);
670 if (sym_idx >= num_syms)
671 err(TEE_ERROR_BAD_FORMAT,
672 "Symbol index out of range");
673 sym_idx = confine_array_index(sym_idx, num_syms);
674 if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
675 /* Symbol is external */
676 e64_process_dyn_rela(sym_tab, num_syms, str_tab,
677 str_tab_size, rela, where);
678 } else {
679 *where = rela->r_addend + elf->load_addr +
680 sym_tab[sym_idx].st_value;
681 }
682 break;
683 case R_AARCH64_RELATIVE:
684 *where = rela->r_addend + elf->load_addr;
685 break;
686 case R_AARCH64_GLOB_DAT:
687 case R_AARCH64_JUMP_SLOT:
688 e64_process_dyn_rela(sym_tab, num_syms, str_tab,
689 str_tab_size, rela, where);
690 break;
691 case R_AARCH64_TLS_TPREL:
692 e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab,
693 str_tab_size, rela, where,
694 elf);
695 break;
696 case R_AARCH64_TLSDESC:
697 e64_process_tlsdesc_rela(sym_tab, num_syms, str_tab,
698 str_tab_size, rela, where,
699 elf);
700 break;
701 #endif /*ARM64*/
702 #ifdef RV64
703 case R_RISCV_NONE:
704 /*
705 * One would expect linker prevents such useless entry
706 * in the relocation table. We still handle this type
707 * here in case such entries exist.
708 */
709 break;
710 case R_RISCV_RELATIVE:
711 *where = rela->r_addend + elf->load_addr;
712 break;
713 case R_RISCV_64:
714 e64_process_dyn_rela(sym_tab, num_syms, str_tab,
715 str_tab_size, rela, where);
716 *where += rela->r_addend;
717 break;
718 case R_RISCV_JUMP_SLOT:
719 e64_process_dyn_rela(sym_tab, num_syms, str_tab,
720 str_tab_size, rela, where);
721 break;
722 #endif /*RV64*/
723 default:
724 err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd",
725 ELF64_R_TYPE(rela->r_info));
726 }
727 }
728 }
729 #else /*ARM64 || RV64*/
e64_relocate(struct ta_elf * elf __unused,unsigned int rel_sidx __unused)730 static void __noreturn e64_relocate(struct ta_elf *elf __unused,
731 unsigned int rel_sidx __unused)
732 {
733 err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported");
734 }
735 #endif /*ARM64 || RV64*/
736
ta_elf_relocate(struct ta_elf * elf)737 void ta_elf_relocate(struct ta_elf *elf)
738 {
739 size_t n = 0;
740
741 if (elf->is_32bit) {
742 Elf32_Shdr *shdr = elf->shdr;
743
744 for (n = 0; n < elf->e_shnum; n++)
745 if (shdr[n].sh_type == SHT_REL)
746 e32_relocate(elf, n);
747 } else {
748 Elf64_Shdr *shdr = elf->shdr;
749
750 for (n = 0; n < elf->e_shnum; n++)
751 if (shdr[n].sh_type == SHT_RELA)
752 e64_relocate(elf, n);
753
754 }
755 }
756