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