1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <elf32.h> 8 #include <elf64.h> 9 #include <elf_common.h> 10 #include <string.h> 11 #include <tee_api_types.h> 12 #include <util.h> 13 14 #include "sys.h" 15 #include "ta_elf.h" 16 17 static bool __resolve_sym(struct ta_elf *elf, unsigned int bind, 18 size_t st_shndx, size_t st_name, size_t st_value, 19 const char *name, vaddr_t *val) 20 { 21 if (bind != STB_GLOBAL) 22 return false; 23 if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX) 24 return false; 25 if (!st_name) 26 return false; 27 if (st_name > elf->dynstr_size) 28 err(TEE_ERROR_BAD_FORMAT, "Symbol out of range"); 29 30 if (strcmp(name, elf->dynstr + st_name)) 31 return false; 32 33 *val = st_value + elf->load_addr; 34 return true; 35 } 36 37 static void resolve_sym(const char *name, vaddr_t *val) 38 { 39 struct ta_elf *elf = NULL; 40 size_t n = 0; 41 42 TAILQ_FOREACH(elf, &main_elf_queue, link) { 43 if (elf->is_32bit) { 44 Elf32_Sym *sym = elf->dynsymtab; 45 46 for (n = 0; n < elf->num_dynsyms; n++) { 47 if (__resolve_sym(elf, 48 ELF32_ST_BIND(sym[n].st_info), 49 sym[n].st_shndx, 50 sym[n].st_name, 51 sym[n].st_value, name, val)) 52 return; 53 } 54 } else { 55 Elf64_Sym *sym = elf->dynsymtab; 56 57 for (n = 0; n < elf->num_dynsyms; n++) { 58 if (__resolve_sym(elf, 59 ELF64_ST_BIND(sym[n].st_info), 60 sym[n].st_shndx, 61 sym[n].st_name, 62 sym[n].st_value, name, val)) 63 return; 64 } 65 } 66 } 67 err(TEE_ERROR_ITEM_NOT_FOUND, "Symbol %s not found", name); 68 } 69 70 static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms, 71 const char *str_tab, size_t str_tab_size, 72 Elf32_Rel *rel, Elf32_Addr *where) 73 { 74 size_t sym_idx = 0; 75 const char *name = NULL; 76 vaddr_t val = 0; 77 size_t name_idx = 0; 78 79 sym_idx = ELF32_R_SYM(rel->r_info); 80 assert(sym_idx < num_syms); 81 82 name_idx = sym_tab[sym_idx].st_name; 83 assert(name_idx < str_tab_size); 84 name = str_tab + name_idx; 85 86 resolve_sym(name, &val); 87 *where = val; 88 } 89 90 static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx) 91 { 92 Elf32_Shdr *shdr = elf->shdr; 93 Elf32_Rel *rel = NULL; 94 Elf32_Rel *rel_end = NULL; 95 size_t sym_tab_idx = 0; 96 Elf32_Sym *sym_tab = NULL; 97 size_t num_syms = 0; 98 size_t sh_end = 0; 99 const char *str_tab = NULL; 100 size_t str_tab_size = 0; 101 102 assert(shdr[rel_sidx].sh_type == SHT_REL); 103 104 assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel)); 105 106 sym_tab_idx = shdr[rel_sidx].sh_link; 107 if (sym_tab_idx) { 108 size_t str_tab_idx = 0; 109 110 assert(sym_tab_idx < elf->e_shnum); 111 112 assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym)); 113 114 /* Check the address is inside ELF memory */ 115 if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, 116 shdr[sym_tab_idx].sh_size, &sh_end)) 117 err(TEE_ERROR_SECURITY, "Overflow"); 118 assert(sh_end < (elf->max_addr - elf->load_addr)); 119 120 sym_tab = (Elf32_Sym *)(elf->load_addr + 121 shdr[sym_tab_idx].sh_addr); 122 123 num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym); 124 125 str_tab_idx = shdr[sym_tab_idx].sh_link; 126 if (str_tab_idx) { 127 /* Check the address is inside ELF memory */ 128 if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, 129 shdr[str_tab_idx].sh_size, &sh_end)) 130 err(TEE_ERROR_SECURITY, "Overflow"); 131 assert(sh_end < (elf->max_addr - elf->load_addr)); 132 133 str_tab = (const char *)(elf->load_addr + 134 shdr[str_tab_idx].sh_addr); 135 str_tab_size = shdr[str_tab_idx].sh_size; 136 } 137 } 138 139 /* Check the address is inside TA memory */ 140 assert(shdr[rel_sidx].sh_addr < (elf->max_addr - elf->load_addr)); 141 rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr); 142 143 /* Check the address is inside TA memory */ 144 if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, shdr[rel_sidx].sh_size, 145 &sh_end)) 146 err(TEE_ERROR_SECURITY, "Overflow"); 147 assert(sh_end < (elf->max_addr - elf->load_addr)); 148 rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel); 149 for (; rel < rel_end; rel++) { 150 Elf32_Addr *where = NULL; 151 size_t sym_idx = 0; 152 153 /* Check the address is inside TA memory */ 154 assert(rel->r_offset < (elf->max_addr - elf->load_addr)); 155 where = (Elf32_Addr *)(elf->load_addr + rel->r_offset); 156 157 switch (ELF32_R_TYPE(rel->r_info)) { 158 case R_ARM_ABS32: 159 sym_idx = ELF32_R_SYM(rel->r_info); 160 assert(sym_idx < num_syms); 161 if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { 162 /* Symbol is external */ 163 e32_process_dyn_rel(sym_tab, num_syms, str_tab, 164 str_tab_size, rel, where); 165 } else { 166 *where += elf->load_addr + 167 sym_tab[sym_idx].st_value; 168 } 169 break; 170 case R_ARM_REL32: 171 sym_idx = ELF32_R_SYM(rel->r_info); 172 assert(sym_idx < num_syms); 173 *where += sym_tab[sym_idx].st_value - rel->r_offset; 174 break; 175 case R_ARM_RELATIVE: 176 *where += elf->load_addr; 177 break; 178 case R_ARM_GLOB_DAT: 179 case R_ARM_JUMP_SLOT: 180 e32_process_dyn_rel(sym_tab, num_syms, str_tab, 181 str_tab_size, rel, where); 182 break; 183 default: 184 err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d", 185 ELF32_R_TYPE(rel->r_info)); 186 } 187 } 188 } 189 190 #ifdef ARM64 191 static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms, 192 const char *str_tab, size_t str_tab_size, 193 Elf64_Rela *rela, Elf64_Addr *where) 194 { 195 size_t sym_idx = 0; 196 const char *name = NULL; 197 uintptr_t val = 0; 198 size_t name_idx = 0; 199 200 sym_idx = ELF64_R_SYM(rela->r_info); 201 assert(sym_idx < num_syms); 202 203 name_idx = sym_tab[sym_idx].st_name; 204 assert(name_idx < str_tab_size); 205 name = str_tab + name_idx; 206 207 resolve_sym(name, &val); 208 *where = val; 209 } 210 211 static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx) 212 { 213 Elf64_Shdr *shdr = elf->shdr; 214 Elf64_Rela *rela = NULL; 215 Elf64_Rela *rela_end = NULL; 216 size_t sym_tab_idx = 0; 217 Elf64_Sym *sym_tab = NULL; 218 size_t num_syms = 0; 219 size_t sh_end = 0; 220 const char *str_tab = NULL; 221 size_t str_tab_size = 0; 222 223 assert(shdr[rel_sidx].sh_type == SHT_RELA); 224 225 assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela)); 226 227 sym_tab_idx = shdr[rel_sidx].sh_link; 228 if (sym_tab_idx) { 229 size_t str_tab_idx = 0; 230 231 assert(sym_tab_idx < elf->e_shnum); 232 233 assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym)); 234 235 /* Check the address is inside TA memory */ 236 if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, 237 shdr[sym_tab_idx].sh_size, &sh_end)) 238 err(TEE_ERROR_SECURITY, "Overflow"); 239 assert(sh_end < (elf->max_addr - elf->load_addr)); 240 241 sym_tab = (Elf64_Sym *)(elf->load_addr + 242 shdr[sym_tab_idx].sh_addr); 243 244 num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym); 245 246 str_tab_idx = shdr[sym_tab_idx].sh_link; 247 if (str_tab_idx) { 248 /* Check the address is inside ELF memory */ 249 if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, 250 shdr[str_tab_idx].sh_size, &sh_end)) 251 err(TEE_ERROR_SECURITY, "Overflow"); 252 assert(sh_end < (elf->max_addr - elf->load_addr)); 253 254 str_tab = (const char *)(elf->load_addr + 255 shdr[str_tab_idx].sh_addr); 256 str_tab_size = shdr[str_tab_idx].sh_size; 257 } 258 } 259 260 /* Check the address is inside TA memory */ 261 assert(shdr[rel_sidx].sh_addr < (elf->max_addr - elf->load_addr)); 262 rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr); 263 264 /* Check the address is inside TA memory */ 265 if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, shdr[rel_sidx].sh_size, 266 &sh_end)) 267 err(TEE_ERROR_SECURITY, "Overflow"); 268 assert(sh_end < (elf->max_addr - elf->load_addr)); 269 rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela); 270 for (; rela < rela_end; rela++) { 271 Elf64_Addr *where = NULL; 272 size_t sym_idx = 0; 273 274 /* Check the address is inside TA memory */ 275 assert(rela->r_offset < (elf->max_addr - elf->load_addr)); 276 277 where = (Elf64_Addr *)(elf->load_addr + rela->r_offset); 278 279 switch (ELF64_R_TYPE(rela->r_info)) { 280 case R_AARCH64_ABS64: 281 sym_idx = ELF64_R_SYM(rela->r_info); 282 assert(sym_idx < num_syms); 283 if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { 284 /* Symbol is external */ 285 e64_process_dyn_rela(sym_tab, num_syms, str_tab, 286 str_tab_size, rela, where); 287 } else { 288 *where = rela->r_addend + elf->load_addr + 289 sym_tab[sym_idx].st_value; 290 } 291 break; 292 case R_AARCH64_RELATIVE: 293 *where = rela->r_addend + elf->load_addr; 294 break; 295 case R_AARCH64_GLOB_DAT: 296 case R_AARCH64_JUMP_SLOT: 297 e64_process_dyn_rela(sym_tab, num_syms, str_tab, 298 str_tab_size, rela, where); 299 break; 300 default: 301 err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd", 302 ELF64_R_TYPE(rela->r_info)); 303 } 304 } 305 } 306 #else /*ARM64*/ 307 static void e64_relocate(struct ta_elf *elf __unused, 308 unsigned int rel_sidx __unused) 309 { 310 err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported"); 311 } 312 #endif /*ARM64*/ 313 314 void ta_elf_relocate(struct ta_elf *elf) 315 { 316 size_t n = 0; 317 318 if (elf->is_32bit) { 319 Elf32_Shdr *shdr = elf->shdr; 320 321 for (n = 0; n < elf->e_shnum; n++) 322 if (shdr[n].sh_type == SHT_REL) 323 e32_relocate(elf, n); 324 } else { 325 Elf64_Shdr *shdr = elf->shdr; 326 327 for (n = 0; n < elf->e_shnum; n++) 328 if (shdr[n].sh_type == SHT_RELA) 329 e64_relocate(elf, n); 330 331 } 332 } 333