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