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 <mem_ops.h>
15 #include <dlist.h>
16 #include "tee_log.h"
17 #include "tee_mem_mgmt_api.h"
18 #include "ta_framework.h"
19 #include "gtask_inner.h"
20 #include "agent_manager.h"
21 #include "service_manager.h"
22 #include "mem_manager.h"
23 #include "session_manager.h"
24 #include "tee_ext_api.h"
25 #include "tee_config.h"
26 #include "gtask_config_hal.h"
27 #include "mem_page_ops.h"
28 #include "securec.h"
29 #include "permsrv_api.h"
30 #include "gtask_adapt.h"
31 #include "task_adaptor_pub.h"
32 #include "tee_internal_task_pub.h"
33 #include "global_task.h"
34 #include "tee_task_exception.h"
35 #include <ipclib_hal.h>
36
37 #define AGENT_MAX 32
38 #define BITS_PER_BYTE 8
39 extern struct session_struct *g_cur_session;
40
41 static struct dlist_node g_agent_head;
42 static uint32_t g_agent_cnt;
43
44 /*
45 * service thread is a kthread 'CA' in tzdriver, it can be used
46 * to handle build-in agent(ssa) request while there's
47 * no source CA for agent request.
48 * cases as list:
49 * 1.TA open file but not close, ssa will do the close work in
50 * unregister work;
51 * 2.permission service call ssa;
52 * 3.tui service's release work if tui TA not release correctly.
53 */
54 struct service_thread_control {
55 smc_cmd_t cmd;
56 bool working;
57 struct dlist_node pending_head;
58 };
59 static struct service_thread_control g_svc_thread_ctrl;
60
61 struct service_thread_request {
62 struct dlist_node list;
63 uint32_t agent_id;
64 };
65
66 static TEE_Result tee_lock_agent(uint32_t agent_id, struct session_struct *session);
67 static void tee_unblock_agent(const struct session_struct *session, uint32_t cmd_id);
68 struct agent_control *find_agent(uint32_t agent_id);
69 static void tee_unlock_agent(struct agent_control *agent, uint32_t task_id);
70
agent_manager_init(void)71 void agent_manager_init(void)
72 {
73 dlist_init(&g_agent_head);
74 g_agent_cnt = 0;
75
76 g_svc_thread_ctrl.working = false;
77 dlist_init(&g_svc_thread_ctrl.pending_head);
78 }
79
is_system_agent(uint32_t agent_id)80 bool is_system_agent(uint32_t agent_id)
81 {
82 if (agent_id == TEE_FS_AGENT_ID || agent_id == TEE_MISC_AGENT_ID ||
83 agent_id == TEE_SOCKET_AGENT_ID || agent_id == TEE_SECLOAD_AGENT_ID ||
84 agent_id == TEE_VLTMM_AGENT_ID)
85 return true;
86 else
87 return false;
88 }
89
process_lock_agent(uint32_t agent_id,uint32_t task_id,struct service_struct * service,struct session_struct * session)90 static TEE_Result process_lock_agent(uint32_t agent_id, uint32_t task_id,
91 struct service_struct *service, struct session_struct *session)
92 {
93 if (is_system_agent(agent_id)) {
94 if (!check_system_agent_permission(task_id, agent_id)) {
95 tloge("task %s try to lock system agent:0x%x failed, permission denied\n",
96 service->name, agent_id);
97 tee_unblock_agent(session, TEE_INVALID_AGENT);
98 return TEE_ERROR_BAD_PARAMETERS;
99 }
100 }
101
102 TEE_Result ret = tee_lock_agent(agent_id, session);
103 if (ret == TEE_SUCCESS) {
104 tlogd("Succeed to get the lock of agent %u\n", agent_id);
105 tee_unblock_agent(session, TEE_AGENT_LOCK);
106 } else if (ret != TEE_ERROR_BUSY) {
107 tloge("Invalid agent %u\n", agent_id);
108 tee_unblock_agent(session, TEE_INVALID_AGENT);
109 } else {
110 tlogd("Agent %d was already locked, will wait\n", agent_id);
111 }
112
113 return ret;
114 }
115
process_unlock_agent(uint32_t agent_id,uint32_t task_id,struct session_struct * session)116 static TEE_Result process_unlock_agent(uint32_t agent_id, uint32_t task_id,
117 struct session_struct *session)
118 {
119 struct agent_control *agent = NULL;
120 struct session_struct *tmp_session = NULL;
121
122 /* 1. Unlock all the agents in the session locked agents list */
123 dlist_for_each_entry(agent, &session->locked_agents, struct agent_control, session_list) {
124 if (agent->id == agent_id) {
125 tlogd("Unlocking locked aggent %u\n", agent->id);
126 dlist_delete(&agent->session_list);
127 tee_unlock_agent(agent, task_id);
128 /* Unblock sending task */
129 tee_unblock_agent(session, TEE_AGENT_LOCK);
130 return TEE_SUCCESS;
131 }
132 }
133 tloge("Couldn't find agent to unlock!");
134
135 /* 2. delete the node in the waiting list , shouldn't come here normally */
136 agent = find_agent(agent_id);
137 if (agent == NULL) {
138 tloge("Failed to find the agent %u\n", agent_id);
139 tee_unblock_agent(session, TEE_INVALID_AGENT);
140 return TEE_ERROR_GENERIC;
141 }
142
143 while (!dlist_empty(&agent->waiting_sessions)) {
144 tmp_session = dlist_first_entry(&agent->waiting_sessions, struct session_struct, waiting_agent);
145 if (tmp_session == session) {
146 tloge("session %x haven't get lock but to unlock agent %x\n", session->task_id, agent->id);
147 dlist_delete(&session->waiting_agent);
148 }
149 }
150
151 tee_unblock_agent(session, TEE_AGENT_LOCK);
152
153 return TEE_ERROR_GENERIC;
154 }
155
process_get_agent_buffer(uint32_t agent_id,uint32_t task_id,const struct session_struct * session)156 static TEE_Result process_get_agent_buffer(uint32_t agent_id, uint32_t task_id,
157 const struct session_struct *session)
158 {
159 uint64_t buffer;
160 global_to_ta_msg buffer_msg = {0};
161 struct agent_control *control = NULL;
162
163 control = find_agent(agent_id);
164 if (control == NULL) {
165 tloge("Failed to find the agent 0x%x\n", agent_id);
166 goto agent_error;
167 }
168
169 /* check the agent has been locked by the session */
170 bool flag = (control->locked == true) && (control->locking_session == session);
171 if (!flag) {
172 tloge("this agent not locked by this session:agent=0x%x, task=0x%x\n", agent_id, task_id);
173 goto agent_error;
174 }
175
176 if (control->buffer == 0) {
177 if (task_map_ns_phy_mem(task_id, (uint64_t)control->phys_buffer, control->size, &buffer) != 0) {
178 tloge("map smc cmd operation params failed\n");
179 goto agent_error;
180 }
181 control->buffer = buffer;
182 }
183 buffer_msg.session_context = control->buffer;
184 buffer_msg.param_type = control->size;
185 buffer_msg.cmd_id = TEE_RETURN_AGENT_BUFFER;
186
187 TEE_Result ret = send_global2ta_msg(&buffer_msg, TA_GET_AGENT_BUFFER, task_id, NULL);
188 if (ret != TEE_SUCCESS)
189 tloge("get agent buffer msg send to ta failed:0x%x\n", ret);
190 return ret;
191
192 agent_error:
193 tloge("Failed to get the buffer of agent %u\n", agent_id);
194 buffer_msg.cmd_id = TEE_INVALID_AGENT;
195 buffer_msg.session_context = 0;
196 if (send_global2ta_msg(&buffer_msg, 0x0, task_id, NULL) != TEE_SUCCESS)
197 tloge("send agent msg to ta failed\n");
198 return TEE_ERROR_GENERIC;
199 }
200
set_agent_status(uint32_t agent_id,struct session_struct * session)201 static TEE_Result set_agent_status(uint32_t agent_id, struct session_struct *session)
202 {
203 struct agent_control *control = NULL;
204
205 control = find_agent(agent_id);
206 if (control != NULL) {
207 if (!control->locked || control->locking_session != session) {
208 tloge("control->locked=%d\n", control->locked);
209 return TEE_ERROR_GENERIC;
210 }
211 session->agent_pending = true;
212 return TEE_SUCCESS;
213 } else {
214 tloge("Failed to find the agent 0x%x\n", agent_id);
215 return TEE_ERROR_GENERIC;
216 }
217 }
218
find_agent(uint32_t agent_id)219 struct agent_control *find_agent(uint32_t agent_id)
220 {
221 struct agent_control *tmp_control = NULL;
222 uint32_t find_flag = 0;
223
224 dlist_for_each_entry(tmp_control, &g_agent_head, struct agent_control, list) {
225 if (tmp_control->id == agent_id) {
226 find_flag = 1;
227 break;
228 }
229 }
230 if (find_flag == 0) {
231 tlogd("Failed to find the agent 0x%x\n", agent_id);
232 return NULL;
233 }
234 tlogd("Found agent 0x%x \n", agent_id);
235 return tmp_control;
236 }
237
add_agent_control(uint32_t agent_id,paddr_t agent_buf_phys_addr,uint32_t agent_buf_size)238 static TEE_Result add_agent_control(uint32_t agent_id, paddr_t agent_buf_phys_addr, uint32_t agent_buf_size)
239 {
240 struct agent_control *tmp_control = TEE_Malloc(sizeof(struct agent_control), 0);
241 if (tmp_control == NULL) {
242 tloge("malloc for agent_control failed!\n");
243 return TEE_ERROR_OUT_OF_MEMORY;
244 }
245
246 dlist_insert_tail(&tmp_control->list, &g_agent_head);
247 dlist_init(&tmp_control->waiting_sessions);
248
249 tmp_control->id = agent_id;
250 tmp_control->locking_session = NULL;
251 tmp_control->locked = false;
252 tmp_control->buffer = 0;
253 tmp_control->phys_buffer = agent_buf_phys_addr;
254 tmp_control->size = agent_buf_size;
255
256 ++g_agent_cnt;
257
258 return TEE_SUCCESS;
259 }
260
check_agent_param(const smc_cmd_t * cmd,TEE_Param ** param,uint32_t * param_type)261 static TEE_Result check_agent_param(const smc_cmd_t *cmd, TEE_Param **param, uint32_t *param_type)
262 {
263 if (cmd == NULL)
264 return TEE_ERROR_BAD_PARAMETERS;
265
266 if (cmd_global_ns_get_params(cmd, param_type, param) != TEE_SUCCESS) {
267 tloge("Failed to get param\n");
268 return TEE_ERROR_GENERIC;
269 }
270
271 /* check params types */
272 if ((TEE_PARAM_TYPE_GET(*param_type, 0) != TEE_PARAM_TYPE_VALUE_INPUT) ||
273 (TEE_PARAM_TYPE_GET(*param_type, 1) != TEE_PARAM_TYPE_VALUE_INPUT)) {
274 tloge("Bad expected parameter types.\n");
275 return TEE_ERROR_BAD_PARAMETERS;
276 }
277 /* this condition should never happen here */
278 if (*param == NULL)
279 return TEE_ERROR_BAD_PARAMETERS;
280
281 return TEE_SUCCESS;
282 }
283
register_agent(const smc_cmd_t * cmd)284 TEE_Result register_agent(const smc_cmd_t *cmd)
285 {
286 uint32_t agent_id;
287 uint32_t param_type = 0;
288 TEE_Param *param = NULL;
289 paddr_t agent_buf_phys_addr;
290 uint32_t agent_buf_size;
291
292 if (g_agent_cnt >= AGENT_MAX) {
293 tloge("Failed to register agent, exceeds the max agents");
294 return TEE_ERROR_GENERIC;
295 }
296
297 TEE_Result ret = check_agent_param(cmd, ¶m, ¶m_type);
298 if (ret != TEE_SUCCESS)
299 return ret;
300
301 agent_buf_phys_addr = (paddr_t)(param[0].value.a | ((paddr_t)param[0].value.b << SHIFT_OFFSET));
302 agent_buf_size = param[1].value.a;
303 if (!in_mailbox_range(agent_buf_phys_addr, agent_buf_size)) {
304 tloge("agent buf is not in mailbox range!\n");
305 return TEE_ERROR_BAD_PARAMETERS;
306 }
307
308 agent_id = cmd->agent_id;
309 tlogd("register agent id = 0x%x, size=%u\n", agent_id, agent_buf_size);
310 #ifndef CONFIG_REGISTER_OTHER_AGENT
311 if (!is_system_agent(agent_id)) {
312 tloge("not system agent!\n");
313 return TEE_ERROR_GENERIC;
314 }
315 #endif
316 if ((agent_buf_size < AGENT_BUFF_SIZE) || (agent_buf_size > BITS_PER_BYTE * AGENT_BUFF_SIZE))
317 return TEE_ERROR_GENERIC;
318
319 // judge agent is exist
320 if (find_agent(agent_id)) {
321 tloge("agent whose id = 0x%x has been registered\n", agent_id);
322 goto fail0;
323 }
324
325 if (add_agent_control(agent_id, agent_buf_phys_addr, agent_buf_size) != TEE_SUCCESS)
326 goto fail0;
327
328 task_adapt_register_agent(agent_id);
329 return TEE_SUCCESS;
330
331 fail0:
332 return TEE_ERROR_GENERIC;
333 }
334
unregister_agent(const smc_cmd_t * cmd)335 TEE_Result unregister_agent(const smc_cmd_t *cmd)
336 {
337 struct agent_control *control = NULL;
338 struct session_struct *session = NULL;
339 uint32_t agent_id;
340 uint32_t param_type = 0;
341 TEE_Param *param = NULL;
342
343 if (g_agent_cnt == 0) {
344 tloge("Failed to unregister agent, no more agent exists!\n");
345 return TEE_ERROR_GENERIC;
346 }
347
348 TEE_Result ret = check_agent_param(cmd, ¶m, ¶m_type);
349 if (ret != TEE_SUCCESS)
350 return ret;
351
352 agent_id = cmd->agent_id;
353 tlogd("unregister agent id = 0x%x\n", agent_id);
354
355 if (is_system_agent(agent_id)) {
356 tloge("system agents not allowed to unregister\n");
357 return TEE_ERROR_GENERIC;
358 }
359 control = find_agent(agent_id);
360 if (control != NULL) {
361 if (control->locked) {
362 tloge("agent already had lock set, cannot be unregistered!\n");
363 return TEE_ERROR_GENERIC;
364 }
365 /* If we have waiting sessions then unlock them */
366 while (!dlist_empty(&control->waiting_sessions)) {
367 tlogd("Agent %u has blocked sessions\n", control->id);
368 session = dlist_first_entry(&control->waiting_sessions, struct session_struct, waiting_agent);
369 tee_unblock_agent(session, TEE_INVALID_AGENT);
370 tlogd("Agent %u unblock session task\n", session->task_id);
371 dlist_delete(&session->waiting_agent);
372 }
373
374 dlist_delete(&control->list);
375 TEE_Free(control);
376 control = NULL;
377 --g_agent_cnt;
378 }
379 return TEE_SUCCESS;
380 }
381
tee_get_agent_buffer(uint32_t agent_id,paddr_t * buffer,uint32_t * length)382 TEE_Result tee_get_agent_buffer(uint32_t agent_id, paddr_t *buffer, uint32_t *length)
383 {
384 struct agent_control *control = NULL;
385
386 if (buffer == NULL || length == NULL)
387 return TEE_ERROR_BAD_PARAMETERS;
388
389 control = find_agent(agent_id);
390 if (control == NULL) {
391 tloge("Failed to find the agent %u\n", agent_id);
392 return TEE_ERROR_GENERIC;
393 }
394 tlogd("Found agent %u \n", agent_id);
395 *buffer = control->phys_buffer;
396 *length = control->size;
397 return TEE_SUCCESS;
398 }
399
tee_unblock_agent(const struct session_struct * session,uint32_t cmd_id)400 static void tee_unblock_agent(const struct session_struct *session, uint32_t cmd_id)
401 {
402 global_to_ta_msg buffer_msg = { 0 };
403
404 if (session == NULL)
405 return;
406
407 buffer_msg.cmd_id = cmd_id;
408 if (send_global2ta_msg(&buffer_msg, TA_LOCK_ACK, session->task_id, NULL) != TEE_SUCCESS)
409 tloge("send msg failed\n");
410 }
411
add_waiting_session(struct session_struct * session,const struct agent_control * control)412 static void add_waiting_session(struct session_struct *session, const struct agent_control *control)
413 {
414 struct session_struct *sess_context = NULL;
415
416 if (session == NULL || control == NULL) {
417 tloge("session or control is null\n");
418 return;
419 }
420
421 dlist_for_each_entry(sess_context, &control->waiting_sessions, struct session_struct, waiting_agent) {
422 if (sess_context == session && sess_context->session_id == session->session_id) {
423 tloge("session already add into agent waiting_sessions list\n");
424 return;
425 }
426 }
427
428 dlist_insert_tail(&session->waiting_agent, &control->waiting_sessions);
429
430 return;
431 }
432
tee_lock_agent(uint32_t agent_id,struct session_struct * session)433 static TEE_Result tee_lock_agent(uint32_t agent_id, struct session_struct *session)
434 {
435 struct agent_control *control = NULL;
436
437 if (session == NULL)
438 return TEE_ERROR_BAD_PARAMETERS;
439
440 control = find_agent(agent_id);
441 if (control == NULL) {
442 tloge("Failed to find the agent %u\n", agent_id);
443 return TEE_ERROR_GENERIC;
444 }
445
446 if (control->locking_session == session)
447 return TEE_SUCCESS;
448
449 if (control->locked) {
450 /* Add the session in the agent's waiting list */
451 add_waiting_session(session, control);
452 return TEE_ERROR_BUSY;
453 }
454 control->locking_session = session;
455 control->locked = true;
456 dlist_insert_tail(&control->session_list, &session->locked_agents);
457 tlogd("Locked agent %u\n", agent_id);
458 return TEE_SUCCESS;
459 }
460
tee_unlock_agent(struct agent_control * agent,uint32_t task_id)461 static void tee_unlock_agent(struct agent_control *agent, uint32_t task_id)
462 {
463 struct session_struct *session = NULL;
464
465 if (agent == NULL)
466 return;
467
468 agent->locked = false;
469 agent->locking_session = NULL;
470
471 if (agent->buffer != 0) {
472 if (task_unmap(task_id, agent->buffer, agent->size) != 0)
473 tloge("unmap agent buffer error\n");
474
475 agent->buffer = 0;
476 }
477
478 /* If we have waiting sessions then unlock them */
479 if (!dlist_empty(&agent->waiting_sessions)) {
480 tlogd("Agent %d has blocked session\n", agent->id);
481 session = dlist_entry(agent->waiting_sessions.next, struct session_struct, waiting_agent);
482 tlogd("Agent %d unblock session task\n", session->task_id);
483
484 dlist_delete(&session->waiting_agent);
485 /* Need to lock the agent on the new session */
486 if (tee_lock_agent(agent->id, session) != TEE_SUCCESS) {
487 tloge("Failed to add new lock on agent!");
488 tee_unblock_agent(session, TEE_INVALID_AGENT);
489 } else {
490 tee_unblock_agent(session, TEE_AGENT_LOCK);
491 }
492 }
493 }
494
tee_unlock_agents(struct session_struct * session)495 void tee_unlock_agents(struct session_struct *session)
496 {
497 struct agent_control *agent = NULL;
498 struct agent_control *tmp = NULL;
499
500 if (session == NULL)
501 return;
502
503 /* Unlock all the agents in the session locked agents list */
504 dlist_for_each_entry_safe(agent, tmp, &session->locked_agents, struct agent_control, session_list) {
505 agent = dlist_first_entry(&session->locked_agents, struct agent_control, session_list);
506 tlogd("Unlocking locked aggent %u\n", agent->id);
507 dlist_delete(&agent->session_list);
508 tee_unlock_agent(agent, session->task_id);
509 }
510 }
511
512 /* caller needs to ensure dest_task_id is valid */
register_agent_buffer_to_task(uint32_t agent_id,uint32_t dest_task_id)513 void register_agent_buffer_to_task(uint32_t agent_id, uint32_t dest_task_id)
514 {
515 struct reg_agent_buf reg_msg;
516 struct agent_control *control = NULL;
517
518 control = find_agent(agent_id);
519 if (control != NULL) {
520 reg_msg.agentid = agent_id;
521 reg_msg.phys_addr = control->phys_buffer;
522 reg_msg.size = control->size;
523 uint32_t ret = ipc_msg_snd((uint32_t)TEE_TASK_REGISTER_AGENT, dest_task_id, ®_msg, sizeof(reg_msg));
524 if (ret != 0)
525 tloge("send reg agent msg to 0x%x failed, err=0x%x\n", dest_task_id, ret);
526 } else {
527 tloge("agent %u is not ready\n", agent_id);
528 }
529 }
530
531 enum LATE_INIT_INDEX {
532 FS_LATE_INIT = 0x1,
533 };
agent_late_init(const smc_cmd_t * cmd)534 TEE_Result agent_late_init(const smc_cmd_t *cmd)
535 {
536 uint32_t param_type = 0;
537 TEE_Param *param = NULL;
538 uint32_t index;
539
540 if (cmd == NULL)
541 return TEE_ERROR_BAD_PARAMETERS;
542
543 if (cmd_global_ns_get_params(cmd, ¶m_type, ¶m) != 0)
544 return TEE_ERROR_GENERIC;
545
546 /* check params types */
547 if (TEE_PARAM_TYPE_GET(param_type, 0) != TEE_PARAM_TYPE_VALUE_INPUT) {
548 tloge("Bad expected parameter types.\n");
549 return TEE_ERROR_BAD_PARAMETERS;
550 }
551 /* this condition should never happen here */
552 if (param == NULL)
553 return TEE_ERROR_BAD_PARAMETERS;
554
555 index = param[0].value.a;
556 if (index == FS_LATE_INIT)
557 fs_agent_late_init();
558
559 return TEE_SUCCESS;
560 }
561
set_service_thread_cmd(const smc_cmd_t * cmd,bool * async)562 TEE_Result set_service_thread_cmd(const smc_cmd_t *cmd, bool *async)
563 {
564 if (cmd == NULL || async == NULL)
565 return TEE_ERROR_BAD_PARAMETERS;
566
567 if (memcpy_s(&g_svc_thread_ctrl.cmd, sizeof(smc_cmd_t), cmd, sizeof(smc_cmd_t)) != EOK) {
568 tloge("memcpy cmd failed\n");
569 return TEE_ERROR_GENERIC;
570 }
571
572 *async = true;
573 return TEE_SUCCESS;
574 }
575
get_service_thread_cmd(void)576 static smc_cmd_t *get_service_thread_cmd(void)
577 {
578 if (g_svc_thread_ctrl.working == true) {
579 tloge("agent svc thread is working, wait until last request done\n");
580 return NULL;
581 }
582 g_svc_thread_ctrl.working = true;
583
584 return &g_svc_thread_ctrl.cmd;
585 }
586
service_thread_request_enqueue(uint32_t agent_id)587 static TEE_Result service_thread_request_enqueue(uint32_t agent_id)
588 {
589 struct service_thread_request *request = NULL;
590
591 request = TEE_Malloc(sizeof(struct service_thread_request), ZERO);
592 if (request == NULL) {
593 tloge("alloc request failed\n");
594 return TEE_ERROR_OUT_OF_MEMORY;
595 }
596
597 request->agent_id = agent_id;
598 dlist_insert_tail(&request->list, &g_svc_thread_ctrl.pending_head);
599
600 return TEE_SUCCESS;
601 }
602
service_thread_request_dequeue(const smc_cmd_t * in,smc_cmd_t * out)603 bool service_thread_request_dequeue(const smc_cmd_t *in, smc_cmd_t *out)
604 {
605 struct service_thread_request *request = NULL;
606 bool check_stat = (in == NULL || out == NULL);
607
608 if (check_stat)
609 return false;
610
611 /* if it's a agent response from svc thread */
612 if (in->event_nr != g_svc_thread_ctrl.cmd.event_nr)
613 return false;
614
615 if (dlist_empty(&g_svc_thread_ctrl.pending_head)) {
616 g_svc_thread_ctrl.working = false;
617 return false;
618 }
619
620 if (memcpy_s(out, sizeof(smc_cmd_t), &g_svc_thread_ctrl.cmd, sizeof(smc_cmd_t)) != EOK) {
621 tloge("memcpy_s failed\n");
622 return false;
623 }
624 request = dlist_first_entry(&g_svc_thread_ctrl.pending_head, struct service_thread_request, list);
625 if (request == NULL) {
626 tloge("request is null\n");
627 return false;
628 }
629 out->agent_id = request->agent_id;
630
631 dlist_delete(&request->list);
632 TEE_Free(request);
633
634 return true;
635 }
636
put_agent_request_cmd(smc_cmd_t * cmd,uint32_t cmd_type,uint32_t agent_id)637 static void put_agent_request_cmd(smc_cmd_t *cmd, uint32_t cmd_type, uint32_t agent_id)
638 {
639 cmd->ret_val = TEE_PENDING2;
640 cmd->agent_id = agent_id;
641 cmd->cmd_type = cmd_type;
642
643 int ret = put_last_out_cmd(cmd);
644 if (ret != GT_ERR_OK)
645 tloge("put agent req cmd fail:%d, cmd type=%u, agent id=0x%x\n", ret, cmd_type, agent_id);
646 }
647
handle_ta_agent_back_cmd(smc_cmd_t * cmd)648 int32_t handle_ta_agent_back_cmd(smc_cmd_t *cmd)
649 {
650 TEE_Result ret;
651 uint32_t cmd_type;
652
653 if (cmd == NULL)
654 return GT_ERR_END_CMD;
655
656 if (cmd->cmd_type == CMD_TYPE_TA2TA_AGENT) {
657 /* hanle TA2TA->AGENT back cmd */
658 cmd_type = CMD_TYPE_SECURE_TO_SECURE;
659 ret = init_ta2ta_agent_context(cmd);
660 if (ret != TEE_SUCCESS) {
661 tloge("init TA2TA agent back context failed, ret = 0x%x\n", ret);
662 goto ta_dead_chk;
663 }
664
665 /*
666 * we restore cmd_in here for GLOBAL_CMD_ID_KILL_TASK, because:
667 * 1. ca invoke ta1, tzdriver will put smc_cmd_1 in g_cmd_data->in
668 * 2. ta1 invoke ta2, using smc_cmd_2
669 * 3. when ta2 call agent, gtask will put_last_out_cmd, which will put smc_cmd_2 to g_cmd_data->out
670 * 4. tzdriver will copy g_cmd_data->out to g_cmd_data->in when agent back
671 * 5. after that, if kill ca, tzdriver will send GLOBAL_CMD_ID_KILL_TASK to gtask, reuse g_cmd_data->in,
672 * which is smc_cmd_2, that will cause kill ta1 fail. actually, we need reuse smc_cmd_1
673 */
674 struct service_struct *service = NULL;
675 struct session_struct *session = NULL;
676 if (g_cur_session != NULL && find_task(g_cur_session->ta2ta_from_taskid, &service, &session)) {
677 if (session != NULL)
678 restore_cmd_in(&(session->cmd_in));
679 }
680 } else {
681 /* hanle CA2TA->AGENT back cmd */
682 cmd_type = CMD_TYPE_NS_TO_SECURE;
683 ret = init_ta_context(cmd);
684 if (ret != TEE_SUCCESS) {
685 tloge("init TA context failed, ret = 0x%x\n", ret);
686 goto ta_dead_chk;
687 }
688 }
689
690 if (g_cur_session == NULL || !g_cur_session->agent_pending) {
691 tloge("session is null or is not in agent pending status, agent id=0x%x\n", cmd->agent_id);
692 goto error;
693 }
694
695 g_cur_session->agent_pending = false;
696 /* reset cmd_type & agent_id for reuse cmd like TEE_PENDING */
697 cmd->cmd_type = g_cur_session->cmd_in.cmd_type;
698 cmd->agent_id = 0;
699
700 /* resume app task that pending on message */
701 ret = start_ta_task(cmd, cmd_type);
702 if (ret != TEE_SUCCESS) {
703 tloge("resume agent pending error:%x\n", ret);
704 goto error;
705 }
706 return GT_ERR_OK;
707 ta_dead_chk:
708 /* TA may has exception, service is dead */
709 if (ret == TEE_ERROR_SERVICE_NOT_EXIST) {
710 if (ta_exception_handle_agent_ack(cmd) == TEE_SUCCESS)
711 return GT_ERR_OK;
712 }
713 error:
714 set_tee_return(cmd, ret);
715 ns_cmd_response(cmd);
716 return GT_ERR_END_CMD;
717 }
718
719 /* handle service agent(e.g. ssa) back cmd */
handle_service_agent_back_cmd(const smc_cmd_t * cmd)720 int32_t handle_service_agent_back_cmd(const smc_cmd_t *cmd)
721 {
722 uint32_t agent_task_id;
723 uint32_t *agent_status = NULL;
724 uint32_t caller_task_id;
725 uint32_t ret;
726
727 if (cmd == NULL)
728 return GT_ERR_END_CMD;
729
730 if (!is_agent_response(cmd->agent_id, &agent_task_id, &caller_task_id, &agent_status)) {
731 tloge("unexcepted buildin agent back cmd, agent id=0x%x\n", cmd->agent_id);
732 return GT_ERR_END_CMD;
733 }
734
735 if ((*agent_status) != TEE_PENDING2) {
736 tloge("unexcepted buildint agent status, agent id=0x%x\n", cmd->agent_id);
737 return GT_ERR_END_CMD;
738 }
739
740 ret = ipc_msg_snd(TEE_TASK_AGENT_SMC_ACK, agent_task_id, NULL, 0);
741 if (ret != 0)
742 tloge("send msg to agent:%u fail:%u\n", agent_task_id, ret);
743
744 smc_cmd_t cmd_out;
745 struct service_struct *service = NULL;
746 struct session_struct *session = NULL;
747
748 *agent_status = 0;
749 if (find_task(caller_task_id, &service, &session))
750 session->agent_pending = false;
751 else if (find_service_by_task_id(caller_task_id) == NULL)
752 /* TA may be crash, service is dead */
753 ta_exception_handle_buildin_agent_ack(caller_task_id);
754
755 if (service_thread_request_dequeue(cmd, &cmd_out)) {
756 tlogi("agent svc thread process pending work\n");
757 put_agent_request_cmd(&cmd_out, CMD_TYPE_BUILDIN_AGENT, cmd_out.agent_id);
758 }
759 return GT_ERR_OK;
760 }
761
762 /* handle service agent(e.g. ssa) request */
handle_service_agent_request(uint32_t caller_task_id,uint32_t agent_id,uint32_t * agent_status)763 static TEE_Result handle_service_agent_request(uint32_t caller_task_id,
764 uint32_t agent_id, uint32_t *agent_status)
765 {
766 smc_cmd_t cmd;
767 smc_cmd_t *cmd_in = NULL;
768 struct service_struct *service = NULL;
769 struct session_struct *session = NULL;
770
771 if (!find_task(caller_task_id, &service, &session)) {
772 tlogd("can't find ta session by task id %u, will use svc thread\n", caller_task_id);
773 cmd_in = get_service_thread_cmd();
774 if (cmd_in == NULL) {
775 if (service_thread_request_enqueue(agent_id) != TEE_SUCCESS) {
776 tloge("svc request enqueue failed\n");
777 return TEE_ERROR_GENERIC;
778 }
779 *agent_status = TEE_PENDING2;
780 return TEE_SUCCESS;
781 }
782 } else {
783 cmd_in = &session->cmd_in;
784 session->agent_pending = true;
785 }
786
787 errno_t rc = memcpy_s(&cmd, sizeof(cmd), cmd_in, sizeof(*cmd_in));
788 if (rc != EOK) {
789 tloge("memcpy cmd failed, rc=%d, line:%d.\n", rc, __LINE__);
790 return TEE_ERROR_GENERIC;
791 }
792
793 *agent_status = TEE_PENDING2;
794 put_agent_request_cmd(&cmd, CMD_TYPE_BUILDIN_AGENT, agent_id);
795 return TEE_SUCCESS;
796 }
797
handle_ta_agent_request(uint32_t agent_id,struct session_struct * session)798 static TEE_Result handle_ta_agent_request(uint32_t agent_id, struct session_struct *session)
799 {
800 smc_cmd_t cmd;
801 TEE_Result ret;
802 uint32_t agent_type;
803 global_to_ta_msg entry_msg = {0};
804
805 session_set_cancelable(false);
806 /*
807 * Need to return to NWD for agent process then we resume,
808 * TA is waiting, nwd will send smc back
809 */
810 if (set_agent_status(agent_id, session) == TEE_SUCCESS) {
811 agent_type = (session->cmd_type == CMD_TYPE_SECURE_TO_SECURE) ?
812 CMD_TYPE_TA2TA_AGENT : CMD_TYPE_TA_AGENT;
813
814 (void)memcpy_s(&cmd, sizeof(cmd), &session->cmd_in, sizeof(session->cmd_in));
815 put_agent_request_cmd(&cmd, agent_type, agent_id);
816 return TEE_SUCCESS;
817 }
818
819 /* TA tried to call invalid agent */
820 entry_msg.cmd_id = TEE_INVALID_AGENT;
821 ret = send_global2ta_msg(&entry_msg, 0x0, session->task_id, NULL);
822 if (ret != TEE_SUCCESS)
823 tloge("msg send to ta failed:0x%x\n", ret);
824 return ret;
825 }
826
handle_agent_pending_msg(uint32_t agent_id,uint32_t task_id,struct session_struct * session)827 static TEE_Result handle_agent_pending_msg(uint32_t agent_id, uint32_t task_id, struct session_struct *session)
828 {
829 uint32_t caller_task_id;
830 uint32_t *agent_status = NULL;
831
832 if (is_service_agent_request(task_id, &caller_task_id, &agent_status))
833 return handle_service_agent_request(caller_task_id, agent_id, agent_status);
834 else
835 return handle_ta_agent_request(agent_id, session);
836 }
837
838 /*
839 * this function do not support 32-bit TA or service sends agent request to 64-bit gtask,
840 * we should solve this problem later
841 */
handle_agent_request(uint32_t cmd_id,uint32_t task_id,const uint8_t * msg_buf,uint32_t msg_size)842 int32_t handle_agent_request(uint32_t cmd_id, uint32_t task_id, const uint8_t *msg_buf, uint32_t msg_size)
843 {
844 errno_t rc;
845 TEE_Result ret;
846 uint32_t caller_task_id;
847 struct ta_to_global_msg msg;
848 struct service_struct *service = NULL;
849 struct session_struct *session = NULL;
850
851 if (msg_buf == NULL || msg_size < sizeof(msg)) {
852 tloge("invalid msg param, msg size %u\n", msg_size);
853 return GT_ERR_END_CMD;
854 }
855
856 rc = memcpy_s(&msg, sizeof(msg), msg_buf, sizeof(msg));
857 if (rc != EOK) {
858 tloge("memcpy agent request msg failed, rc=%d, line:%d\n", rc, __LINE__);
859 return GT_ERR_END_CMD;
860 }
861
862 caller_task_id = task_id;
863
864 if (find_task(caller_task_id, &service, &session) == false) {
865 tloge("find task 0x%x failed, agent request %u failed\n", caller_task_id, cmd_id);
866 return GT_ERR_END_CMD;
867 }
868
869 switch (cmd_id) {
870 case TA_LOCK_AGENT:
871 ret = process_lock_agent(msg.agent_id, caller_task_id, service, session);
872 break;
873 case TA_UNLOCK_AGENT:
874 ret = process_unlock_agent(msg.agent_id, caller_task_id, session);
875 break;
876 case TA_GET_AGENT_BUFFER:
877 ret = process_get_agent_buffer(msg.agent_id, caller_task_id, session);
878 break;
879 case TEE_TASK_AGENT_SMC_CMD:
880 ret = handle_agent_pending_msg(msg.agent_id, caller_task_id, session);
881 break;
882 default:
883 ret = TEE_ERROR_BAD_PARAMETERS;
884 tloge("invalid agent request cmd %u\n", cmd_id);
885 break;
886 }
887 if (ret != TEE_SUCCESS)
888 return GT_ERR_END_CMD;
889
890 return GT_ERR_OK;
891 }
892