xref: /optee_os/ldelf/ta_elf_rel.c (revision cf830b2b674ccc672d0124425714da7cae27c303)
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 
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 
35 static bool __resolve_sym(struct ta_elf *elf, unsigned int st_bind,
36 			  unsigned int st_type, size_t st_shndx,
37 			  size_t st_name, size_t st_value, const char *name,
38 			  vaddr_t *val, bool weak_ok)
39 {
40 	bool bind_ok = false;
41 
42 	if (!st_name)
43 		return false;
44 	if (st_name > elf->dynstr_size)
45 		err(TEE_ERROR_BAD_FORMAT, "Symbol name out of range");
46 	if (strcmp(name, elf->dynstr + st_name))
47 		return false;
48 	if (st_bind == STB_GLOBAL || (weak_ok && st_bind == STB_WEAK))
49 		bind_ok = true;
50 	if (!bind_ok)
51 		return false;
52 	if (st_bind == STB_WEAK && st_shndx == SHN_UNDEF) {
53 		if (val)
54 			*val = 0;
55 		return true;
56 	}
57 	if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX)
58 		return false;
59 
60 	if (st_value > (elf->max_addr - elf->load_addr))
61 		err(TEE_ERROR_BAD_FORMAT, "Symbol location out of range");
62 
63 	switch (st_type) {
64 	case STT_NOTYPE:
65 	case STT_OBJECT:
66 	case STT_FUNC:
67 		*val = st_value + elf->load_addr;
68 		break;
69 	default:
70 		err(TEE_ERROR_NOT_SUPPORTED, "Symbol type not supported");
71 	}
72 
73 	return true;
74 }
75 
76 static TEE_Result resolve_sym_helper(uint32_t hash, const char *name,
77 				     vaddr_t *val, struct ta_elf *elf,
78 				     bool weak_ok)
79 {
80 	/*
81 	 * Using uint32_t here for convenience because both Elf64_Word
82 	 * and Elf32_Word are 32-bit types
83 	 */
84 	uint32_t *hashtab = elf->hashtab;
85 	uint32_t nbuckets = hashtab[0];
86 	uint32_t nchains = hashtab[1];
87 	uint32_t *bucket = &hashtab[2];
88 	uint32_t *chain = &bucket[nbuckets];
89 	size_t n = 0;
90 
91 	if (elf->is_32bit) {
92 		Elf32_Sym *sym = elf->dynsymtab;
93 
94 		for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
95 			if (n >= nchains || n >= elf->num_dynsyms)
96 				err(TEE_ERROR_BAD_FORMAT,
97 				    "Index out of range");
98 			/*
99 			 * We're loading values from sym[] which later
100 			 * will be used to load something.
101 			 * => Spectre V1 pattern, need to cap the index
102 			 * against speculation.
103 			 */
104 			n = confine_array_index(n, elf->num_dynsyms);
105 			if (__resolve_sym(elf,
106 					  ELF32_ST_BIND(sym[n].st_info),
107 					  ELF32_ST_TYPE(sym[n].st_info),
108 					  sym[n].st_shndx,
109 					  sym[n].st_name,
110 					  sym[n].st_value, name, val, weak_ok))
111 				return TEE_SUCCESS;
112 		}
113 	} else {
114 		Elf64_Sym *sym = elf->dynsymtab;
115 
116 		for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
117 			if (n >= nchains || n >= elf->num_dynsyms)
118 				err(TEE_ERROR_BAD_FORMAT,
119 				    "Index out of range");
120 			/*
121 			 * We're loading values from sym[] which later
122 			 * will be used to load something.
123 			 * => Spectre V1 pattern, need to cap the index
124 			 * against speculation.
125 			 */
126 			n = confine_array_index(n, elf->num_dynsyms);
127 			if (__resolve_sym(elf,
128 					  ELF64_ST_BIND(sym[n].st_info),
129 					  ELF64_ST_TYPE(sym[n].st_info),
130 					  sym[n].st_shndx,
131 					  sym[n].st_name,
132 					  sym[n].st_value, name, val, weak_ok))
133 				return TEE_SUCCESS;
134 		}
135 	}
136 
137 	return TEE_ERROR_ITEM_NOT_FOUND;
138 }
139 
140 /*
141  * Look for named symbol in @elf, or all modules if @elf == NULL. Global symbols
142  * are searched first, then weak ones. Last option, when at least one weak but
143  * undefined symbol exists, resolve to zero. Otherwise return
144  * TEE_ERROR_ITEM_NOT_FOUND.
145  */
146 TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val,
147 			      struct ta_elf *elf)
148 {
149 	uint32_t hash = elf_hash(name);
150 
151 	if (elf) {
152 		/* Search global symbols */
153 		if (!resolve_sym_helper(hash, name, val, elf,
154 					false /* !weak_ok */))
155 			return TEE_SUCCESS;
156 		/* Search weak symbols */
157 		if (!resolve_sym_helper(hash, name, val, elf,
158 					true /* weak_ok */))
159 			return TEE_SUCCESS;
160 	}
161 
162 	TAILQ_FOREACH(elf, &main_elf_queue, link) {
163 		if (!resolve_sym_helper(hash, name, val, elf,
164 					false /* !weak_ok */))
165 			return TEE_SUCCESS;
166 		if (!resolve_sym_helper(hash, name, val, elf,
167 					true /* weak_ok */))
168 			return TEE_SUCCESS;
169 	}
170 
171 	return TEE_ERROR_ITEM_NOT_FOUND;
172 }
173 
174 static void resolve_sym(const char *name, vaddr_t *val)
175 {
176 	TEE_Result res = ta_elf_resolve_sym(name, val, NULL);
177 
178 	if (res)
179 		err(res, "Symbol %s not found", name);
180 }
181 
182 static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms,
183 				const char *str_tab, size_t str_tab_size,
184 				Elf32_Rel *rel, Elf32_Addr *where)
185 {
186 	size_t sym_idx = 0;
187 	const char *name = NULL;
188 	vaddr_t val = 0;
189 	size_t name_idx = 0;
190 
191 	sym_idx = ELF32_R_SYM(rel->r_info);
192 	if (sym_idx >= num_syms)
193 		err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range");
194 	sym_idx = confine_array_index(sym_idx, num_syms);
195 
196 	name_idx = sym_tab[sym_idx].st_name;
197 	if (name_idx >= str_tab_size)
198 		err(TEE_ERROR_BAD_FORMAT, "Name index out of range");
199 	name = str_tab + name_idx;
200 
201 	resolve_sym(name, &val);
202 	*where = val;
203 }
204 
205 static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx)
206 {
207 	Elf32_Shdr *shdr = elf->shdr;
208 	Elf32_Rel *rel = NULL;
209 	Elf32_Rel *rel_end = NULL;
210 	size_t sym_tab_idx = 0;
211 	Elf32_Sym *sym_tab = NULL;
212 	size_t num_syms = 0;
213 	size_t sh_end = 0;
214 	const char *str_tab = NULL;
215 	size_t str_tab_size = 0;
216 
217 	assert(shdr[rel_sidx].sh_type == SHT_REL);
218 
219 	assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel));
220 
221 	sym_tab_idx = shdr[rel_sidx].sh_link;
222 	if (sym_tab_idx) {
223 		size_t str_tab_idx = 0;
224 
225 		if (sym_tab_idx >= elf->e_shnum)
226 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range");
227 		sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum);
228 
229 		assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym));
230 
231 		/* Check the address is inside ELF memory */
232 		if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
233 				 shdr[sym_tab_idx].sh_size, &sh_end))
234 			err(TEE_ERROR_BAD_FORMAT, "Overflow");
235 		if (sh_end >= (elf->max_addr - elf->load_addr))
236 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range");
237 
238 		sym_tab = (Elf32_Sym *)(elf->load_addr +
239 					shdr[sym_tab_idx].sh_addr);
240 
241 		num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym);
242 
243 		str_tab_idx = shdr[sym_tab_idx].sh_link;
244 		if (str_tab_idx) {
245 			if (str_tab_idx >= elf->e_shnum)
246 				err(TEE_ERROR_BAD_FORMAT,
247 				    "STRTAB index out of range");
248 			str_tab_idx = confine_array_index(str_tab_idx,
249 							  elf->e_shnum);
250 
251 			/* Check the address is inside ELF memory */
252 			if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
253 					 shdr[str_tab_idx].sh_size, &sh_end))
254 				err(TEE_ERROR_BAD_FORMAT, "Overflow");
255 			if (sh_end >= (elf->max_addr - elf->load_addr))
256 				err(TEE_ERROR_BAD_FORMAT,
257 				    "STRTAB out of range");
258 
259 			str_tab = (const char *)(elf->load_addr +
260 						 shdr[str_tab_idx].sh_addr);
261 			str_tab_size = shdr[str_tab_idx].sh_size;
262 		}
263 	}
264 
265 	/* Check the address is inside TA memory */
266 	if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr,
267 			 shdr[rel_sidx].sh_size, &sh_end))
268 		err(TEE_ERROR_BAD_FORMAT, "Overflow");
269 	if (sh_end >= (elf->max_addr - elf->load_addr))
270 		err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range");
271 	rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr);
272 
273 	rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel);
274 	for (; rel < rel_end; rel++) {
275 		Elf32_Addr *where = NULL;
276 		size_t sym_idx = 0;
277 
278 		/* Check the address is inside TA memory */
279 		if (rel->r_offset >= (elf->max_addr - elf->load_addr))
280 			err(TEE_ERROR_BAD_FORMAT,
281 			    "Relocation offset out of range");
282 		where = (Elf32_Addr *)(elf->load_addr + rel->r_offset);
283 
284 		switch (ELF32_R_TYPE(rel->r_info)) {
285 		case R_ARM_ABS32:
286 			sym_idx = ELF32_R_SYM(rel->r_info);
287 			if (sym_idx >= num_syms)
288 				err(TEE_ERROR_BAD_FORMAT,
289 				    "Symbol index out of range");
290 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
291 				/* Symbol is external */
292 				e32_process_dyn_rel(sym_tab, num_syms, str_tab,
293 						    str_tab_size, rel, where);
294 			} else {
295 				*where += elf->load_addr +
296 					  sym_tab[sym_idx].st_value;
297 			}
298 			break;
299 		case R_ARM_REL32:
300 			sym_idx = ELF32_R_SYM(rel->r_info);
301 			if (sym_idx >= num_syms)
302 				err(TEE_ERROR_BAD_FORMAT,
303 				    "Symbol index out of range");
304 			*where += sym_tab[sym_idx].st_value - rel->r_offset;
305 			break;
306 		case R_ARM_RELATIVE:
307 			*where += elf->load_addr;
308 			break;
309 		case R_ARM_GLOB_DAT:
310 		case R_ARM_JUMP_SLOT:
311 			e32_process_dyn_rel(sym_tab, num_syms, str_tab,
312 					    str_tab_size, rel, where);
313 			break;
314 		default:
315 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d",
316 			     ELF32_R_TYPE(rel->r_info));
317 		}
318 	}
319 }
320 
321 #ifdef ARM64
322 static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms,
323 				 const char *str_tab, size_t str_tab_size,
324 				 Elf64_Rela *rela, Elf64_Addr *where)
325 {
326 	size_t sym_idx = 0;
327 	const char *name = NULL;
328 	uintptr_t val = 0;
329 	size_t name_idx = 0;
330 
331 	sym_idx = ELF64_R_SYM(rela->r_info);
332 	if (sym_idx >= num_syms)
333 		err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range");
334 	sym_idx = confine_array_index(sym_idx, num_syms);
335 
336 	name_idx = sym_tab[sym_idx].st_name;
337 	if (name_idx >= str_tab_size)
338 		err(TEE_ERROR_BAD_FORMAT, "Name index out of range");
339 	name = str_tab + name_idx;
340 
341 	resolve_sym(name, &val);
342 	*where = val;
343 }
344 
345 static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx)
346 {
347 	Elf64_Shdr *shdr = elf->shdr;
348 	Elf64_Rela *rela = NULL;
349 	Elf64_Rela *rela_end = NULL;
350 	size_t sym_tab_idx = 0;
351 	Elf64_Sym *sym_tab = NULL;
352 	size_t num_syms = 0;
353 	size_t sh_end = 0;
354 	const char *str_tab = NULL;
355 	size_t str_tab_size = 0;
356 
357 	assert(shdr[rel_sidx].sh_type == SHT_RELA);
358 
359 	assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela));
360 
361 	sym_tab_idx = shdr[rel_sidx].sh_link;
362 	if (sym_tab_idx) {
363 		size_t str_tab_idx = 0;
364 
365 		if (sym_tab_idx >= elf->e_shnum)
366 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range");
367 		sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum);
368 
369 		assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym));
370 
371 		/* Check the address is inside TA memory */
372 		if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr,
373 				 shdr[sym_tab_idx].sh_size, &sh_end))
374 			err(TEE_ERROR_BAD_FORMAT, "Overflow");
375 		if (sh_end >= (elf->max_addr - elf->load_addr))
376 			err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range");
377 
378 		sym_tab = (Elf64_Sym *)(elf->load_addr +
379 					shdr[sym_tab_idx].sh_addr);
380 
381 		num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym);
382 
383 		str_tab_idx = shdr[sym_tab_idx].sh_link;
384 		if (str_tab_idx) {
385 			if (str_tab_idx >= elf->e_shnum)
386 				err(TEE_ERROR_BAD_FORMAT,
387 				    "STRTAB index out of range");
388 			str_tab_idx = confine_array_index(str_tab_idx,
389 							  elf->e_shnum);
390 
391 			/* Check the address is inside ELF memory */
392 			if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr,
393 					 shdr[str_tab_idx].sh_size, &sh_end))
394 				err(TEE_ERROR_BAD_FORMAT, "Overflow");
395 			if (sh_end >= (elf->max_addr - elf->load_addr))
396 				err(TEE_ERROR_BAD_FORMAT,
397 				    "STRTAB out of range");
398 
399 			str_tab = (const char *)(elf->load_addr +
400 						 shdr[str_tab_idx].sh_addr);
401 			str_tab_size = shdr[str_tab_idx].sh_size;
402 		}
403 	}
404 
405 	/* Check the address is inside TA memory */
406 	if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr,
407 			 shdr[rel_sidx].sh_size, &sh_end))
408 		err(TEE_ERROR_BAD_FORMAT, "Overflow");
409 	if (sh_end >= (elf->max_addr - elf->load_addr))
410 		err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range");
411 	rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr);
412 
413 	rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela);
414 	for (; rela < rela_end; rela++) {
415 		Elf64_Addr *where = NULL;
416 		size_t sym_idx = 0;
417 
418 		/* Check the address is inside TA memory */
419 		if (rela->r_offset >= (elf->max_addr - elf->load_addr))
420 			err(TEE_ERROR_BAD_FORMAT,
421 			    "Relocation offset out of range");
422 
423 		where = (Elf64_Addr *)(elf->load_addr + rela->r_offset);
424 
425 		switch (ELF64_R_TYPE(rela->r_info)) {
426 		case R_AARCH64_ABS64:
427 			sym_idx = ELF64_R_SYM(rela->r_info);
428 			if (sym_idx >= num_syms)
429 				err(TEE_ERROR_BAD_FORMAT,
430 				    "Symbol index out of range");
431 			sym_idx = confine_array_index(sym_idx, num_syms);
432 			if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
433 				/* Symbol is external */
434 				e64_process_dyn_rela(sym_tab, num_syms, str_tab,
435 						     str_tab_size, rela, where);
436 			} else {
437 				*where = rela->r_addend + elf->load_addr +
438 					 sym_tab[sym_idx].st_value;
439 			}
440 			break;
441 		case R_AARCH64_RELATIVE:
442 			*where = rela->r_addend + elf->load_addr;
443 			break;
444 		case R_AARCH64_GLOB_DAT:
445 		case R_AARCH64_JUMP_SLOT:
446 			e64_process_dyn_rela(sym_tab, num_syms, str_tab,
447 					     str_tab_size, rela, where);
448 			break;
449 		default:
450 			err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd",
451 			     ELF64_R_TYPE(rela->r_info));
452 		}
453 	}
454 }
455 #else /*ARM64*/
456 static void __noreturn e64_relocate(struct ta_elf *elf __unused,
457 				    unsigned int rel_sidx __unused)
458 {
459 	err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported");
460 }
461 #endif /*ARM64*/
462 
463 void ta_elf_relocate(struct ta_elf *elf)
464 {
465 	size_t n = 0;
466 
467 	if (elf->is_32bit) {
468 		Elf32_Shdr *shdr = elf->shdr;
469 
470 		for (n = 0; n < elf->e_shnum; n++)
471 			if (shdr[n].sh_type == SHT_REL)
472 				e32_relocate(elf, n);
473 	} else {
474 		Elf64_Shdr *shdr = elf->shdr;
475 
476 		for (n = 0; n < elf->e_shnum; n++)
477 			if (shdr[n].sh_type == SHT_RELA)
478 				e64_relocate(elf, n);
479 
480 	}
481 }
482