1d8e4ae07SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause 2d8e4ae07SMarouene Boubakri /* 3d8e4ae07SMarouene Boubakri * Copyright (c) 2014, STMicroelectronics International N.V. 4d8e4ae07SMarouene Boubakri * Copyright (c) 2015-2020, 2022 Linaro Limited 5af78e1b1SImre Kis * Copyright (c) 2020-2023, Arm Limited 6d8e4ae07SMarouene Boubakri */ 7d8e4ae07SMarouene Boubakri 8d8e4ae07SMarouene Boubakri #include <assert.h> 9d8e4ae07SMarouene Boubakri #include <kernel/ldelf_loader.h> 10d8e4ae07SMarouene Boubakri #include <kernel/ldelf_syscalls.h> 11d8e4ae07SMarouene Boubakri #include <kernel/scall.h> 12d8e4ae07SMarouene Boubakri #include <ldelf.h> 13d8e4ae07SMarouene Boubakri #include <mm/mobj.h> 14d8e4ae07SMarouene Boubakri #include <mm/vm.h> 15d8e4ae07SMarouene Boubakri 16*c5a0db99SJens Wiklander #define BOUNCE_BUFFER_SIZE 4096 17*c5a0db99SJens Wiklander 18d8e4ae07SMarouene Boubakri extern uint8_t ldelf_data[]; 19d8e4ae07SMarouene Boubakri extern const unsigned int ldelf_code_size; 20d8e4ae07SMarouene Boubakri extern const unsigned int ldelf_data_size; 21d8e4ae07SMarouene Boubakri extern const unsigned int ldelf_entry; 22d8e4ae07SMarouene Boubakri 23d8e4ae07SMarouene Boubakri /* ldelf has the same architecture/register width as the kernel */ 24cb5f271cSMarouene Boubakri #if defined(ARM32) || defined(RV32) 25cb5f271cSMarouene Boubakri static const bool is_32bit = true; 26d8e4ae07SMarouene Boubakri #else 27cb5f271cSMarouene Boubakri static const bool is_32bit; 28d8e4ae07SMarouene Boubakri #endif 29d8e4ae07SMarouene Boubakri 30*c5a0db99SJens Wiklander static TEE_Result alloc_and_map_fobj(struct user_mode_ctx *uctx, size_t sz, 31*c5a0db99SJens Wiklander uint32_t prot, uint32_t flags, vaddr_t *va) 32d8e4ae07SMarouene Boubakri { 33d8e4ae07SMarouene Boubakri size_t num_pgs = ROUNDUP(sz, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; 34d8e4ae07SMarouene Boubakri struct fobj *fobj = fobj_ta_mem_alloc(num_pgs); 35d8e4ae07SMarouene Boubakri struct mobj *mobj = mobj_with_fobj_alloc(fobj, NULL, 36d8e4ae07SMarouene Boubakri TEE_MATTR_MEM_TYPE_TAGGED); 37d8e4ae07SMarouene Boubakri TEE_Result res = TEE_SUCCESS; 38d8e4ae07SMarouene Boubakri 39d8e4ae07SMarouene Boubakri fobj_put(fobj); 40d8e4ae07SMarouene Boubakri if (!mobj) 41d8e4ae07SMarouene Boubakri return TEE_ERROR_OUT_OF_MEMORY; 42*c5a0db99SJens Wiklander res = vm_map(uctx, va, num_pgs * SMALL_PAGE_SIZE, prot, flags, mobj, 0); 43d8e4ae07SMarouene Boubakri mobj_put(mobj); 44d8e4ae07SMarouene Boubakri 45d8e4ae07SMarouene Boubakri return res; 46d8e4ae07SMarouene Boubakri } 47d8e4ae07SMarouene Boubakri 48d8e4ae07SMarouene Boubakri /* 49d8e4ae07SMarouene Boubakri * This function may leave a few mappings behind on error, but that's taken 50d8e4ae07SMarouene Boubakri * care of by tee_ta_init_user_ta_session() since the entire context is 51d8e4ae07SMarouene Boubakri * removed then. 52d8e4ae07SMarouene Boubakri */ 53d8e4ae07SMarouene Boubakri TEE_Result ldelf_load_ldelf(struct user_mode_ctx *uctx) 54d8e4ae07SMarouene Boubakri { 55d8e4ae07SMarouene Boubakri TEE_Result res = TEE_SUCCESS; 56d8e4ae07SMarouene Boubakri vaddr_t stack_addr = 0; 57d8e4ae07SMarouene Boubakri vaddr_t code_addr = 0; 58d8e4ae07SMarouene Boubakri vaddr_t rw_addr = 0; 59*c5a0db99SJens Wiklander vaddr_t bb_addr = 0; 60d8e4ae07SMarouene Boubakri uint32_t prot = 0; 61d8e4ae07SMarouene Boubakri 62cb5f271cSMarouene Boubakri uctx->is_32bit = is_32bit; 63d8e4ae07SMarouene Boubakri 64*c5a0db99SJens Wiklander res = alloc_and_map_fobj(uctx, BOUNCE_BUFFER_SIZE, TEE_MATTR_PRW, 0, 65*c5a0db99SJens Wiklander &bb_addr); 66*c5a0db99SJens Wiklander if (res) 67*c5a0db99SJens Wiklander return res; 68*c5a0db99SJens Wiklander uctx->bbuf = (void *)bb_addr; 69*c5a0db99SJens Wiklander uctx->bbuf_size = BOUNCE_BUFFER_SIZE; 70*c5a0db99SJens Wiklander 71*c5a0db99SJens Wiklander res = alloc_and_map_fobj(uctx, LDELF_STACK_SIZE, 72*c5a0db99SJens Wiklander TEE_MATTR_URW | TEE_MATTR_PRW, VM_FLAG_LDELF, 73d8e4ae07SMarouene Boubakri &stack_addr); 74d8e4ae07SMarouene Boubakri if (res) 75d8e4ae07SMarouene Boubakri return res; 76d8e4ae07SMarouene Boubakri uctx->ldelf_stack_ptr = stack_addr + LDELF_STACK_SIZE; 77d8e4ae07SMarouene Boubakri 78*c5a0db99SJens Wiklander res = alloc_and_map_fobj(uctx, ldelf_code_size, TEE_MATTR_PRW, 79*c5a0db99SJens Wiklander VM_FLAG_LDELF, &code_addr); 80d8e4ae07SMarouene Boubakri if (res) 81d8e4ae07SMarouene Boubakri return res; 82d8e4ae07SMarouene Boubakri uctx->entry_func = code_addr + ldelf_entry; 83d8e4ae07SMarouene Boubakri 84d8e4ae07SMarouene Boubakri rw_addr = ROUNDUP(code_addr + ldelf_code_size, SMALL_PAGE_SIZE); 85*c5a0db99SJens Wiklander res = alloc_and_map_fobj(uctx, ldelf_data_size, 86*c5a0db99SJens Wiklander TEE_MATTR_URW | TEE_MATTR_PRW, VM_FLAG_LDELF, 87*c5a0db99SJens Wiklander &rw_addr); 88d8e4ae07SMarouene Boubakri if (res) 89d8e4ae07SMarouene Boubakri return res; 90d8e4ae07SMarouene Boubakri 91d8e4ae07SMarouene Boubakri vm_set_ctx(uctx->ts_ctx); 92d8e4ae07SMarouene Boubakri 93d8e4ae07SMarouene Boubakri memcpy((void *)code_addr, ldelf_data, ldelf_code_size); 94d8e4ae07SMarouene Boubakri memcpy((void *)rw_addr, ldelf_data + ldelf_code_size, ldelf_data_size); 95d8e4ae07SMarouene Boubakri 96d8e4ae07SMarouene Boubakri prot = TEE_MATTR_URX; 97d8e4ae07SMarouene Boubakri if (IS_ENABLED(CFG_CORE_BTI)) 98d8e4ae07SMarouene Boubakri prot |= TEE_MATTR_GUARDED; 99d8e4ae07SMarouene Boubakri 100d8e4ae07SMarouene Boubakri res = vm_set_prot(uctx, code_addr, 101d8e4ae07SMarouene Boubakri ROUNDUP(ldelf_code_size, SMALL_PAGE_SIZE), prot); 102d8e4ae07SMarouene Boubakri if (res) 103d8e4ae07SMarouene Boubakri return res; 104d8e4ae07SMarouene Boubakri 105d8e4ae07SMarouene Boubakri DMSG("ldelf load address %#"PRIxVA, code_addr); 106d8e4ae07SMarouene Boubakri 107d8e4ae07SMarouene Boubakri return TEE_SUCCESS; 108d8e4ae07SMarouene Boubakri } 109d8e4ae07SMarouene Boubakri 110d8e4ae07SMarouene Boubakri TEE_Result ldelf_init_with_ldelf(struct ts_session *sess, 111d8e4ae07SMarouene Boubakri struct user_mode_ctx *uctx) 112d8e4ae07SMarouene Boubakri { 113d8e4ae07SMarouene Boubakri TEE_Result res = TEE_SUCCESS; 114d8e4ae07SMarouene Boubakri struct ldelf_arg *arg = NULL; 115d8e4ae07SMarouene Boubakri uint32_t panic_code = 0; 116d8e4ae07SMarouene Boubakri uint32_t panicked = 0; 117d8e4ae07SMarouene Boubakri uaddr_t usr_stack = 0; 118d8e4ae07SMarouene Boubakri 119d8e4ae07SMarouene Boubakri usr_stack = uctx->ldelf_stack_ptr; 120d8e4ae07SMarouene Boubakri usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); 121d8e4ae07SMarouene Boubakri arg = (struct ldelf_arg *)usr_stack; 122d8e4ae07SMarouene Boubakri memset(arg, 0, sizeof(*arg)); 123d8e4ae07SMarouene Boubakri arg->uuid = uctx->ts_ctx->uuid; 124d8e4ae07SMarouene Boubakri sess->handle_scall = scall_handle_ldelf; 125d8e4ae07SMarouene Boubakri 126d8e4ae07SMarouene Boubakri res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, 127d8e4ae07SMarouene Boubakri usr_stack, uctx->entry_func, 128cb5f271cSMarouene Boubakri is_32bit, &panicked, &panic_code); 129d8e4ae07SMarouene Boubakri 130d8e4ae07SMarouene Boubakri sess->handle_scall = sess->ctx->ops->handle_scall; 131d8e4ae07SMarouene Boubakri thread_user_clear_vfp(uctx); 132d8e4ae07SMarouene Boubakri ldelf_sess_cleanup(sess); 133d8e4ae07SMarouene Boubakri 134d8e4ae07SMarouene Boubakri if (panicked) { 135d8e4ae07SMarouene Boubakri abort_print_current_ts(); 136d8e4ae07SMarouene Boubakri EMSG("ldelf panicked"); 137d8e4ae07SMarouene Boubakri return TEE_ERROR_GENERIC; 138d8e4ae07SMarouene Boubakri } 139d8e4ae07SMarouene Boubakri if (res) { 140d8e4ae07SMarouene Boubakri EMSG("ldelf failed with res: %#"PRIx32, res); 141d8e4ae07SMarouene Boubakri return res; 142d8e4ae07SMarouene Boubakri } 143d8e4ae07SMarouene Boubakri 144d8e4ae07SMarouene Boubakri res = vm_check_access_rights(uctx, 145d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_READ | 146d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_ANY_OWNER, 147d8e4ae07SMarouene Boubakri (uaddr_t)arg, sizeof(*arg)); 148d8e4ae07SMarouene Boubakri if (res) 149d8e4ae07SMarouene Boubakri return res; 150d8e4ae07SMarouene Boubakri 151d8e4ae07SMarouene Boubakri if (is_user_ta_ctx(uctx->ts_ctx)) { 152d8e4ae07SMarouene Boubakri /* 153d8e4ae07SMarouene Boubakri * This is already checked by the elf loader, but since it runs 154d8e4ae07SMarouene Boubakri * in user mode we're not trusting it entirely. 155d8e4ae07SMarouene Boubakri */ 156d8e4ae07SMarouene Boubakri if (arg->flags & ~TA_FLAGS_MASK) 157d8e4ae07SMarouene Boubakri return TEE_ERROR_BAD_FORMAT; 158d8e4ae07SMarouene Boubakri 159d8e4ae07SMarouene Boubakri to_user_ta_ctx(uctx->ts_ctx)->ta_ctx.flags = arg->flags; 160d8e4ae07SMarouene Boubakri } 161d8e4ae07SMarouene Boubakri 162d8e4ae07SMarouene Boubakri uctx->is_32bit = arg->is_32bit; 163d8e4ae07SMarouene Boubakri uctx->entry_func = arg->entry_func; 164af78e1b1SImre Kis uctx->load_addr = arg->load_addr; 165d8e4ae07SMarouene Boubakri uctx->stack_ptr = arg->stack_ptr; 166d8e4ae07SMarouene Boubakri uctx->dump_entry_func = arg->dump_entry; 167d8e4ae07SMarouene Boubakri #ifdef CFG_FTRACE_SUPPORT 168d8e4ae07SMarouene Boubakri uctx->ftrace_entry_func = arg->ftrace_entry; 169d8e4ae07SMarouene Boubakri sess->fbuf = arg->fbuf; 170d8e4ae07SMarouene Boubakri #endif 171d8e4ae07SMarouene Boubakri uctx->dl_entry_func = arg->dl_entry; 172d8e4ae07SMarouene Boubakri 173d8e4ae07SMarouene Boubakri return TEE_SUCCESS; 174d8e4ae07SMarouene Boubakri } 175d8e4ae07SMarouene Boubakri 176d8e4ae07SMarouene Boubakri TEE_Result ldelf_dump_state(struct user_mode_ctx *uctx) 177d8e4ae07SMarouene Boubakri { 178d8e4ae07SMarouene Boubakri TEE_Result res = TEE_SUCCESS; 179d8e4ae07SMarouene Boubakri uaddr_t usr_stack = uctx->ldelf_stack_ptr; 180d8e4ae07SMarouene Boubakri struct dump_entry_arg *arg = NULL; 181d8e4ae07SMarouene Boubakri uint32_t panic_code = 0; 182d8e4ae07SMarouene Boubakri uint32_t panicked = 0; 183d8e4ae07SMarouene Boubakri struct thread_specific_data *tsd = thread_get_tsd(); 184d8e4ae07SMarouene Boubakri struct ts_session *sess = NULL; 185d8e4ae07SMarouene Boubakri struct vm_region *r = NULL; 186d8e4ae07SMarouene Boubakri size_t n = 0; 187d8e4ae07SMarouene Boubakri 188d8e4ae07SMarouene Boubakri TAILQ_FOREACH(r, &uctx->vm_info.regions, link) 189d8e4ae07SMarouene Boubakri if (r->attr & TEE_MATTR_URWX) 190d8e4ae07SMarouene Boubakri n++; 191d8e4ae07SMarouene Boubakri 192d8e4ae07SMarouene Boubakri usr_stack = uctx->ldelf_stack_ptr; 193d8e4ae07SMarouene Boubakri usr_stack -= ROUNDUP(sizeof(*arg) + n * sizeof(struct dump_map), 194d8e4ae07SMarouene Boubakri STACK_ALIGNMENT); 195d8e4ae07SMarouene Boubakri arg = (struct dump_entry_arg *)usr_stack; 196d8e4ae07SMarouene Boubakri 197d8e4ae07SMarouene Boubakri res = vm_check_access_rights(uctx, 198d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_READ | 199d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_ANY_OWNER, 200d8e4ae07SMarouene Boubakri (uaddr_t)arg, sizeof(*arg)); 201d8e4ae07SMarouene Boubakri if (res) { 202d8e4ae07SMarouene Boubakri EMSG("ldelf stack is inaccessible!"); 203d8e4ae07SMarouene Boubakri return res; 204d8e4ae07SMarouene Boubakri } 205d8e4ae07SMarouene Boubakri 206d8e4ae07SMarouene Boubakri memset(arg, 0, sizeof(*arg) + n * sizeof(struct dump_map)); 207d8e4ae07SMarouene Boubakri 208d8e4ae07SMarouene Boubakri arg->num_maps = n; 209d8e4ae07SMarouene Boubakri n = 0; 210d8e4ae07SMarouene Boubakri TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { 211d8e4ae07SMarouene Boubakri if (r->attr & TEE_MATTR_URWX) { 212d8e4ae07SMarouene Boubakri if (r->mobj) 213d8e4ae07SMarouene Boubakri mobj_get_pa(r->mobj, r->offset, 0, 214d8e4ae07SMarouene Boubakri &arg->maps[n].pa); 215d8e4ae07SMarouene Boubakri arg->maps[n].va = r->va; 216d8e4ae07SMarouene Boubakri arg->maps[n].sz = r->size; 217d8e4ae07SMarouene Boubakri if (r->attr & TEE_MATTR_UR) 218d8e4ae07SMarouene Boubakri arg->maps[n].flags |= DUMP_MAP_READ; 219d8e4ae07SMarouene Boubakri if (r->attr & TEE_MATTR_UW) 220d8e4ae07SMarouene Boubakri arg->maps[n].flags |= DUMP_MAP_WRITE; 221d8e4ae07SMarouene Boubakri if (r->attr & TEE_MATTR_UX) 222d8e4ae07SMarouene Boubakri arg->maps[n].flags |= DUMP_MAP_EXEC; 223d8e4ae07SMarouene Boubakri if (r->attr & TEE_MATTR_SECURE) 224d8e4ae07SMarouene Boubakri arg->maps[n].flags |= DUMP_MAP_SECURE; 225d8e4ae07SMarouene Boubakri if (r->flags & VM_FLAG_EPHEMERAL) 226d8e4ae07SMarouene Boubakri arg->maps[n].flags |= DUMP_MAP_EPHEM; 227d8e4ae07SMarouene Boubakri if (r->flags & VM_FLAG_LDELF) 228d8e4ae07SMarouene Boubakri arg->maps[n].flags |= DUMP_MAP_LDELF; 229d8e4ae07SMarouene Boubakri n++; 230d8e4ae07SMarouene Boubakri } 231d8e4ae07SMarouene Boubakri } 232d8e4ae07SMarouene Boubakri 233cb5f271cSMarouene Boubakri arg->is_32bit = uctx->is_32bit; 234d8e4ae07SMarouene Boubakri #ifdef ARM32 235d8e4ae07SMarouene Boubakri arg->arm32.regs[0] = tsd->abort_regs.r0; 236d8e4ae07SMarouene Boubakri arg->arm32.regs[1] = tsd->abort_regs.r1; 237d8e4ae07SMarouene Boubakri arg->arm32.regs[2] = tsd->abort_regs.r2; 238d8e4ae07SMarouene Boubakri arg->arm32.regs[3] = tsd->abort_regs.r3; 239d8e4ae07SMarouene Boubakri arg->arm32.regs[4] = tsd->abort_regs.r4; 240d8e4ae07SMarouene Boubakri arg->arm32.regs[5] = tsd->abort_regs.r5; 241d8e4ae07SMarouene Boubakri arg->arm32.regs[6] = tsd->abort_regs.r6; 242d8e4ae07SMarouene Boubakri arg->arm32.regs[7] = tsd->abort_regs.r7; 243d8e4ae07SMarouene Boubakri arg->arm32.regs[8] = tsd->abort_regs.r8; 244d8e4ae07SMarouene Boubakri arg->arm32.regs[9] = tsd->abort_regs.r9; 245d8e4ae07SMarouene Boubakri arg->arm32.regs[10] = tsd->abort_regs.r10; 246d8e4ae07SMarouene Boubakri arg->arm32.regs[11] = tsd->abort_regs.r11; 247d8e4ae07SMarouene Boubakri arg->arm32.regs[12] = tsd->abort_regs.ip; 248d8e4ae07SMarouene Boubakri arg->arm32.regs[13] = tsd->abort_regs.usr_sp; /*SP*/ 249d8e4ae07SMarouene Boubakri arg->arm32.regs[14] = tsd->abort_regs.usr_lr; /*LR*/ 250d8e4ae07SMarouene Boubakri arg->arm32.regs[15] = tsd->abort_regs.elr; /*PC*/ 251d8e4ae07SMarouene Boubakri #endif /*ARM32*/ 252d8e4ae07SMarouene Boubakri #ifdef ARM64 253d8e4ae07SMarouene Boubakri if (uctx->is_32bit) { 254d8e4ae07SMarouene Boubakri arg->arm32.regs[0] = tsd->abort_regs.x0; 255d8e4ae07SMarouene Boubakri arg->arm32.regs[1] = tsd->abort_regs.x1; 256d8e4ae07SMarouene Boubakri arg->arm32.regs[2] = tsd->abort_regs.x2; 257d8e4ae07SMarouene Boubakri arg->arm32.regs[3] = tsd->abort_regs.x3; 258d8e4ae07SMarouene Boubakri arg->arm32.regs[4] = tsd->abort_regs.x4; 259d8e4ae07SMarouene Boubakri arg->arm32.regs[5] = tsd->abort_regs.x5; 260d8e4ae07SMarouene Boubakri arg->arm32.regs[6] = tsd->abort_regs.x6; 261d8e4ae07SMarouene Boubakri arg->arm32.regs[7] = tsd->abort_regs.x7; 262d8e4ae07SMarouene Boubakri arg->arm32.regs[8] = tsd->abort_regs.x8; 263d8e4ae07SMarouene Boubakri arg->arm32.regs[9] = tsd->abort_regs.x9; 264d8e4ae07SMarouene Boubakri arg->arm32.regs[10] = tsd->abort_regs.x10; 265d8e4ae07SMarouene Boubakri arg->arm32.regs[11] = tsd->abort_regs.x11; 266d8e4ae07SMarouene Boubakri arg->arm32.regs[12] = tsd->abort_regs.x12; 267d8e4ae07SMarouene Boubakri arg->arm32.regs[13] = tsd->abort_regs.x13; /*SP*/ 268d8e4ae07SMarouene Boubakri arg->arm32.regs[14] = tsd->abort_regs.x14; /*LR*/ 269d8e4ae07SMarouene Boubakri arg->arm32.regs[15] = tsd->abort_regs.elr; /*PC*/ 270d8e4ae07SMarouene Boubakri } else { 271d8e4ae07SMarouene Boubakri arg->arm64.fp = tsd->abort_regs.x29; 272d8e4ae07SMarouene Boubakri arg->arm64.pc = tsd->abort_regs.elr; 273d8e4ae07SMarouene Boubakri arg->arm64.sp = tsd->abort_regs.sp_el0; 274d8e4ae07SMarouene Boubakri } 275d8e4ae07SMarouene Boubakri #endif /*ARM64*/ 27674f6dd9bSMarouene Boubakri #if defined(RV64) || defined(RV32) 27774f6dd9bSMarouene Boubakri arg->rv.fp = tsd->abort_regs.s0; 27874f6dd9bSMarouene Boubakri arg->rv.pc = tsd->abort_regs.epc; 27974f6dd9bSMarouene Boubakri arg->rv.sp = tsd->abort_regs.sp; 28074f6dd9bSMarouene Boubakri #endif /*RV64||RV32*/ 281d8e4ae07SMarouene Boubakri 282d8e4ae07SMarouene Boubakri sess = ts_get_current_session(); 283d8e4ae07SMarouene Boubakri sess->handle_scall = scall_handle_ldelf; 284d8e4ae07SMarouene Boubakri 285d8e4ae07SMarouene Boubakri res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, 286d8e4ae07SMarouene Boubakri usr_stack, uctx->dump_entry_func, 287cb5f271cSMarouene Boubakri is_32bit, &panicked, &panic_code); 288d8e4ae07SMarouene Boubakri 289d8e4ae07SMarouene Boubakri sess->handle_scall = sess->ctx->ops->handle_scall; 290d8e4ae07SMarouene Boubakri thread_user_clear_vfp(uctx); 291d8e4ae07SMarouene Boubakri ldelf_sess_cleanup(sess); 292d8e4ae07SMarouene Boubakri 293d8e4ae07SMarouene Boubakri if (panicked) { 294d8e4ae07SMarouene Boubakri uctx->dump_entry_func = 0; 295d8e4ae07SMarouene Boubakri EMSG("ldelf dump function panicked"); 296d8e4ae07SMarouene Boubakri abort_print_current_ts(); 297d8e4ae07SMarouene Boubakri res = TEE_ERROR_TARGET_DEAD; 298d8e4ae07SMarouene Boubakri } 299d8e4ae07SMarouene Boubakri 300d8e4ae07SMarouene Boubakri return res; 301d8e4ae07SMarouene Boubakri } 302d8e4ae07SMarouene Boubakri 303d8e4ae07SMarouene Boubakri #ifdef CFG_FTRACE_SUPPORT 304d8e4ae07SMarouene Boubakri TEE_Result ldelf_dump_ftrace(struct user_mode_ctx *uctx, 305d8e4ae07SMarouene Boubakri void *buf, size_t *blen) 306d8e4ae07SMarouene Boubakri { 307d8e4ae07SMarouene Boubakri uaddr_t usr_stack = uctx->ldelf_stack_ptr; 308d8e4ae07SMarouene Boubakri TEE_Result res = TEE_SUCCESS; 309d8e4ae07SMarouene Boubakri uint32_t panic_code = 0; 310d8e4ae07SMarouene Boubakri uint32_t panicked = 0; 311d8e4ae07SMarouene Boubakri size_t *arg = NULL; 312d8e4ae07SMarouene Boubakri struct ts_session *sess = NULL; 313d8e4ae07SMarouene Boubakri 314d8e4ae07SMarouene Boubakri if (!uctx->ftrace_entry_func) 315d8e4ae07SMarouene Boubakri return TEE_ERROR_NOT_SUPPORTED; 316d8e4ae07SMarouene Boubakri 317d8e4ae07SMarouene Boubakri usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); 318d8e4ae07SMarouene Boubakri arg = (size_t *)usr_stack; 319d8e4ae07SMarouene Boubakri 320d8e4ae07SMarouene Boubakri res = vm_check_access_rights(uctx, 321d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_READ | 322d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_ANY_OWNER, 323d8e4ae07SMarouene Boubakri (uaddr_t)arg, sizeof(*arg)); 324d8e4ae07SMarouene Boubakri if (res) { 325d8e4ae07SMarouene Boubakri EMSG("ldelf stack is inaccessible!"); 326d8e4ae07SMarouene Boubakri return res; 327d8e4ae07SMarouene Boubakri } 328d8e4ae07SMarouene Boubakri 329d8e4ae07SMarouene Boubakri *arg = *blen; 330d8e4ae07SMarouene Boubakri 331d8e4ae07SMarouene Boubakri sess = ts_get_current_session(); 332d8e4ae07SMarouene Boubakri sess->handle_scall = scall_handle_ldelf; 333d8e4ae07SMarouene Boubakri 334d8e4ae07SMarouene Boubakri res = thread_enter_user_mode((vaddr_t)buf, (vaddr_t)arg, 0, 0, 335d8e4ae07SMarouene Boubakri usr_stack, uctx->ftrace_entry_func, 336cb5f271cSMarouene Boubakri is_32bit, &panicked, &panic_code); 337d8e4ae07SMarouene Boubakri 338d8e4ae07SMarouene Boubakri sess->handle_scall = sess->ctx->ops->handle_scall; 339d8e4ae07SMarouene Boubakri thread_user_clear_vfp(uctx); 340d8e4ae07SMarouene Boubakri ldelf_sess_cleanup(sess); 341d8e4ae07SMarouene Boubakri 342d8e4ae07SMarouene Boubakri if (panicked) { 343d8e4ae07SMarouene Boubakri uctx->ftrace_entry_func = 0; 344d8e4ae07SMarouene Boubakri EMSG("ldelf ftrace function panicked"); 345d8e4ae07SMarouene Boubakri abort_print_current_ts(); 346d8e4ae07SMarouene Boubakri res = TEE_ERROR_TARGET_DEAD; 347d8e4ae07SMarouene Boubakri } 348d8e4ae07SMarouene Boubakri 349d8e4ae07SMarouene Boubakri if (!res) { 350d8e4ae07SMarouene Boubakri if (*arg > *blen) 351d8e4ae07SMarouene Boubakri res = TEE_ERROR_SHORT_BUFFER; 352d8e4ae07SMarouene Boubakri *blen = *arg; 353d8e4ae07SMarouene Boubakri } 354d8e4ae07SMarouene Boubakri 355d8e4ae07SMarouene Boubakri return res; 356d8e4ae07SMarouene Boubakri } 357d8e4ae07SMarouene Boubakri #endif /*CFG_FTRACE_SUPPORT*/ 358d8e4ae07SMarouene Boubakri 359d8e4ae07SMarouene Boubakri TEE_Result ldelf_dlopen(struct user_mode_ctx *uctx, TEE_UUID *uuid, 360d8e4ae07SMarouene Boubakri uint32_t flags) 361d8e4ae07SMarouene Boubakri { 362d8e4ae07SMarouene Boubakri uaddr_t usr_stack = uctx->ldelf_stack_ptr; 363d8e4ae07SMarouene Boubakri TEE_Result res = TEE_ERROR_GENERIC; 364d8e4ae07SMarouene Boubakri struct dl_entry_arg *arg = NULL; 365d8e4ae07SMarouene Boubakri uint32_t panic_code = 0; 366d8e4ae07SMarouene Boubakri uint32_t panicked = 0; 367d8e4ae07SMarouene Boubakri struct ts_session *sess = NULL; 368d8e4ae07SMarouene Boubakri 369d8e4ae07SMarouene Boubakri assert(uuid); 370d8e4ae07SMarouene Boubakri 371d8e4ae07SMarouene Boubakri usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); 372d8e4ae07SMarouene Boubakri arg = (struct dl_entry_arg *)usr_stack; 373d8e4ae07SMarouene Boubakri 374d8e4ae07SMarouene Boubakri res = vm_check_access_rights(uctx, 375d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_READ | 376d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_WRITE | 377d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_ANY_OWNER, 378d8e4ae07SMarouene Boubakri (uaddr_t)arg, sizeof(*arg)); 379d8e4ae07SMarouene Boubakri if (res) { 380d8e4ae07SMarouene Boubakri EMSG("ldelf stack is inaccessible!"); 381d8e4ae07SMarouene Boubakri return res; 382d8e4ae07SMarouene Boubakri } 383d8e4ae07SMarouene Boubakri 384d8e4ae07SMarouene Boubakri memset(arg, 0, sizeof(*arg)); 385d8e4ae07SMarouene Boubakri arg->cmd = LDELF_DL_ENTRY_DLOPEN; 386d8e4ae07SMarouene Boubakri arg->dlopen.uuid = *uuid; 387d8e4ae07SMarouene Boubakri arg->dlopen.flags = flags; 388d8e4ae07SMarouene Boubakri 389d8e4ae07SMarouene Boubakri sess = ts_get_current_session(); 390d8e4ae07SMarouene Boubakri sess->handle_scall = scall_handle_ldelf; 391d8e4ae07SMarouene Boubakri 392d8e4ae07SMarouene Boubakri res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, 393d8e4ae07SMarouene Boubakri usr_stack, uctx->dl_entry_func, 394cb5f271cSMarouene Boubakri is_32bit, &panicked, &panic_code); 395d8e4ae07SMarouene Boubakri 396d8e4ae07SMarouene Boubakri sess->handle_scall = sess->ctx->ops->handle_scall; 397d8e4ae07SMarouene Boubakri ldelf_sess_cleanup(sess); 398d8e4ae07SMarouene Boubakri 399d8e4ae07SMarouene Boubakri if (panicked) { 400d8e4ae07SMarouene Boubakri EMSG("ldelf dl_entry function panicked"); 401d8e4ae07SMarouene Boubakri abort_print_current_ts(); 402d8e4ae07SMarouene Boubakri res = TEE_ERROR_TARGET_DEAD; 403d8e4ae07SMarouene Boubakri } 404d8e4ae07SMarouene Boubakri if (!res) 405d8e4ae07SMarouene Boubakri res = arg->ret; 406d8e4ae07SMarouene Boubakri 407d8e4ae07SMarouene Boubakri return res; 408d8e4ae07SMarouene Boubakri } 409d8e4ae07SMarouene Boubakri 410d8e4ae07SMarouene Boubakri TEE_Result ldelf_dlsym(struct user_mode_ctx *uctx, TEE_UUID *uuid, 411d8e4ae07SMarouene Boubakri const char *sym, size_t maxlen, vaddr_t *val) 412d8e4ae07SMarouene Boubakri { 413d8e4ae07SMarouene Boubakri uaddr_t usr_stack = uctx->ldelf_stack_ptr; 414d8e4ae07SMarouene Boubakri TEE_Result res = TEE_ERROR_GENERIC; 415d8e4ae07SMarouene Boubakri struct dl_entry_arg *arg = NULL; 416d8e4ae07SMarouene Boubakri uint32_t panic_code = 0; 417d8e4ae07SMarouene Boubakri uint32_t panicked = 0; 418d8e4ae07SMarouene Boubakri size_t len = strnlen(sym, maxlen); 419d8e4ae07SMarouene Boubakri struct ts_session *sess = NULL; 420d8e4ae07SMarouene Boubakri 421d8e4ae07SMarouene Boubakri if (len == maxlen) 422d8e4ae07SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 423d8e4ae07SMarouene Boubakri 424d8e4ae07SMarouene Boubakri usr_stack -= ROUNDUP(sizeof(*arg) + len + 1, STACK_ALIGNMENT); 425d8e4ae07SMarouene Boubakri arg = (struct dl_entry_arg *)usr_stack; 426d8e4ae07SMarouene Boubakri 427d8e4ae07SMarouene Boubakri res = vm_check_access_rights(uctx, 428d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_READ | 429d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_WRITE | 430d8e4ae07SMarouene Boubakri TEE_MEMORY_ACCESS_ANY_OWNER, 431d8e4ae07SMarouene Boubakri (uaddr_t)arg, sizeof(*arg) + len + 1); 432d8e4ae07SMarouene Boubakri if (res) { 433d8e4ae07SMarouene Boubakri EMSG("ldelf stack is inaccessible!"); 434d8e4ae07SMarouene Boubakri return res; 435d8e4ae07SMarouene Boubakri } 436d8e4ae07SMarouene Boubakri 437d8e4ae07SMarouene Boubakri memset(arg, 0, sizeof(*arg)); 438d8e4ae07SMarouene Boubakri arg->cmd = LDELF_DL_ENTRY_DLSYM; 439d8e4ae07SMarouene Boubakri arg->dlsym.uuid = *uuid; 440d8e4ae07SMarouene Boubakri memcpy(arg->dlsym.symbol, sym, len); 441d8e4ae07SMarouene Boubakri arg->dlsym.symbol[len] = '\0'; 442d8e4ae07SMarouene Boubakri 443d8e4ae07SMarouene Boubakri sess = ts_get_current_session(); 444d8e4ae07SMarouene Boubakri sess->handle_scall = scall_handle_ldelf; 445d8e4ae07SMarouene Boubakri 446d8e4ae07SMarouene Boubakri res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, 447d8e4ae07SMarouene Boubakri usr_stack, uctx->dl_entry_func, 448cb5f271cSMarouene Boubakri is_32bit, &panicked, &panic_code); 449d8e4ae07SMarouene Boubakri 450d8e4ae07SMarouene Boubakri sess->handle_scall = sess->ctx->ops->handle_scall; 451d8e4ae07SMarouene Boubakri ldelf_sess_cleanup(sess); 452d8e4ae07SMarouene Boubakri 453d8e4ae07SMarouene Boubakri if (panicked) { 454d8e4ae07SMarouene Boubakri EMSG("ldelf dl_entry function panicked"); 455d8e4ae07SMarouene Boubakri abort_print_current_ts(); 456d8e4ae07SMarouene Boubakri res = TEE_ERROR_TARGET_DEAD; 457d8e4ae07SMarouene Boubakri } 458d8e4ae07SMarouene Boubakri if (!res) { 459d8e4ae07SMarouene Boubakri res = arg->ret; 460d8e4ae07SMarouene Boubakri if (!res) 461d8e4ae07SMarouene Boubakri *val = arg->dlsym.val; 462d8e4ae07SMarouene Boubakri } 463d8e4ae07SMarouene Boubakri 464d8e4ae07SMarouene Boubakri return res; 465d8e4ae07SMarouene Boubakri } 466