xref: /optee_os/ldelf/ta_elf_rel.c (revision 68a8e5b5d5a5859bf8aa9440632f9d4eb242cf7d)
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 		Elf32_Addr end_offs = 0;
412 		size_t sym_idx = 0;
413 		vaddr_t val = 0;
414 
415 		/* Check the address is inside TA memory */
416 		if (ADD_OVERFLOW(rel->r_offset, sizeof(*where), &end_offs) ||
417 		    end_offs >= (elf->max_addr - elf->load_addr))
418 			err(TEE_ERROR_BAD_FORMAT,
419 			    "Relocation offset out of range");
420 		where = (Elf32_Addr *)(elf->load_addr + rel->r_offset);
421 
422 		switch (ELF32_R_TYPE(rel->r_info)) {
423 		case R_ARM_NONE:
424 			/*
425 			 * One would expect linker prevents such useless entry
426 			 * in the relocation table. We still handle this type
427 			 * here in case such entries exist.
428 			 */
429 			break;
430 		case R_ARM_ABS32:
431 			sym_idx = ELF32_R_SYM(rel->r_info);
432 			if (sym_idx >= num_syms)
433 				err(TEE_ERROR_BAD_FORMAT,
434 				    "Symbol index out of range");
435 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
436 				/* Symbol is external */
437 				e32_process_dyn_rel(sym_tab, num_syms, str_tab,
438 						    str_tab_size, rel, where);
439 			} else {
440 				*where += elf->load_addr +
441 					  sym_tab[sym_idx].st_value;
442 			}
443 			break;
444 		case R_ARM_REL32:
445 			sym_idx = ELF32_R_SYM(rel->r_info);
446 			if (sym_idx >= num_syms)
447 				err(TEE_ERROR_BAD_FORMAT,
448 				    "Symbol index out of range");
449 			*where += sym_tab[sym_idx].st_value - rel->r_offset;
450 			break;
451 		case R_ARM_RELATIVE:
452 			*where += elf->load_addr;
453 			break;
454 		case R_ARM_GLOB_DAT:
455 		case R_ARM_JUMP_SLOT:
456 			if (!sym_tab)
457 				err(TEE_ERROR_BAD_FORMAT,
458 				    "Missing symbol table");
459 			e32_process_dyn_rel(sym_tab, num_syms, str_tab,
460 					    str_tab_size, rel, where);
461 			break;
462 		case R_ARM_TLS_DTPMOD32:
463 			if (!sym_tab)
464 				err(TEE_ERROR_BAD_FORMAT,
465 				    "Missing symbol table");
466 			mod = elf;
467 			e32_tls_get_module(sym_tab, num_syms, str_tab,
468 					   str_tab_size, rel, &mod);
469 			*where = mod->tls_mod_id;
470 			break;
471 		case R_ARM_TLS_DTPOFF32:
472 			if (!sym_tab)
473 				err(TEE_ERROR_BAD_FORMAT,
474 				    "Missing symbol table");
475 			e32_tls_resolve(sym_tab, num_syms, str_tab,
476 					str_tab_size, rel, &val);
477 			*where = val;
478 			break;
479 		default:
480 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d",
481 			     ELF32_R_TYPE(rel->r_info));
482 		}
483 	}
484 }
485 
486 #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)487 static void e64_get_sym_name(const Elf64_Sym *sym_tab, size_t num_syms,
488 			     const char *str_tab, size_t str_tab_size,
489 			     Elf64_Rela *rela, const char **name,
490 			     bool *weak_undef)
491 {
492 	size_t sym_idx = 0;
493 	size_t name_idx = 0;
494 
495 	sym_idx = ELF64_R_SYM(rela->r_info);
496 	if (sym_idx >= num_syms)
497 		err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range");
498 	sym_idx = confine_array_index(sym_idx, num_syms);
499 
500 	name_idx = sym_tab[sym_idx].st_name;
501 	if (name_idx >= str_tab_size)
502 		err(TEE_ERROR_BAD_FORMAT, "Name index out of range");
503 	*name = str_tab + name_idx;
504 
505 	if (sym_tab[sym_idx].st_shndx == SHN_UNDEF &&
506 	    ELF64_ST_BIND(sym_tab[sym_idx].st_info) == STB_WEAK)
507 		*weak_undef = true;
508 	else
509 		*weak_undef = false;
510 }
511 
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)512 static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms,
513 				 const char *str_tab, size_t str_tab_size,
514 				 Elf64_Rela *rela, Elf64_Addr *where)
515 {
516 	const char *name = NULL;
517 	uintptr_t val = 0;
518 	bool weak_undef = false;
519 
520 	e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela, &name,
521 			 &weak_undef);
522 	resolve_sym(name, &val, NULL, !weak_undef);
523 	*where = val;
524 }
525 
526 #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)527 static void e64_process_tls_tprel_rela(const Elf64_Sym *sym_tab,
528 				       size_t num_syms, const char *str_tab,
529 				       size_t str_tab_size, Elf64_Rela *rela,
530 				       Elf64_Addr *where, struct ta_elf *elf)
531 {
532 	struct ta_elf *mod = NULL;
533 	bool weak_undef = false;
534 	const char *name = NULL;
535 	size_t sym_idx = 0;
536 	vaddr_t symval = 0;
537 
538 	sym_idx = ELF64_R_SYM(rela->r_info);
539 	if (sym_idx) {
540 		e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela,
541 				 &name, &weak_undef);
542 		resolve_sym(name, &symval, &mod, !weak_undef);
543 	} else {
544 		mod = elf;
545 	}
546 	*where = symval + mod->tls_tcb_offs + rela->r_addend;
547 }
548 
549 struct tlsdesc {
550 	long (*resolver)(struct tlsdesc *td);
551 	long value;
552 };
553 
554 /* Helper function written in assembly due to the calling convention */
555 long tlsdesc_resolve(struct tlsdesc *td);
556 
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)557 static void e64_process_tlsdesc_rela(const Elf64_Sym *sym_tab, size_t num_syms,
558 				     const char *str_tab, size_t str_tab_size,
559 				     Elf64_Rela *rela, Elf64_Addr *where,
560 				     struct ta_elf *elf)
561 {
562 	/*
563 	 * @where points to a pair of 64-bit words in the GOT or PLT which is
564 	 * mapped to a struct tlsdesc:
565 	 *
566 	 * - resolver() must return the offset of the thread-local variable
567 	 *   relative to TPIDR_EL0.
568 	 * - value is implementation-dependent. The TLS_TPREL handling code is
569 	 *   re-used to get the desired offset so that tlsdesc_resolve() just
570 	 *   needs to return this value.
571 	 *
572 	 * Both the TA and ldelf are AArch64 so it is OK to point to a function
573 	 * in ldelf.
574 	 */
575 	*where = (Elf64_Addr)tlsdesc_resolve;
576 	e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab, str_tab_size,
577 				   rela, where + 1, elf);
578 }
579 #endif /*ARM64*/
580 
e64_relocate(struct ta_elf * elf,unsigned int rel_sidx)581 static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx)
582 {
583 	Elf64_Shdr *shdr = elf->shdr;
584 	Elf64_Rela *rela = NULL;
585 	Elf64_Rela *rela_end = NULL;
586 	size_t sym_tab_idx = 0;
587 	Elf64_Sym *sym_tab = NULL;
588 	size_t num_syms = 0;
589 	size_t sh_end = 0;
590 	const char *str_tab = NULL;
591 	size_t str_tab_size = 0;
592 
593 	assert(shdr[rel_sidx].sh_type == SHT_RELA);
594 
595 	assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela));
596 
597 	sym_tab_idx = shdr[rel_sidx].sh_link;
598 	if (sym_tab_idx) {
599 		size_t str_tab_idx = 0;
600 
601 		if (sym_tab_idx >= elf->e_shnum)
602 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range");
603 		sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum);
604 
605 		assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym));
606 
607 		/* Check the address is inside TA memory */
608 		if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
609 				 shdr[sym_tab_idx].sh_size, &sh_end))
610 			err(TEE_ERROR_BAD_FORMAT, "Overflow");
611 		if (sh_end >= (elf->max_addr - elf->load_addr))
612 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range");
613 
614 		sym_tab = (Elf64_Sym *)(elf->load_addr +
615 					shdr[sym_tab_idx].sh_addr);
616 
617 		num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym);
618 
619 		str_tab_idx = shdr[sym_tab_idx].sh_link;
620 		if (str_tab_idx) {
621 			if (str_tab_idx >= elf->e_shnum)
622 				err(TEE_ERROR_BAD_FORMAT,
623 				    "STRTAB index out of range");
624 			str_tab_idx = confine_array_index(str_tab_idx,
625 							  elf->e_shnum);
626 
627 			/* Check the address is inside ELF memory */
628 			if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
629 					 shdr[str_tab_idx].sh_size, &sh_end))
630 				err(TEE_ERROR_BAD_FORMAT, "Overflow");
631 			if (sh_end >= (elf->max_addr - elf->load_addr))
632 				err(TEE_ERROR_BAD_FORMAT,
633 				    "STRTAB out of range");
634 
635 			str_tab = (const char *)(elf->load_addr +
636 						 shdr[str_tab_idx].sh_addr);
637 			str_tab_size = shdr[str_tab_idx].sh_size;
638 		}
639 	}
640 
641 	/* Check the address is inside TA memory */
642 	if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr,
643 			 shdr[rel_sidx].sh_size, &sh_end))
644 		err(TEE_ERROR_BAD_FORMAT, "Overflow");
645 	if (sh_end >= (elf->max_addr - elf->load_addr))
646 		err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range");
647 	rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr);
648 
649 	rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela);
650 	for (; rela < rela_end; rela++) {
651 		Elf64_Addr *where = NULL;
652 		size_t write_size = sizeof(*where);
653 		size_t sym_idx __maybe_unused = 0;
654 		Elf64_Addr end_offs = 0;
655 
656 		if (ELF64_R_TYPE(rela->r_info) == R_AARCH64_TLSDESC)
657 			write_size *= 2;
658 
659 		/* Check the address is inside TA memory */
660 		if (ADD_OVERFLOW(rela->r_offset, write_size, &end_offs) ||
661 		    end_offs >= (elf->max_addr - elf->load_addr))
662 			err(TEE_ERROR_BAD_FORMAT,
663 			    "Relocation offset out of range");
664 
665 		where = (Elf64_Addr *)(elf->load_addr + rela->r_offset);
666 
667 		switch (ELF64_R_TYPE(rela->r_info)) {
668 #ifdef ARM64
669 		case R_AARCH64_NONE:
670 			/*
671 			 * One would expect linker prevents such useless entry
672 			 * in the relocation table. We still handle this type
673 			 * here in case such entries exist.
674 			 */
675 			break;
676 		case R_AARCH64_ABS64:
677 			sym_idx = ELF64_R_SYM(rela->r_info);
678 			if (sym_idx >= num_syms)
679 				err(TEE_ERROR_BAD_FORMAT,
680 				    "Symbol index out of range");
681 			sym_idx = confine_array_index(sym_idx, num_syms);
682 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
683 				/* Symbol is external */
684 				e64_process_dyn_rela(sym_tab, num_syms, str_tab,
685 						     str_tab_size, rela, where);
686 			} else {
687 				*where = rela->r_addend + elf->load_addr +
688 					 sym_tab[sym_idx].st_value;
689 			}
690 			break;
691 		case R_AARCH64_RELATIVE:
692 			*where = rela->r_addend + elf->load_addr;
693 			break;
694 		case R_AARCH64_GLOB_DAT:
695 		case R_AARCH64_JUMP_SLOT:
696 			e64_process_dyn_rela(sym_tab, num_syms, str_tab,
697 					     str_tab_size, rela, where);
698 			break;
699 		case R_AARCH64_TLS_TPREL:
700 			e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab,
701 						   str_tab_size, rela, where,
702 						   elf);
703 			break;
704 		case R_AARCH64_TLSDESC:
705 			e64_process_tlsdesc_rela(sym_tab, num_syms, str_tab,
706 						 str_tab_size, rela, where,
707 						 elf);
708 			break;
709 #endif /*ARM64*/
710 #ifdef RV64
711 		case R_RISCV_NONE:
712 			/*
713 			 * One would expect linker prevents such useless entry
714 			 * in the relocation table. We still handle this type
715 			 * here in case such entries exist.
716 			 */
717 			break;
718 		case R_RISCV_RELATIVE:
719 			*where = rela->r_addend + elf->load_addr;
720 			break;
721 		case R_RISCV_64:
722 			e64_process_dyn_rela(sym_tab, num_syms, str_tab,
723 					     str_tab_size, rela, where);
724 			*where += rela->r_addend;
725 			break;
726 		case R_RISCV_JUMP_SLOT:
727 			e64_process_dyn_rela(sym_tab, num_syms, str_tab,
728 					     str_tab_size, rela, where);
729 			break;
730 #endif /*RV64*/
731 		default:
732 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd",
733 			     ELF64_R_TYPE(rela->r_info));
734 		}
735 	}
736 }
737 #else /*ARM64 || RV64*/
e64_relocate(struct ta_elf * elf __unused,unsigned int rel_sidx __unused)738 static void __noreturn e64_relocate(struct ta_elf *elf __unused,
739 				    unsigned int rel_sidx __unused)
740 {
741 	err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported");
742 }
743 #endif /*ARM64 || RV64*/
744 
ta_elf_relocate(struct ta_elf * elf)745 void ta_elf_relocate(struct ta_elf *elf)
746 {
747 	size_t n = 0;
748 
749 	if (elf->is_32bit) {
750 		Elf32_Shdr *shdr = elf->shdr;
751 
752 		for (n = 0; n < elf->e_shnum; n++)
753 			if (shdr[n].sh_type == SHT_REL)
754 				e32_relocate(elf, n);
755 	} else {
756 		Elf64_Shdr *shdr = elf->shdr;
757 
758 		for (n = 0; n < elf->e_shnum; n++)
759 			if (shdr[n].sh_type == SHT_RELA)
760 				e64_relocate(elf, n);
761 
762 	}
763 }
764