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