1*fc82e622SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2*fc82e622SJens Wiklander /* 3*fc82e622SJens Wiklander * Copyright (c) 2014-2022, Linaro Limited 4*fc82e622SJens Wiklander * Copyright (c) 2020, Arm Limited 5*fc82e622SJens Wiklander */ 6*fc82e622SJens Wiklander 7*fc82e622SJens Wiklander #include <assert.h> 8*fc82e622SJens Wiklander #include <kernel/abort.h> 9*fc82e622SJens Wiklander #include <kernel/arch_scall.h> 10*fc82e622SJens Wiklander #include <kernel/ldelf_syscalls.h> 11*fc82e622SJens Wiklander #include <kernel/misc.h> 12*fc82e622SJens Wiklander #include <kernel/panic.h> 13*fc82e622SJens Wiklander #include <kernel/scall.h> 14*fc82e622SJens Wiklander #include <kernel/tee_ta_manager.h> 15*fc82e622SJens Wiklander #include <kernel/thread.h> 16*fc82e622SJens Wiklander #include <kernel/trace_ta.h> 17*fc82e622SJens Wiklander #include <kernel/user_ta.h> 18*fc82e622SJens Wiklander #include <ldelf.h> 19*fc82e622SJens Wiklander #include <mm/vm.h> 20*fc82e622SJens Wiklander #include <speculation_barrier.h> 21*fc82e622SJens Wiklander #include <string.h> 22*fc82e622SJens Wiklander #include <tee/svc_cache.h> 23*fc82e622SJens Wiklander #include <tee_syscall_numbers.h> 24*fc82e622SJens Wiklander #include <tee/tee_svc_cryp.h> 25*fc82e622SJens Wiklander #include <tee/tee_svc.h> 26*fc82e622SJens Wiklander #include <tee/tee_svc_storage.h> 27*fc82e622SJens Wiklander #include <trace.h> 28*fc82e622SJens Wiklander #include <util.h> 29*fc82e622SJens Wiklander 30*fc82e622SJens Wiklander #if (TRACE_LEVEL == TRACE_FLOW) && defined(CFG_TEE_CORE_TA_TRACE) 31*fc82e622SJens Wiklander #define TRACE_SYSCALLS 32*fc82e622SJens Wiklander #endif 33*fc82e622SJens Wiklander 34*fc82e622SJens Wiklander struct syscall_entry { 35*fc82e622SJens Wiklander syscall_t fn; 36*fc82e622SJens Wiklander #ifdef TRACE_SYSCALLS 37*fc82e622SJens Wiklander const char *name; 38*fc82e622SJens Wiklander #endif 39*fc82e622SJens Wiklander }; 40*fc82e622SJens Wiklander 41*fc82e622SJens Wiklander #ifdef TRACE_SYSCALLS 42*fc82e622SJens Wiklander #define SYSCALL_ENTRY(_fn) { .fn = (syscall_t)_fn, .name = #_fn } 43*fc82e622SJens Wiklander #else 44*fc82e622SJens Wiklander #define SYSCALL_ENTRY(_fn) { .fn = (syscall_t)_fn } 45*fc82e622SJens Wiklander #endif 46*fc82e622SJens Wiklander 47*fc82e622SJens Wiklander /* 48*fc82e622SJens Wiklander * This array is ordered according to the SYSCALL ids TEE_SCN_xxx 49*fc82e622SJens Wiklander */ 50*fc82e622SJens Wiklander static const struct syscall_entry tee_syscall_table[] = { 51*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_sys_return), 52*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_log), 53*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_panic), 54*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_get_property), 55*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_get_property_name_to_index), 56*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_open_ta_session), 57*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_close_ta_session), 58*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_invoke_ta_command), 59*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_check_access_rights), 60*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_get_cancellation_flag), 61*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_unmask_cancellation), 62*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_mask_cancellation), 63*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_wait), 64*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_get_time), 65*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_set_ta_time), 66*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_state_alloc), 67*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_state_copy), 68*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_state_free), 69*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_hash_init), 70*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_hash_update), 71*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_hash_final), 72*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cipher_init), 73*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cipher_update), 74*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cipher_final), 75*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_obj_get_info), 76*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_obj_restrict_usage), 77*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_obj_get_attr), 78*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_obj_alloc), 79*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_obj_close), 80*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_obj_reset), 81*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_obj_populate), 82*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_obj_copy), 83*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_derive_key), 84*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cryp_random_number_generate), 85*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_authenc_init), 86*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_authenc_update_aad), 87*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_authenc_update_payload), 88*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_authenc_enc_final), 89*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_authenc_dec_final), 90*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_asymm_operate), 91*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_asymm_verify), 92*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_obj_open), 93*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_obj_create), 94*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_obj_del), 95*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_obj_rename), 96*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_alloc_enum), 97*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_free_enum), 98*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_reset_enum), 99*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_start_enum), 100*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_next_enum), 101*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_obj_read), 102*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_obj_write), 103*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_obj_trunc), 104*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_storage_obj_seek), 105*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_obj_generate_key), 106*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 107*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 108*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 109*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 110*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 111*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 112*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 113*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 114*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 115*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 116*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 117*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 118*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 119*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 120*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_not_supported), 121*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_cache_operation), 122*fc82e622SJens Wiklander }; 123*fc82e622SJens Wiklander 124*fc82e622SJens Wiklander /* 125*fc82e622SJens Wiklander * The ldelf return, log, panic syscalls have the same functionality and syscall 126*fc82e622SJens Wiklander * number as the user TAs'. To avoid unnecessary code duplication, the ldelf SVC 127*fc82e622SJens Wiklander * handler doesn't implement separate functions for these. 128*fc82e622SJens Wiklander */ 129*fc82e622SJens Wiklander static const struct syscall_entry ldelf_syscall_table[] = { 130*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_sys_return), 131*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_log), 132*fc82e622SJens Wiklander SYSCALL_ENTRY(syscall_panic), 133*fc82e622SJens Wiklander SYSCALL_ENTRY(ldelf_syscall_map_zi), 134*fc82e622SJens Wiklander SYSCALL_ENTRY(ldelf_syscall_unmap), 135*fc82e622SJens Wiklander SYSCALL_ENTRY(ldelf_syscall_open_bin), 136*fc82e622SJens Wiklander SYSCALL_ENTRY(ldelf_syscall_close_bin), 137*fc82e622SJens Wiklander SYSCALL_ENTRY(ldelf_syscall_map_bin), 138*fc82e622SJens Wiklander SYSCALL_ENTRY(ldelf_syscall_copy_from_bin), 139*fc82e622SJens Wiklander SYSCALL_ENTRY(ldelf_syscall_set_prot), 140*fc82e622SJens Wiklander SYSCALL_ENTRY(ldelf_syscall_remap), 141*fc82e622SJens Wiklander SYSCALL_ENTRY(ldelf_syscall_gen_rnd_num), 142*fc82e622SJens Wiklander }; 143*fc82e622SJens Wiklander 144*fc82e622SJens Wiklander #ifdef TRACE_SYSCALLS 145*fc82e622SJens Wiklander static void trace_syscall(size_t num) 146*fc82e622SJens Wiklander { 147*fc82e622SJens Wiklander if (num == TEE_SCN_RETURN || num == TEE_SCN_LOG || num > TEE_SCN_MAX) 148*fc82e622SJens Wiklander return; 149*fc82e622SJens Wiklander FMSG("syscall #%zu (%s)", num, tee_syscall_table[num].name); 150*fc82e622SJens Wiklander } 151*fc82e622SJens Wiklander #else 152*fc82e622SJens Wiklander static void trace_syscall(size_t num __unused) 153*fc82e622SJens Wiklander { 154*fc82e622SJens Wiklander } 155*fc82e622SJens Wiklander #endif 156*fc82e622SJens Wiklander 157*fc82e622SJens Wiklander #ifdef CFG_SYSCALL_FTRACE 158*fc82e622SJens Wiklander static void __noprof ftrace_syscall_enter(size_t num) 159*fc82e622SJens Wiklander { 160*fc82e622SJens Wiklander struct ts_session *s = NULL; 161*fc82e622SJens Wiklander 162*fc82e622SJens Wiklander /* 163*fc82e622SJens Wiklander * Syscalls related to inter-TA communication can't be traced in the 164*fc82e622SJens Wiklander * caller TA's ftrace buffer as it involves context switching to callee 165*fc82e622SJens Wiklander * TA's context. Moreover, user can enable ftrace for callee TA to dump 166*fc82e622SJens Wiklander * function trace in corresponding ftrace buffer. 167*fc82e622SJens Wiklander */ 168*fc82e622SJens Wiklander if (num == TEE_SCN_OPEN_TA_SESSION || num == TEE_SCN_CLOSE_TA_SESSION || 169*fc82e622SJens Wiklander num == TEE_SCN_INVOKE_TA_COMMAND) 170*fc82e622SJens Wiklander return; 171*fc82e622SJens Wiklander 172*fc82e622SJens Wiklander s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); 173*fc82e622SJens Wiklander if (s && s->fbuf) 174*fc82e622SJens Wiklander s->fbuf->syscall_trace_enabled = true; 175*fc82e622SJens Wiklander } 176*fc82e622SJens Wiklander 177*fc82e622SJens Wiklander static void __noprof ftrace_syscall_leave(void) 178*fc82e622SJens Wiklander { 179*fc82e622SJens Wiklander struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); 180*fc82e622SJens Wiklander 181*fc82e622SJens Wiklander if (s && s->fbuf) 182*fc82e622SJens Wiklander s->fbuf->syscall_trace_enabled = false; 183*fc82e622SJens Wiklander } 184*fc82e622SJens Wiklander #else 185*fc82e622SJens Wiklander static void __noprof ftrace_syscall_enter(size_t num __unused) 186*fc82e622SJens Wiklander { 187*fc82e622SJens Wiklander } 188*fc82e622SJens Wiklander 189*fc82e622SJens Wiklander static void __noprof ftrace_syscall_leave(void) 190*fc82e622SJens Wiklander { 191*fc82e622SJens Wiklander } 192*fc82e622SJens Wiklander #endif 193*fc82e622SJens Wiklander 194*fc82e622SJens Wiklander static syscall_t get_tee_syscall_func(size_t num) 195*fc82e622SJens Wiklander { 196*fc82e622SJens Wiklander /* Cast away const */ 197*fc82e622SJens Wiklander struct syscall_entry *sc_table = (void *)tee_syscall_table; 198*fc82e622SJens Wiklander 199*fc82e622SJens Wiklander static_assert(ARRAY_SIZE(tee_syscall_table) == (TEE_SCN_MAX + 1)); 200*fc82e622SJens Wiklander 201*fc82e622SJens Wiklander if (num > TEE_SCN_MAX) 202*fc82e622SJens Wiklander return (syscall_t)syscall_not_supported; 203*fc82e622SJens Wiklander 204*fc82e622SJens Wiklander return load_no_speculate(&sc_table[num].fn, &sc_table[0].fn, 205*fc82e622SJens Wiklander &sc_table[TEE_SCN_MAX].fn + 1); 206*fc82e622SJens Wiklander } 207*fc82e622SJens Wiklander 208*fc82e622SJens Wiklander bool scall_handle_user_ta(struct thread_scall_regs *regs) 209*fc82e622SJens Wiklander { 210*fc82e622SJens Wiklander size_t scn = 0; 211*fc82e622SJens Wiklander size_t max_args = 0; 212*fc82e622SJens Wiklander syscall_t scf = NULL; 213*fc82e622SJens Wiklander 214*fc82e622SJens Wiklander scall_get_max_args(regs, &scn, &max_args); 215*fc82e622SJens Wiklander 216*fc82e622SJens Wiklander trace_syscall(scn); 217*fc82e622SJens Wiklander 218*fc82e622SJens Wiklander if (max_args > TEE_SVC_MAX_ARGS) { 219*fc82e622SJens Wiklander DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args); 220*fc82e622SJens Wiklander scall_set_retval(regs, TEE_ERROR_GENERIC); 221*fc82e622SJens Wiklander return true; /* return to user mode */ 222*fc82e622SJens Wiklander } 223*fc82e622SJens Wiklander 224*fc82e622SJens Wiklander scf = get_tee_syscall_func(scn); 225*fc82e622SJens Wiklander 226*fc82e622SJens Wiklander ftrace_syscall_enter(scn); 227*fc82e622SJens Wiklander 228*fc82e622SJens Wiklander scall_set_retval(regs, scall_do_call(regs, scf)); 229*fc82e622SJens Wiklander 230*fc82e622SJens Wiklander ftrace_syscall_leave(); 231*fc82e622SJens Wiklander 232*fc82e622SJens Wiklander /* 233*fc82e622SJens Wiklander * Return true if we're to return to user mode, 234*fc82e622SJens Wiklander * thread_scall_handler() will take care of the rest. 235*fc82e622SJens Wiklander */ 236*fc82e622SJens Wiklander return scn != TEE_SCN_RETURN && scn != TEE_SCN_PANIC; 237*fc82e622SJens Wiklander } 238*fc82e622SJens Wiklander 239*fc82e622SJens Wiklander static syscall_t get_ldelf_syscall_func(size_t num) 240*fc82e622SJens Wiklander { 241*fc82e622SJens Wiklander /* Cast away const */ 242*fc82e622SJens Wiklander struct syscall_entry *sc_table = (void *)ldelf_syscall_table; 243*fc82e622SJens Wiklander 244*fc82e622SJens Wiklander COMPILE_TIME_ASSERT(ARRAY_SIZE(ldelf_syscall_table) == 245*fc82e622SJens Wiklander (LDELF_SCN_MAX + 1)); 246*fc82e622SJens Wiklander 247*fc82e622SJens Wiklander if (num > LDELF_SCN_MAX) 248*fc82e622SJens Wiklander return (syscall_t)syscall_not_supported; 249*fc82e622SJens Wiklander 250*fc82e622SJens Wiklander return load_no_speculate(&sc_table[num].fn, &sc_table[0].fn, 251*fc82e622SJens Wiklander &sc_table[LDELF_SCN_MAX].fn + 1); 252*fc82e622SJens Wiklander } 253*fc82e622SJens Wiklander 254*fc82e622SJens Wiklander bool scall_handle_ldelf(struct thread_scall_regs *regs) 255*fc82e622SJens Wiklander { 256*fc82e622SJens Wiklander size_t scn = 0; 257*fc82e622SJens Wiklander size_t max_args = 0; 258*fc82e622SJens Wiklander syscall_t scf = NULL; 259*fc82e622SJens Wiklander 260*fc82e622SJens Wiklander scall_get_max_args(regs, &scn, &max_args); 261*fc82e622SJens Wiklander 262*fc82e622SJens Wiklander trace_syscall(scn); 263*fc82e622SJens Wiklander 264*fc82e622SJens Wiklander if (max_args > TEE_SVC_MAX_ARGS) { 265*fc82e622SJens Wiklander DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args); 266*fc82e622SJens Wiklander scall_set_retval(regs, TEE_ERROR_GENERIC); 267*fc82e622SJens Wiklander return true; /* return to user mode */ 268*fc82e622SJens Wiklander } 269*fc82e622SJens Wiklander 270*fc82e622SJens Wiklander scf = get_ldelf_syscall_func(scn); 271*fc82e622SJens Wiklander 272*fc82e622SJens Wiklander ftrace_syscall_enter(scn); 273*fc82e622SJens Wiklander 274*fc82e622SJens Wiklander scall_set_retval(regs, scall_do_call(regs, scf)); 275*fc82e622SJens Wiklander 276*fc82e622SJens Wiklander ftrace_syscall_leave(); 277*fc82e622SJens Wiklander 278*fc82e622SJens Wiklander /* 279*fc82e622SJens Wiklander * Return true if we're to return to user mode, 280*fc82e622SJens Wiklander * thread_scall_handler() will take care of the rest. 281*fc82e622SJens Wiklander */ 282*fc82e622SJens Wiklander return scn != LDELF_RETURN && scn != LDELF_PANIC; 283*fc82e622SJens Wiklander } 284*fc82e622SJens Wiklander 285*fc82e622SJens Wiklander uint32_t scall_sys_return_helper(uint32_t ret, bool panic, uint32_t panic_code, 286*fc82e622SJens Wiklander struct thread_scall_regs *regs) 287*fc82e622SJens Wiklander { 288*fc82e622SJens Wiklander if (panic) { 289*fc82e622SJens Wiklander TAMSG_RAW(""); 290*fc82e622SJens Wiklander TAMSG_RAW("TA panicked with code 0x%" PRIx32, panic_code); 291*fc82e622SJens Wiklander scall_save_panic_stack(regs); 292*fc82e622SJens Wiklander } 293*fc82e622SJens Wiklander 294*fc82e622SJens Wiklander scall_set_sys_return_regs(regs, panic, panic_code); 295*fc82e622SJens Wiklander 296*fc82e622SJens Wiklander return ret; 297*fc82e622SJens Wiklander } 298