xref: /optee_os/core/kernel/scall.c (revision c5a0db9903f1889a430a5d7143e2fa8b3cff6729)
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