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