1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12
13 #include <stddef.h>
14 #include <tee_config.h>
15 #include "securec.h"
16 #include "ta_framework.h"
17 #include "gtask_inner.h"
18 #include "mem_manager.h"
19 #include "session_manager.h"
20 #include "agent_manager.h"
21 #include "service_manager.h"
22 #include "global_task.h"
23 #include "tee_log.h"
24 #include "tee_app_load_srv.h"
25 #include "tee_property_api.h"
26 #include "timer_export.h"
27 #include <teecall.h>
28 #include "tee_init.h"
29 #include <string.h>
30 #include <ipclib.h>
31 #include "init.h"
32 #include "initlib.h"
33 #include "gtask_config.h"
34
35 #include "gtask_adapt.h"
36 #include "dynload.h"
37 #include "task_adaptor_pub.h"
38 #include "tee_property_inner.h"
39 #include "tee_ext_api.h"
40 #include "tee_task_exception.h"
41 #include "tee_ns_cmd_dispatch.h"
42 #include "tee_s_cmd_dispatch.h"
43 #include "tee_compat_check.h"
44 #include "tee_load_lib.h"
45 #include <ipclib_hal.h>
46 #include <usrsyscall_irq.h>
47 #include <sched.h>
48
49 #define GT_MSG_REV_SIZE 512
50
51 /* From 1970 to 2050 */
52 #define SYSTIME_SET_MAX ((2050U - 1970U) * 365U * 24U * 60U * 60U)
53 #define PHY_ADDR_HIGHER_BITS_INDEX 3
54 #define PHY_ADDR_LOWER_BITS_INDEX 1
55 #define SMC_CMD_RESULT_INDEX 0
56 #define SMC_CMD_ADDR_INDEX 1
57 #define SMC_CMD_TYPE_INDEX 2
58 #define SMC_CMD_ADDR_TRANS_INDEX 3
59
60 static kernel_shared_varibles_t g_k_variables;
61
62 static nwd_cmd_t *g_nwd_cmd = NULL;
63
64 /* It can be modified only by gtask, we can use it to check if the bitmap
65 * in g_nwd_cmd is right. */
66 static DECLEAR_BITMAP(cmd_doing_bitmap, MAX_SMC_CMD);
67
68 static bool g_systime_set_flag = false;
69
acquire_smc_buf_lock(uint32_t * lock)70 static void acquire_smc_buf_lock(uint32_t *lock)
71 {
72 int rc;
73 rc = disable_local_irq();
74 if (rc != 0)
75 tee_abort("disable_local_irq failed: %x\n", rc);
76 do
77 rc = __sync_bool_compare_and_swap(lock, 0, 1);
78 while (!rc);
79 asm volatile("dmb sy");
80 }
81
release_smc_buf_lock(uint32_t * lock)82 static void release_smc_buf_lock(uint32_t *lock)
83 {
84 int rc;
85 asm volatile("dmb sy");
86 *lock = 0;
87 asm volatile("dmb sy");
88 rc = enable_local_irq();
89 if (rc != 0)
90 tee_abort("enable_local_irq failed: %x\n", rc);
91 }
92
93 /*
94 * start internal service tasks
95 */
init_internal_tasks(void)96 static void init_internal_tasks(void)
97 {
98 /* load all internal tasks */
99 load_internal_task(LOAD_ALL_TASKS);
100
101 task_adapt_init();
102 }
103
104 /*
105 * setup smc cmd shared mem for TEE
106 */
init_smc_cmd_mem(void)107 static void init_smc_cmd_mem(void)
108 {
109 bool init_done = false;
110 int ret;
111
112 /* Setup the shared buffer for communication
113 * between tzdriver and global task */
114 while (!init_done) {
115 (void)ipc_msg_rcv(OS_WAIT_FOREVER, (uint32_t *)NULL, NULL, 0);
116
117 tlogd("initializing...\n");
118 /* the smc cmd mem setup params from REE received */
119 ret = tee_pull_kernel_variables(&g_k_variables);
120 if (ret != 0) {
121 tloge("pullKernelVariables failed...\n");
122 continue;
123 }
124
125 tlogd("init cmd: 0x%x 0x%x 0x%llx...\n", g_k_variables.params_stack[SMC_CMD_ADDR_INDEX],
126 g_k_variables.params_stack[SMC_CMD_TYPE_INDEX], g_k_variables.params_stack[SMC_CMD_ADDR_TRANS_INDEX]);
127
128 /* setup the smc cmd mem in TEE */
129 if (g_k_variables.params_stack[SMC_CMD_TYPE_INDEX] == CMD_TYPE_SECURE_CONFIG) {
130 /* init g_nwd_cmd */
131 paddr_t tmp_phy = g_k_variables.params_stack[PHY_ADDR_LOWER_BITS_INDEX] |
132 ((paddr_t)g_k_variables.params_stack[PHY_ADDR_HIGHER_BITS_INDEX] << SHIFT_OFFSET);
133 g_nwd_cmd = map_ns_cmd(tmp_phy);
134 if (g_nwd_cmd == NULL) {
135 tloge("map ns memory failed\n");
136 continue;
137 }
138
139 init_done = true;
140 }
141 }
142 }
143
setup_init_info(void)144 static void setup_init_info(void)
145 {
146 generate_teeos_compat_level(((uint32_t *)(void *)g_nwd_cmd->in),
147 COMPAT_LEVEL_BUF_LEN);
148 }
149
is_abort_cmd(const smc_cmd_t * cmd)150 bool is_abort_cmd(const smc_cmd_t *cmd)
151 {
152 if (cmd == NULL)
153 return false;
154
155 if (cmd->cmd_type == CMD_TYPE_GLOBAL && cmd->cmd_id == GLOBAL_CMD_ID_KILL_TASK)
156 return true;
157
158 return false;
159 }
160
restore_cmd_in(const smc_cmd_t * cmd)161 void restore_cmd_in(const smc_cmd_t *cmd)
162 {
163 uint32_t index;
164
165 if (cmd == NULL)
166 return;
167
168 index = cmd->event_nr;
169 if (index >= MAX_SMC_CMD) {
170 tloge("invalid idex: %u\n", index);
171 return;
172 }
173
174 acquire_smc_buf_lock(&g_nwd_cmd->smc_lock);
175 if (index != g_nwd_cmd->in[index].event_nr) {
176 tloge("event_nr not match, %u/%u\n", index, g_nwd_cmd->in[index].event_nr);
177 release_smc_buf_lock(&g_nwd_cmd->smc_lock);
178 return;
179 }
180
181 if (memcpy_s(&g_nwd_cmd->in[index], sizeof(smc_cmd_t), cmd, sizeof(smc_cmd_t)) != EOK)
182 tloge("copy restore cmd failed\n");
183 release_smc_buf_lock(&g_nwd_cmd->smc_lock);
184 }
185
get_last_in_cmd(smc_cmd_t * cmd)186 static int get_last_in_cmd(smc_cmd_t *cmd)
187 {
188 errno_t rc = EOK;
189 int ret = GT_ERR_END_CMD;
190 static uint32_t last_index = MAX_SMC_CMD;
191 uint32_t i = last_index;
192
193 acquire_smc_buf_lock(&g_nwd_cmd->smc_lock);
194 do {
195 if (i == MAX_SMC_CMD)
196 i = 0;
197 if (test_bit(i, g_nwd_cmd->in_bitmap) && !test_bit(i, g_nwd_cmd->doing_bitmap)) {
198 if (test_bit(i, cmd_doing_bitmap) && !is_abort_cmd(&g_nwd_cmd->in[i])) {
199 /* in this case, maybe the in_bitmap/doing_bitmap in g_nwd_cmd
200 * was modified by malicious, so we will skip this cmd. */
201 tloge("find a unreasonable in-cmd, cmd id=0x%x, cmd type=%u\n",
202 g_nwd_cmd->in[i].cmd_id, g_nwd_cmd->in[i].cmd_type);
203 set_bit(i, g_nwd_cmd->doing_bitmap);
204 /* skip this cmd */
205 continue;
206 }
207
208 rc = memcpy_s(cmd, sizeof(smc_cmd_t), &g_nwd_cmd->in[i], sizeof(smc_cmd_t));
209 if (rc != EOK) {
210 break;
211 }
212
213 /* check if cmd->event_nr is compatible the index in bitmap */
214 if (cmd->event_nr != i) {
215 tloge("it's a invalid cmd, event_nr/bitmap=%u/%u\n", cmd->event_nr, i);
216 set_bit(i, g_nwd_cmd->doing_bitmap);
217 /* skip this cmd */
218 continue;
219 }
220
221 __asm__ volatile("isb");
222 __asm__ volatile("dsb sy");
223 set_bit(i, g_nwd_cmd->doing_bitmap);
224 if (!is_abort_cmd(&g_nwd_cmd->in[i]))
225 set_bit(i, cmd_doing_bitmap);
226
227 last_index = i + 1;
228 ret = GT_ERR_OK;
229 break;
230 }
231 i++;
232 } while (i != last_index);
233 release_smc_buf_lock(&g_nwd_cmd->smc_lock);
234 if (rc != EOK) {
235 tloge("memcopy in cmd failed\n");
236 ret = GT_ERR_END_CMD;
237 }
238 if (cmd->event_nr >= MAX_SMC_CMD) {
239 tloge("invalid event_nr: %u\n", cmd->event_nr);
240 ret = GT_ERR_END_CMD;
241 }
242
243 return ret;
244 }
245
put_last_out_cmd(const smc_cmd_t * cmd)246 int put_last_out_cmd(const smc_cmd_t *cmd)
247 {
248 errno_t rc;
249
250 if (cmd == NULL)
251 return GT_ERR_END_CMD;
252
253 if (cmd->event_nr >= MAX_SMC_CMD) {
254 tloge("invalid event_nr: %u\n", cmd->event_nr);
255 return GT_ERR_END_CMD;
256 }
257 /* when ta session return to REE, need to umap ca2ta releation; otherwise when ca crash may kill wrong ta session */
258 if ((cmd->ret_val != TEE_PENDING) && (cmd->ret_val != TEE_PENDING2)) {
259 if (g_cur_session != NULL)
260 g_cur_session->cmd_in.ca_pid = 0;
261 }
262 acquire_smc_buf_lock(&g_nwd_cmd->smc_lock);
263
264 rc = memcpy_s(&g_nwd_cmd->out[cmd->event_nr], sizeof(smc_cmd_t), cmd, sizeof(smc_cmd_t));
265 if (rc != EOK) {
266 release_smc_buf_lock(&g_nwd_cmd->smc_lock);
267 tloge("memcpy out cmd failed\n");
268 return GT_ERR_END_CMD;
269 }
270 __asm__ volatile("isb");
271 __asm__ volatile("dsb sy");
272 set_bit(cmd->event_nr, g_nwd_cmd->out_bitmap);
273 clear_bit(cmd->event_nr, cmd_doing_bitmap);
274 release_smc_buf_lock(&g_nwd_cmd->smc_lock);
275
276 return GT_ERR_OK;
277 }
278
ns_cmd_response(smc_cmd_t * cmd)279 void ns_cmd_response(smc_cmd_t *cmd)
280 {
281 if (cmd == NULL)
282 return;
283
284 if (cmd->ret_val != TEE_PENDING) {
285 TEE_Result ret = copy_pam_to_src(cmd->cmd_id, false);
286 if (ret != TEE_SUCCESS)
287 cmd->ret_val = ret;
288
289 ret = unmap_ns_operation(cmd);
290 if (ret != TEE_SUCCESS)
291 tloge("ns cmd unmap ns fail:%08X\n", ret);
292 }
293
294 errno_t ret_i = put_last_out_cmd(cmd);
295 if (ret_i != GT_ERR_OK)
296 tloge("ns cmd put fail:%d\n", ret_i);
297 }
298
handle_time_adjust(const smc_cmd_t * cmd)299 TEE_Result handle_time_adjust(const smc_cmd_t *cmd)
300 {
301 TEE_Result ret;
302 tee_time_kernel time;
303 uint32_t param_type = 0;
304 TEE_Param *params = NULL;
305
306 if (cmd == NULL)
307 return TEE_ERROR_BAD_PARAMETERS;
308
309 if (g_systime_set_flag) {
310 tlogd("The time seems already been adjusted");
311 return TEE_SUCCESS;
312 }
313
314 if (cmd_global_ns_get_params(cmd, ¶m_type, ¶ms) != TEE_SUCCESS) {
315 tloge("cmd_global_ns_get_params failed");
316 return TEE_ERROR_BAD_PARAMETERS;
317 }
318
319 if (params == NULL)
320 return TEE_ERROR_BAD_PARAMETERS;
321
322 time.seconds = (int32_t)params->value.a;
323 time.millis = (int32_t)params->value.b;
324 if ((uint32_t)time.seconds <= SYSTIME_SET_MAX) {
325 #ifdef CONFIG_OFF_DRV_TIMER
326 ret = teecall_cap_time_sync(time.seconds, time.millis);
327 #else
328 ret = adjust_sys_time(&time);
329 #endif
330 if (ret != TEE_SUCCESS)
331 return ret;
332
333 g_systime_set_flag = true;
334 } else {
335 tloge("time adjust failed\n");
336 ret = TEE_ERROR_GENERIC;
337 }
338
339 return ret;
340 }
341
342 /*
343 * handle open_session cmds which is called from process_ta_common_cmd
344 * just for Complexity check.
345 * DO NOT USE this func in anyother situations.
346 */
347 extern struct service_struct *g_cur_service;
processs_opensession(smc_cmd_t * cmd,uint32_t cmd_type,uint32_t task_id,bool * async,const struct ta2ta_info_t * ta2ta_info)348 static TEE_Result processs_opensession(smc_cmd_t *cmd, uint32_t cmd_type, uint32_t task_id, bool *async,
349 const struct ta2ta_info_t *ta2ta_info)
350 {
351 TEE_Result ret;
352 uint32_t userid = 0;
353
354 ret = open_session(cmd, cmd_type, task_id, ta2ta_info);
355 if (ret == TEE_SUCCESS) {
356 *async = true;
357
358 if (g_cur_session->cmd_type == CMD_TYPE_NS_TO_SECURE) {
359 /*
360 * here restore cmd is to save cmd->context, if TA open session is stuck,
361 * we need context to find the stuck session to kill TA
362 */
363 restore_cmd_in(cmd);
364
365 userid = g_cur_session->cmd_in.uid / PER_USER_RANGE;
366 }
367
368 task_adapt_register_ta(g_cur_session->task_id, userid, g_cur_service->property.ssa_enum_enable,
369 &g_cur_service->property.uuid);
370 }
371
372 return ret;
373 }
374
375 /*
376 * handle both ca2ta and ta2ta cmds
377 */
process_ta_common_cmd(smc_cmd_t * cmd,uint32_t cmd_type,uint32_t task_id,bool * async,const struct ta2ta_info_t * ta2ta_info)378 TEE_Result process_ta_common_cmd(smc_cmd_t *cmd, uint32_t cmd_type, uint32_t task_id, bool *async,
379 const struct ta2ta_info_t *ta2ta_info)
380 {
381 TEE_Result ret;
382 bool sync = false;
383 uint32_t cmd_id;
384
385 if (cmd == NULL || async == NULL)
386 return TEE_ERROR_BAD_PARAMETERS;
387
388 cmd_id = cmd->cmd_id;
389 switch (cmd_id) {
390 case GLOBAL_CMD_ID_OPEN_SESSION:
391 if (cmd_type == CMD_TYPE_SECURE_TO_SECURE) {
392 tlogd("ta2ta is running\n");
393 if (g_cur_service == NULL) {
394 tloge("cur service is null\n");
395 return TEE_ERROR_BAD_PARAMETERS;
396 }
397 }
398 ret = processs_opensession(cmd, cmd_type, task_id, async, ta2ta_info);
399 break;
400 case GLOBAL_CMD_ID_CLOSE_SESSION:
401 ret = close_session(cmd, cmd_type, &sync);
402 if (ret == TEE_SUCCESS && false == sync)
403 *async = true;
404 break;
405 default:
406 ret = TEE_ERROR_INVALID_CMD;
407 break;
408 }
409
410 return ret;
411 }
412
tee_get_max_api_level(void)413 static uint32_t tee_get_max_api_level(void)
414 {
415 uint32_t value = 0;
416
417 if (TEE_GetPropertyAsU32(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.api_level", &value) != TEE_SUCCESS)
418 return TEE_MAX_API_LEVEL_CONFIG;
419
420 return value;
421 }
422
get_tee_version(const smc_cmd_t * cmd)423 TEE_Result get_tee_version(const smc_cmd_t *cmd)
424 {
425 unsigned int version;
426 uint32_t param_type = 0;
427 TEE_Param *params = NULL;
428
429 if (cmd == NULL)
430 return TEE_ERROR_BAD_PARAMETERS;
431
432 if (cmd_global_ns_get_params(cmd, ¶m_type, ¶ms) != TEE_SUCCESS) {
433 tloge("cmd_global_ns_get_params failed");
434 return TEE_ERROR_BAD_PARAMETERS;
435 }
436 if (params == NULL)
437 return TEE_ERROR_BAD_PARAMETERS;
438 if (TEE_PARAM_TYPE_GET(param_type, 0) != TEE_PARAM_TYPE_VALUE_OUTPUT) {
439 tloge("Bad expected parameter types: 0x%x\n", TEE_PARAM_TYPE_GET(param_type, 0));
440 return TEE_ERROR_BAD_PARAMETERS;
441 }
442 version = tee_get_max_api_level();
443 params->value.a = version;
444
445 return TEE_SUCCESS;
446 }
447
process_load_image(smc_cmd_t * cmd,bool * async)448 TEE_Result process_load_image(smc_cmd_t *cmd, bool *async)
449 {
450 TEE_Result ret;
451
452 ret = load_secure_file_image(cmd, async);
453 if (ret == TEE_ERROR_IMG_VERIFY_FAIL || ret == TEE_ERROR_IMG_PARSE_FAIL || ret == TEE_ERROR_IMG_ELF_LOAD_FAIL ||
454 ret == TEE_ERROR_IMG_DECRYPTO_FAIL)
455 tloge("load_secure_app_image failed\n");
456 return ret;
457 }
458
check_ns_cmd(smc_cmd_t * cmd)459 static int check_ns_cmd(smc_cmd_t *cmd)
460 {
461 TEE_Result ret;
462
463 /* check phy_addr in smc_cmd is in mailbox or not */
464 ret = check_cmd_in_mailbox_range(cmd);
465 if (ret != TEE_SUCCESS) {
466 tloge("mailbox check failed, cmd type=%u, cmd id=%u, ret = 0x%x\n",
467 cmd->cmd_type, cmd->cmd_id, ret);
468 goto error;
469 }
470
471 ret = init_ta_context(cmd);
472 if (ret != TEE_SUCCESS) {
473 tloge("init TA context failed, cmd type=%u, cmd id=%u, ret = 0x%x\n",
474 cmd->cmd_type, cmd->cmd_id, ret);
475 goto error;
476 }
477
478 return GT_ERR_OK;
479
480 error:
481 cmd->ret_val = ret;
482 if (put_last_out_cmd(cmd) != GT_ERR_OK)
483 tloge("put last out cmd fail\n");
484 return GT_ERR_END_CMD;
485 }
486
handle_ns_cmd(void)487 static int handle_ns_cmd(void)
488 {
489 int gt_err_ret;
490 smc_cmd_t cmd;
491
492 (void)memset_s(&cmd, sizeof(cmd), 0, sizeof(cmd));
493 /* get lastest smc cmd from smc mem */
494 gt_err_ret = get_last_in_cmd(&cmd);
495 if (gt_err_ret != GT_ERR_OK)
496 return gt_err_ret;
497
498 set_tee_return_origin(&cmd, TEE_ORIGIN_TEE);
499
500 if (cmd.cmd_type == CMD_TYPE_BUILDIN_AGENT)
501 return handle_service_agent_back_cmd(&cmd);
502
503 if (cmd.cmd_type == CMD_TYPE_TA_AGENT ||
504 cmd.cmd_type == CMD_TYPE_TA2TA_AGENT)
505 return handle_ta_agent_back_cmd(&cmd);
506
507 if (cmd.cmd_type == CMD_TYPE_GLOBAL && cmd.cmd_id == GLOBAL_CMD_ID_KILL_TASK)
508 return handle_kill_task(&cmd);
509
510 gt_err_ret = check_ns_cmd(&cmd);
511 if (gt_err_ret != GT_ERR_OK)
512 return gt_err_ret;
513
514 if (dispatch_ns_cmd(&cmd) != TEE_SUCCESS)
515 return GT_ERR_END_CMD;
516
517 return GT_ERR_OK;
518 }
519
is_cmd_in_unproceed(void)520 static int is_cmd_in_unproceed(void)
521 {
522 uint32_t i;
523 int ret = 0;
524
525 acquire_smc_buf_lock(&g_nwd_cmd->smc_lock);
526 for (i = 0; i < MAX_SMC_CMD; i++) {
527 if (test_bit(i, g_nwd_cmd->in_bitmap) && !test_bit(i, g_nwd_cmd->doing_bitmap)) {
528 ret = 1;
529 break;
530 }
531 }
532 release_smc_buf_lock(&g_nwd_cmd->smc_lock);
533
534 return ret;
535 }
536
gtask_main_init(void)537 static int32_t gtask_main_init(void)
538 {
539 if (ta_framework_init()) {
540 tloge("ta_framework init failed\n");
541 while (1)
542 (void)sched_yield();
543 }
544 init_internal_tasks();
545 #ifdef __aarch64__
546 tlogi("Gtask (64bit) Execute Successfully and jump to Linux kernel\n");
547 #else
548 tlogi("Gtask Execute Successfully and jump to Linux kernel\n");
549 #endif
550
551 init_smc_cmd_mem();
552 setup_init_info();
553
554 return GT_ERR_OK;
555 }
556
is_ns_cmd(uint32_t task_id,uint32_t back_cmd)557 bool is_ns_cmd(uint32_t task_id, uint32_t back_cmd)
558 {
559 (void)back_cmd;
560 if (taskid_to_pid(task_id) == SMCMGR_PID)
561 return true;
562 return false;
563 }
564
gtask_main(void)565 void gtask_main(void)
566 {
567 TEE_Result ret;
568 uint32_t back_cmd;
569 uint32_t task_id;
570 tlogd("global TEETaskEntry start\n");
571
572 if (gtask_main_init() != GT_ERR_OK)
573 return;
574
575 while (1) {
576 uint8_t buffer[GT_MSG_REV_SIZE] = { 0 };
577
578 reset_ta_context();
579 back_cmd = 0;
580 task_id = TASK_ID_NULL;
581
582 /* We still have incomming notifications, don't block yet */
583 if (is_cmd_in_unproceed()) {
584 if (ipc_msg_rcv_a(0, (uint32_t *)(&back_cmd), buffer, GT_MSG_REV_SIZE, &task_id)) {
585 task_id = SMCMGR_PID;
586 back_cmd = 0;
587 tlogd("Still having incoming notifications\n");
588 }
589 } else {
590 ret = ipc_msg_rcv_a(OS_WAIT_FOREVER, (uint32_t *)(&back_cmd), buffer, GT_MSG_REV_SIZE, &task_id);
591 if (ret != 0) {
592 tloge("global_task rcv error %x\n", ret);
593 continue;
594 }
595 }
596
597 tlogd("received back cmd =%x, task_id=%d\n", back_cmd, task_id);
598
599 /* tzdriver SIQ schedule is not needed NOW */
600 if (is_ns_cmd(task_id, back_cmd)) {
601 /* handle cmd from ree */
602 (void)handle_ns_cmd();
603 } else {
604 /* handle cmd from tee */
605 (void)handle_s_cmd(back_cmd, task_id, buffer, GT_MSG_REV_SIZE);
606 }
607 }
608 }
609