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