• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param, &param_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, &param, &param_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, &reg_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, &param_type, &param) != 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