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