1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019, Linaro Limited 4 * Copyright (c) 2022-2023, Arm Limited 5 */ 6 7 #include <assert.h> 8 #include <config.h> 9 #include <ldelf.h> 10 #include <malloc.h> 11 #include <printk.h> 12 #include <string.h> 13 #include <sys/queue.h> 14 #include <tee_api_types.h> 15 #include <trace.h> 16 #include <types_ext.h> 17 #include <util.h> 18 19 #include "asan.h" 20 #include "dl.h" 21 #include "ftrace.h" 22 #include "sys.h" 23 #include "ta_elf.h" 24 25 static size_t mpool_size = 4 * SMALL_PAGE_SIZE; 26 static vaddr_t mpool_base; 27 28 static void __printf(2, 0) print_to_console(void *pctx __unused, 29 const char *fmt, va_list ap) 30 { 31 trace_vprintf(NULL, 0, TRACE_ERROR, true, fmt, ap); 32 } 33 34 static void __noreturn __maybe_unused dump_ta_state(struct dump_entry_arg *arg) 35 { 36 struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue); 37 38 assert(elf && elf->is_main); 39 EMSG_RAW("Status of TA %pUl", (void *)&elf->uuid); 40 #if defined(ARM32) || defined(ARM64) 41 EMSG_RAW(" arch: %s", elf->is_32bit ? "arm" : "aarch64"); 42 #elif defined(RV32) || defined(RV64) 43 EMSG_RAW(" arch: %s", elf->is_32bit ? "riscv32" : "riscv64"); 44 #endif 45 46 ta_elf_print_mappings(NULL, print_to_console, &main_elf_queue, 47 arg->num_maps, arg->maps, mpool_base); 48 49 #if defined(ARM32) || defined(ARM64) 50 if (arg->is_32bit) 51 ta_elf_stack_trace_a32(arg->arm32.regs); 52 else 53 ta_elf_stack_trace_a64(arg->arm64.fp, arg->arm64.sp, 54 arg->arm64.pc); 55 #elif defined(RV32) || defined(RV64) 56 ta_elf_stack_trace_riscv(arg->rv.fp, arg->rv.pc); 57 #endif 58 59 sys_return_cleanup(); 60 } 61 62 #ifdef CFG_FTRACE_SUPPORT 63 struct print_buf_ctx { 64 char *buf; 65 size_t blen; 66 size_t ret; 67 }; 68 69 static void __printf(2, 0) print_to_pbuf(void *pctx, const char *fmt, 70 va_list ap) 71 { 72 struct print_buf_ctx *pbuf = pctx; 73 char *buf = NULL; 74 size_t blen = 0; 75 int ret = 0; 76 77 if (pbuf->buf && pbuf->blen > pbuf->ret) { 78 buf = pbuf->buf + pbuf->ret; 79 blen = pbuf->blen - pbuf->ret; 80 } 81 82 ret = vsnprintk(buf, blen, fmt, ap); 83 assert(ret >= 0); 84 85 pbuf->ret += ret; 86 } 87 88 static void copy_to_pbuf(void *pctx, void *b, size_t bl) 89 { 90 struct print_buf_ctx *pbuf = pctx; 91 char *buf = NULL; 92 size_t blen = 0; 93 94 if (pbuf->buf && pbuf->blen > pbuf->ret) { 95 buf = pbuf->buf + pbuf->ret; 96 blen = pbuf->blen - pbuf->ret; 97 memcpy(buf, b, MIN(blen, bl)); 98 } 99 100 pbuf->ret += bl; 101 102 } 103 104 static void __noreturn ftrace_dump(void *buf, size_t *blen) 105 { 106 struct print_buf_ctx pbuf = { .buf = buf, .blen = *blen }; 107 108 /* only print the header when this is a new dump */ 109 if (!ftrace_get_dump_id()) 110 ta_elf_print_mappings(&pbuf, print_to_pbuf, &main_elf_queue, 111 0, NULL, mpool_base); 112 ftrace_copy_buf(&pbuf, copy_to_pbuf); 113 /* 114 * Reset the buffer after dump if this is the actual write 115 * The OS may call this function with buf == NULL, 116 * in order to get the length required to write ftrace data. 117 */ 118 if (buf) 119 ftrace_reset_buf(); 120 *blen = pbuf.ret; 121 sys_return_cleanup(); 122 } 123 #endif 124 125 static void __noreturn dl_entry(struct dl_entry_arg *arg) 126 { 127 switch (arg->cmd) { 128 case LDELF_DL_ENTRY_DLOPEN: 129 arg->ret = dlopen_entry(arg); 130 break; 131 case LDELF_DL_ENTRY_DLSYM: 132 arg->ret = dlsym_entry(arg); 133 break; 134 default: 135 arg->ret = TEE_ERROR_NOT_SUPPORTED; 136 } 137 138 sys_return_cleanup(); 139 } 140 141 /* 142 * ldelf()- Loads ELF into memory 143 * @arg: Argument passing to/from TEE Core 144 * 145 * Only called from assembly 146 */ 147 void __noreturn __no_asan ldelf(struct ldelf_arg *arg); 148 void ldelf(struct ldelf_arg *arg) 149 { 150 TEE_Result res = TEE_SUCCESS; 151 struct ta_elf *elf = NULL; 152 153 res = asan_init_ldelf(); 154 if (res) { 155 EMSG("asan init result %"PRIx32, res); 156 panic(); 157 } 158 159 DMSG("Loading TS %pUl", (void *)&arg->uuid); 160 res = sys_map_zi(mpool_size, 0, &mpool_base, 0, 0); 161 if (res) { 162 EMSG("sys_map_zi(%zu): result %"PRIx32, mpool_size, res); 163 panic(); 164 } 165 malloc_add_pool((void *)mpool_base, mpool_size); 166 167 asan_start(); 168 169 /* Load the main binary and get a list of dependencies, if any. */ 170 ta_elf_load_main(&arg->uuid, &arg->is_32bit, &arg->stack_ptr, 171 &arg->flags); 172 173 /* 174 * Load binaries, ta_elf_load() may add external libraries to the 175 * list, so the loop will end when all the dependencies are 176 * satisfied. 177 */ 178 TAILQ_FOREACH(elf, &main_elf_queue, link) 179 ta_elf_load_dependency(elf, arg->is_32bit); 180 181 TAILQ_FOREACH(elf, &main_elf_queue, link) { 182 ta_elf_relocate(elf); 183 ta_elf_finalize_mappings(elf); 184 } 185 186 ta_elf_finalize_load_main(&arg->entry_func, &arg->load_addr); 187 188 arg->ftrace_entry = 0; 189 #ifdef CFG_FTRACE_SUPPORT 190 if (ftrace_init(&arg->fbuf)) 191 arg->ftrace_entry = (vaddr_t)(void *)ftrace_dump; 192 #endif 193 194 TAILQ_FOREACH(elf, &main_elf_queue, link) { 195 if (IS_ENABLED(CFG_TA_SANITIZE_KADDRESS)) { 196 TEE_Result rc = TEE_ERROR_GENERIC; 197 198 rc = asan_user_map_shadow((void *)elf->load_addr, 199 (void *)elf->max_addr, 200 ASAN_REG_ELF); 201 if (rc) { 202 EMSG("Failed to map shadow for ELF (%pUl)", 203 (void *)&elf->uuid); 204 panic(); 205 } 206 } 207 DMSG("ELF (%pUl) at %#"PRIxVA, 208 (void *)&elf->uuid, elf->load_addr); 209 } 210 211 #if TRACE_LEVEL >= TRACE_ERROR 212 arg->dump_entry = (vaddr_t)(void *)dump_ta_state; 213 #else 214 arg->dump_entry = 0; 215 #endif 216 arg->dl_entry = (vaddr_t)(void *)dl_entry; 217 218 sys_return_cleanup(); 219 } 220