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