• 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 <dlist.h>
15 #include "tee_log.h"
16 #include "tee_mem_mgmt_api.h"
17 #include "ta_framework.h"
18 #include "gtask_inner.h"
19 #include "session_manager.h"
20 #include "service_manager.h"
21 #include "agent_manager.h"
22 #include "mem_manager.h"
23 #include "tee_ext_api.h"
24 #include "tee_config.h"
25 #include "gtask_config_hal.h"
26 #include "securec.h"
27 
28 #include "gtask_adapt.h"
29 #include "dynload.h"
30 #include "task_adaptor_pub.h"
31 #include "tee_task.h"
32 #include "tee_task_exception.h"
33 #include <ipclib_hal.h>
34 
35 #define DEFAULT_EVENT_NR 0xffffffff
36 
37 struct service_struct *g_cur_service = (struct service_struct *)NULL;
38 struct session_struct *g_cur_session = (struct session_struct *)NULL;
39 
40 /* static funs declare */
41 int32_t find_service(const TEE_UUID *uuid, uint32_t service_index, struct service_struct **entry);
42 void set_session_context(smc_cmd_t *cmd, uint32_t service_index, uint32_t session_id);
43 TEE_Result process_close_session_entry(struct service_struct **service, struct session_struct **session);
44 void process_close_ta2ta_target_sessions(uint32_t from_taskid, uint32_t level);
45 
get_cur_session(void)46 struct session_struct *get_cur_session(void)
47 {
48     return g_cur_session;
49 }
50 
get_cur_service(void)51 struct service_struct *get_cur_service(void)
52 {
53     return g_cur_service;
54 }
55 
call_ta_invoke_close_session(const smc_cmd_t * cmd,uint32_t cmd_type,uint32_t cmd_id,global_to_ta_msg * entry_msg)56 static TEE_Result __attribute__((noinline)) call_ta_invoke_close_session(const smc_cmd_t *cmd, uint32_t cmd_type, uint32_t cmd_id,
57                                                global_to_ta_msg *entry_msg)
58 {
59     TEE_Result ret;
60 
61     if (cmd->ret_val == TEE_PENDING2 || cmd->ret_val == TEE_PENDING)
62         return TEE_SUCCESS;
63 
64     entry_msg->session_id      = set_session_context_bit(g_cur_service->index, g_cur_session->session_id);
65     entry_msg->session_context = g_cur_session->session_context;
66     entry_msg->cmd_id          = cmd->cmd_id;
67     entry_msg->dev_id          = cmd->dev_file_id;
68     entry_msg->started         = cmd->started;
69 
70     if (cmd_id == CALL_TA_CLOSE_SESSION) {
71         if (g_cur_service->session_count == 1 && g_cur_service->property.keep_alive == false)
72             entry_msg->last_session = 1;
73     }
74     if (cmd_type == CMD_TYPE_NS_TO_SECURE) {
75         ret = cmd_ns_get_params(g_cur_session->task_id, cmd, &entry_msg->param_type, &entry_msg->params);
76         if (ret != TEE_SUCCESS) {
77             tloge("map ns params error\n");
78             return ret;
79         }
80         entry_msg->session_type = SESSION_FROM_CA;
81     } else {
82         ret = cmd_secure_get_params(g_cur_session->task_id, cmd, &entry_msg->param_type, &entry_msg->params);
83         if (ret != TEE_SUCCESS) {
84             tloge("map secure params error\n");
85             return ret;
86         }
87         entry_msg->session_type = SESSION_FROM_TA;
88     }
89 
90     return ret;
91 }
92 
set_init_msg_prop(const struct ta_property * in,ta_property_t_64 * out)93 static void set_init_msg_prop(const struct ta_property *in, ta_property_t_64 *out)
94 {
95     out->uuid            = in->uuid;
96     out->stack_size      = in->stack_size;
97     out->heap_size       = in->heap_size;
98     out->single_instance = in->single_instance;
99     out->multi_session   = in->multi_session;
100     out->keep_alive      = in->keep_alive;
101     out->ssa_enum_enable = in->ssa_enum_enable;
102     out->other_buff      = (uintptr_t)in->other_buff;
103     out->other_len       = in->other_len;
104 }
105 
check_and_process_init_build(ta_init_msg * init_msg,global_to_ta_msg * entry_msg,bool * flag)106 static TEE_Result check_and_process_init_build(ta_init_msg *init_msg,
107                                                global_to_ta_msg *entry_msg, bool *flag)
108 {
109     TEE_Result ret;
110 
111     if (g_cur_service->init_build == 0) {
112         tlogd("Do service initial build!\n");
113         *flag = true;
114         /*
115          * Once the first msg CALL_TA_OPEN_SESSION_INIT send
116          * to TA, TA will do init work like clear bss etc,
117          * So we need make sure the other session of the TA will
118          * not send msg with init_build=0 again.
119          */
120         g_cur_service->init_build = 1;
121 
122         set_init_msg_prop(&g_cur_service->property, &(init_msg->prop));
123         init_msg->login_method = g_cur_session->login_method;
124 
125         ret = send_ta_init_msg(init_msg, g_cur_service->ta_64bit, CALL_TA_OPEN_SESSION_INIT,
126                                g_cur_session->task_id);
127         if (ret != TEE_SUCCESS) {
128             tloge("send open session init msg to session[%s] failed:0x%x\n", g_cur_session->name, ret);
129             return ret;
130         }
131         g_cur_session->wait_ta_back_msg = true;
132 
133         return TEE_SUCCESS;
134     }
135 
136     if (g_cur_service->session_count == 1)
137         entry_msg->first_session = 1;
138 
139     return TEE_SUCCESS;
140 }
141 
async_call_ta_entry(const smc_cmd_t * cmd,uint32_t cmd_type,uint32_t cmd_id)142 TEE_Result async_call_ta_entry(const smc_cmd_t *cmd, uint32_t cmd_type, uint32_t cmd_id)
143 {
144     global_to_ta_msg entry_msg = { 0 };
145     ta_init_msg init_msg       = { 0 };
146     TEE_Result ret;
147     bool flag = false;
148 
149     if (cmd == NULL || g_cur_session == NULL)
150         return TEE_ERROR_BAD_PARAMETERS;
151 
152     /*
153      * If the TA has agent pending command but the incomming command
154      * does not come from the agent then we cannot forward the command
155      * because the TA is single threaded!
156      */
157     if (g_cur_session->agent_pending) {
158         tloge("session %s is busy, command %u rejected\n", g_cur_session->name, cmd_id);
159         return TEE_ERROR_BUSY;
160     }
161 
162     g_cur_session->login_method = cmd->login_method;
163 
164     switch (cmd_id) {
165     case CALL_TA_OPEN_SESSION:
166         ret = check_and_process_init_build(&init_msg, &entry_msg, &flag);
167         if (flag)
168             return ret;
169         /* fall-through */
170     case CALL_TA_INVOKE_CMD:
171     case CALL_TA_CLOSE_SESSION:
172         ret = call_ta_invoke_close_session(cmd, cmd_type, cmd_id, &entry_msg);
173         if (ret) {
174             tloge("call ta invoke_cmd or close_session error\n");
175             return ret;
176         }
177         break;
178     default:
179         tloge("invalid asyn cmd id %u\n", cmd_id);
180         return TEE_ERROR_GENERIC;
181     }
182 
183     tlogd("send to TA(0x%x): cmd=0x%x, session_id=0x%x\n", g_cur_session->task_id, cmd_id, entry_msg.session_id);
184     ret = send_global2ta_msg(&entry_msg, cmd_id, g_cur_session->task_id, NULL);
185     if (ret != TEE_SUCCESS) {
186         tloge("msg send to ta failed:0x%x\n", ret);
187         return ret;
188     }
189 
190     g_cur_session->wait_ta_back_msg = true;
191     return TEE_SUCCESS;
192 }
193 
session_set_cancelable(bool cancelable)194 void session_set_cancelable(bool cancelable)
195 {
196     if (g_cur_session != NULL)
197         g_cur_session->cancelable = cancelable;
198 }
199 
find_session_with_dev_file_id(uint32_t session_id,uint32_t dev_file_id,const struct service_struct * srv)200 struct session_struct *find_session_with_dev_file_id(uint32_t session_id, uint32_t dev_file_id,
201     const struct service_struct *srv)
202 {
203     struct session_struct *sess_context = NULL;
204 
205     if (srv == NULL)
206         return NULL;
207 
208     dlist_for_each_entry (sess_context, &srv->session_head, struct session_struct, session_list) {
209         if ((sess_context->session_id == session_id) && (sess_context->cmd_in.dev_file_id == dev_file_id))
210             return sess_context;
211     }
212     return NULL;
213 }
214 
reset_ta_context(void)215 void reset_ta_context(void)
216 {
217     g_cur_service = (struct service_struct *)NULL;
218     g_cur_session = (struct session_struct *)NULL;
219 }
220 
set_tee_return_origin(smc_cmd_t * cmd,TEE_Result ret_origin)221 void set_tee_return_origin(smc_cmd_t *cmd, TEE_Result ret_origin)
222 {
223     if (cmd == NULL)
224         return;
225 
226     cmd->err_origin = ret_origin;
227 }
228 
set_tee_return(smc_cmd_t * cmd,TEE_Result ret_val)229 void set_tee_return(smc_cmd_t *cmd, TEE_Result ret_val)
230 {
231     if (cmd == NULL)
232         return;
233 
234     cmd->ret_val = ret_val;
235 }
236 
init_ta_service_session(const smc_cmd_t * cmd)237 static TEE_Result init_ta_service_session(const smc_cmd_t *cmd)
238 {
239     const TEE_UUID *uuid = NULL;
240     int32_t service_index;
241 
242     uuid = (const TEE_UUID *)(uintptr_t)cmd->uuid;
243 
244     if ((service_index = find_service(uuid, service_index_of_context(cmd->context), &g_cur_service)) == -1) {
245         tloge("service not found uuid = %x-%x\n", uuid->timeLow, uuid->timeMid);
246         return TEE_ERROR_SERVICE_NOT_EXIST;
247     }
248 
249     g_cur_session = find_session_with_dev_file_id(session_id_of_context(cmd->context), cmd->dev_file_id, g_cur_service);
250     if ((g_cur_session == NULL) && (cmd->cmd_type != CMD_TYPE_GLOBAL)) {
251         tloge("session[%u] not exist in service[%s]\n", session_id_of_context(cmd->context), g_cur_service->name);
252         return TEE_ERROR_SESSION_NOT_EXIST;
253     }
254 
255     return TEE_SUCCESS;
256 }
257 
init_ta_context(const smc_cmd_t * cmd)258 TEE_Result init_ta_context(const smc_cmd_t *cmd)
259 {
260     if (cmd == NULL)
261         return TEE_ERROR_BAD_PARAMETERS;
262 
263     TEE_Result ret = init_ta_service_session(cmd);
264     if (ret != 0) {
265         tloge("init ta service session error:%x\n", ret);
266         return ret;
267     }
268 
269     return TEE_SUCCESS;
270 }
271 
init_ta2ta_session(const smc_cmd_t * cmd)272 static TEE_Result init_ta2ta_session(const smc_cmd_t *cmd)
273 {
274     g_cur_session = find_session_with_dev_file_id(session_id_of_context(cmd->context), cmd->dev_file_id, g_cur_service);
275     if ((g_cur_session == NULL) && (cmd->cmd_type != CMD_TYPE_GLOBAL))
276         return TEE_ERROR_SESSION_NOT_EXIST;
277 
278     return TEE_SUCCESS;
279 }
280 
ta2ta_call_back(uint32_t task_id)281 static int ta2ta_call_back(uint32_t task_id)
282 {
283     struct service_struct *serv = NULL;
284     struct session_struct *sess = NULL;
285     uint32_t pre_task           = task_id;
286     uint32_t level;
287 
288     do {
289         if (!find_task(pre_task, &serv, &sess)) {
290             tloge("find service fail taskid:%u\n", pre_task);
291             return -1;
292         }
293 
294         if (serv == g_cur_service) {
295             tloge("WRONG! ta2ta cannot call back\n");
296             return -1;
297         }
298         tlogd("sess level:%d\n", sess->ta2ta_level);
299 
300         pre_task = sess->ta2ta_from_taskid;
301         level    = sess->ta2ta_level;
302     } while (level > 0);
303 
304     return 0;
305 }
306 
307 
check_ta2ta_context(uint32_t task_id)308 static TEE_Result check_ta2ta_context(uint32_t task_id)
309 {
310     /* check if there is a loop call */
311     if (ta2ta_call_back(task_id) != 0) {
312         tloge("ta2ta call in wrong state\n");
313         return TEE_ERROR_GENERIC;
314     }
315 
316     /* We don't allow TA2TA session calls from TAs that did not initiate the session */
317     if (g_cur_session != NULL) {
318         if (g_cur_session->ta2ta_from_taskid != task_id) {
319             tloge("receive invalid ta2ta call from task 0x%x\n", task_id);
320             return TEE_ERROR_SESSION_NOT_EXIST;
321         }
322     }
323     return TEE_SUCCESS;
324 }
325 
init_ta2ta_service(const smc_cmd_t * cmd)326 static TEE_Result init_ta2ta_service(const smc_cmd_t *cmd)
327 {
328     const TEE_UUID *uuid = NULL;
329 
330     uuid = (const TEE_UUID *)(uintptr_t)cmd->uuid;
331     if (find_service(uuid, service_index_of_context(cmd->context), &g_cur_service) == -1) {
332         tloge("find second service fail\n");
333         return TEE_ERROR_SERVICE_NOT_EXIST;
334     }
335 
336     return TEE_SUCCESS;
337 }
338 
init_ta2ta_service_session(const smc_cmd_t * cmd)339 static TEE_Result init_ta2ta_service_session(const smc_cmd_t *cmd)
340 {
341     TEE_Result ret;
342     ret = init_ta2ta_service(cmd);
343     if (ret != TEE_SUCCESS) {
344         tloge("init ta2ta service error:%x\n", ret);
345         return ret;
346     }
347 
348     ret = init_ta2ta_session(cmd);
349     if (ret != TEE_SUCCESS) {
350         tloge("init ta2ta session error:%x\n", ret);
351         return ret;
352     }
353 
354     return ret;
355 }
356 
init_ta2ta_agent_context(smc_cmd_t * cmd)357 TEE_Result init_ta2ta_agent_context(smc_cmd_t *cmd)
358 {
359     uint32_t ret_val;
360     TEE_Result ret;
361     struct service_struct *service = NULL;
362     struct session_struct *session = NULL;
363 
364     if (cmd == NULL)
365         return TEE_ERROR_BAD_PARAMETERS;
366 
367     ret_val = cmd->ret_val;
368 
369     ret = init_ta2ta_service_session(cmd);
370     if (ret != TEE_SUCCESS)
371         return ret;
372 
373     if ((g_cur_session != NULL) && (g_cur_session->cmd != NULL)) {
374         /* agent response will use a new cmd index, updata the event_nr in original cmd */
375         if (g_cur_session->cmd->event_nr != cmd->event_nr) {
376             /*
377              * The ta2ta cmd was already initialized so we need to change out cmd to point to the
378              * mapped pointer instead of the current cmd
379              */
380             if (!find_task(g_cur_session->ta2ta_from_taskid, &service, &session)) {
381                 tloge("can't find session for ta2ta_from_taskid taskid=0x%x\n", g_cur_session->ta2ta_from_taskid);
382                 return TEE_ERROR_GENERIC;
383             }
384 
385             session->cmd_in.event_nr     = cmd->event_nr;
386             session->cmd_in.ca_pid       = cmd->ca_pid;
387             g_cur_session->cmd->event_nr = cmd->event_nr;
388             g_cur_session->cmd->ca_pid   = cmd->ca_pid;
389         }
390         cmd = g_cur_session->cmd;
391         if (cmd != NULL) {
392             cmd->ret_val = ret_val;
393         } else {
394             /* this never happen */
395             tloge("out cmd is null\n");
396             return TEE_ERROR_GENERIC;
397         }
398     }
399 
400     return TEE_SUCCESS;
401 }
402 
init_ta2ta_context(smc_cmd_t * cmd,uint64_t ta_cmd,uint32_t task_id)403 TEE_Result init_ta2ta_context(smc_cmd_t *cmd, uint64_t ta_cmd, uint32_t task_id)
404 {
405     TEE_Result ret;
406     struct service_struct *service = NULL;
407     struct session_struct *session = NULL;
408 
409     if (cmd == NULL || ta_cmd == 0)
410         return TEE_ERROR_BAD_PARAMETERS;
411 
412     /* Need to remap the command id incomming from the secure ta2ta call */
413     if (map_secure_operation(ta_cmd, cmd, task_id) != TEE_SUCCESS)
414         return TEE_ERROR_OUT_OF_MEMORY;
415 
416     if (!find_task(task_id, &service, &session)) {
417         tloge("can't find session for ta2ta call taskid=%u\n", task_id);
418         return TEE_ERROR_GENERIC;
419     }
420     /* TA2TA call will reuse the src TA's CA's cmd_index */
421     cmd->ca_pid   = session->cmd_in.ca_pid;
422     cmd->event_nr = session->cmd_in.event_nr;
423     cmd->dev_file_id = session->cmd_in.dev_file_id;
424     tlogd("ta2ta call update, service_id=%u, session_id=%u, ca_pid=%u, event_nr=%u, dev_file_id=%u\n",
425         service->index, session->session_id, cmd->ca_pid, cmd->event_nr, cmd->dev_file_id);
426 
427     ret = init_ta2ta_service_session(cmd);
428     if (ret != TEE_SUCCESS)
429         return ret;
430     ret = check_ta2ta_context(task_id);
431     if (ret != TEE_SUCCESS)
432         return ret;
433 
434     /*
435      * If it's the first time we map the ta2ta command then set the internals of the session
436      * to point to it
437      */
438     if (g_cur_session != NULL) {
439         g_cur_session->cmd = &g_cur_session->cmd_in;
440         if (memcpy_s(&g_cur_session->cmd_in, sizeof(g_cur_session->cmd_in), cmd, sizeof(*cmd)) != TEE_SUCCESS) {
441             tloge("memcpy cmd_in failed\n");
442             return TEE_ERROR_GENERIC;
443         }
444     }
445 
446     return TEE_SUCCESS;
447 }
448 
init_session_context(uint32_t task_id,struct service_struct ** service,struct session_struct ** session)449 TEE_Result init_session_context(uint32_t task_id,
450     struct service_struct **service, struct session_struct **session)
451 {
452     if (!find_task(task_id, &g_cur_service, &g_cur_session))
453         return TEE_ERROR_SESSION_NOT_EXIST;
454 
455     if (service != NULL)
456         *service = g_cur_service;
457     if (session != NULL)
458         *session = g_cur_session;
459 
460     return TEE_SUCCESS;
461 }
462 
set_session_context(smc_cmd_t * cmd,uint32_t service_index,uint32_t session_id)463 void set_session_context(smc_cmd_t *cmd, uint32_t service_index, uint32_t session_id)
464 {
465     if (cmd == NULL)
466         return;
467     cmd->context = set_session_context_bit(service_index, session_id);
468 
469     tlogd("set session id = 0x%x\n", cmd->context);
470 }
471 
get_session_id(void)472 int32_t get_session_id(void)
473 {
474     int32_t id = ERROR_SESSION_ID;
475     uint32_t i;
476 
477     for (i = 0; i < MAX_SESSION_ID; i++) {
478         if ((g_cur_service->session_bitmap[get_index_by_uint32(i)] & (uint32_t)(0x1 << get_bit_by_uint32(i))) == 0) {
479             id = (int32_t)(i + 1);
480             break;
481         }
482     }
483 
484     return id;
485 }
486 
join_session_task_name(const char * service_name,struct session_struct * session)487 int join_session_task_name(const char *service_name, struct session_struct *session)
488 {
489     if (service_name == NULL || session == NULL)
490         return -1;
491 
492     if (snprintf_s(session->name, SERVICE_NAME_MAX + SESSION_ID_LEN,
493         SERVICE_NAME_MAX + SESSION_ID_LEN - 1, "%u%s", session->session_id,
494         service_name) < 0) {
495         tloge("snprintf_s session name failed\n");
496         return -1;
497     }
498 
499     return 0;
500 }
501 
start_ta_task(const smc_cmd_t * cmd,uint32_t cmd_type)502 TEE_Result start_ta_task(const smc_cmd_t *cmd, uint32_t cmd_type)
503 {
504     TEE_Result ret;
505 
506     if (cmd == NULL)
507         return TEE_ERROR_BAD_PARAMETERS;
508 
509     if (g_cur_session != NULL &&
510         memcpy_s(&g_cur_session->cmd_in, sizeof(smc_cmd_t), cmd, sizeof(smc_cmd_t))) {
511         tloge("memcpy_s cmd_in failed\n");
512         return TEE_ERROR_GENERIC;
513     }
514 
515     ret = async_call_ta_entry(cmd, cmd_type, CALL_TA_INVOKE_CMD);
516     return ret;
517 }
518 
ta_task_init(struct tsk_init_param * task_param)519 static void ta_task_init(struct tsk_init_param *task_param)
520 {
521     if (task_param == NULL)
522         return;
523 
524     task_param->task_prior = DEFAULT_TASK_PRIO;
525     task_param->task_name  = g_cur_session->name;
526     task_param->que_num    = DEFAULT_MSG_QUEUE_NUM;
527 
528     task_param->uuid.timeLow          = g_cur_service->property.uuid.timeLow;
529     task_param->uuid.timeMid          = g_cur_service->property.uuid.timeMid;
530     task_param->uuid.timeHiAndVersion = g_cur_service->property.uuid.timeHiAndVersion;
531     int i;
532     for (i = 0; i < NODE_LEN; i++)
533         task_param->uuid.clockSeqAndNode[i] = g_cur_service->property.uuid.clockSeqAndNode[i];
534 }
535 
get_ta2ta_level(uint32_t cmd_type,uint32_t task_id,uint32_t * level)536 static int get_ta2ta_level(uint32_t cmd_type, uint32_t task_id, uint32_t *level)
537 {
538     struct service_struct *serv = NULL;
539     struct session_struct *sess = NULL;
540 
541     if (level == NULL) {
542         tloge("get ta2ta level invalid param\n");
543         return -1;
544     }
545 
546     if (cmd_type == CMD_TYPE_NS_TO_SECURE) {
547         tlogd("type is ns to secure\n");
548         *level = 0;
549         return 0;
550     }
551 
552     if (find_task(task_id, &serv, &sess) == 0) {
553         tloge("cannot find caller ta. something wrong\n");
554         return -1;
555     }
556 
557     if (sess->ta2ta_level >= MAX_TA2TA_LEVEL) {
558         tloge("get caller ta2ta_level:%u, cannot open other ta\n", sess->ta2ta_level);
559         return -1;
560     }
561 
562     *level = sess->ta2ta_level + 1;
563 
564     return 0;
565 }
566 
add_session_to_ta2ta_list(uint32_t cmd_type,uint32_t caller_task_id,struct session_struct * cur_sess)567 static void add_session_to_ta2ta_list(uint32_t cmd_type, uint32_t caller_task_id, struct session_struct *cur_sess)
568 {
569     struct service_struct *caller_serv = NULL;
570     struct session_struct *caller_sess = NULL;
571 
572     if (cmd_type == CMD_TYPE_NS_TO_SECURE)
573         return;
574 
575     if (find_task(caller_task_id, &caller_serv, &caller_sess) == 0) {
576         tloge("find caller task 0x%x failed\n", caller_task_id);
577         return;
578     }
579     dlist_insert_tail(&(cur_sess->child_ta_sess_list), &caller_sess->child_ta_sess_head);
580 }
581 
release_srvc_gc(bool handle_ref_cnt,int sre_ret)582 static void release_srvc_gc(bool handle_ref_cnt, int sre_ret)
583 {
584     /*
585      * for built-in service, we only need to care about session node,
586      * don't need to care about service node
587      */
588     if (is_build_in_service(&(g_cur_service->property.uuid)))
589         return;
590 
591     if (handle_ref_cnt)
592         decr_ref_cnt(g_cur_service);
593 
594     /* when service thread is blocked and session count is 0, we release service thread */
595     if (sre_ret == TIMEOUT_FAIL_RET) {
596         tloge("%s is blocked and session count is %u\n",
597             g_cur_service->name, g_cur_service->session_count);
598         if (g_cur_service->session_count == 0) {
599             process_release_service(g_cur_service, TA_REGION_RELEASE);
600             g_cur_service = NULL;
601         }
602         return;
603     }
604 
605     /*
606      * for non built-in TA, in following case, we release service node and service thread
607      * 1. keepalive is false;
608      * 2. keepalive is true, first open session;
609      */
610     if (g_cur_service->session_count == 0 && g_cur_service->ref_cnt == 0) {
611         bool need_release_service =
612             (!g_cur_service->property.keep_alive ||
613             (g_cur_service->property.keep_alive && g_cur_service->first_open));
614         if (need_release_service) {
615             process_release_service(g_cur_service, TA_REGION_RELEASE);
616             g_cur_service = NULL;
617         }
618     }
619 }
620 
621 /* for normal TA and built-in TA, we need to release session node and service node. */
create_task_fail_gc(bool handle_ref_cnt,int sre_ret)622 static void create_task_fail_gc(bool handle_ref_cnt, int sre_ret)
623 {
624     if (g_cur_session != NULL) {
625         CLR_BIT(g_cur_service->session_bitmap[get_index_by_uint32(g_cur_session->session_id - 1)],
626                 get_bit_by_uint32(g_cur_session->session_id - 1));
627         release_pam_node(g_cur_session->pam_node);
628         dlist_delete(&g_cur_session->session_list);
629         dlist_delete(&g_cur_session->child_ta_sess_list);
630         TEE_Free(g_cur_session);
631         g_cur_session = NULL;
632     }
633     release_srvc_gc(handle_ref_cnt, sre_ret);
634 }
635 
open_session_fail_gc(void)636 static int open_session_fail_gc(void)
637 {
638     if (g_cur_service->session_count > 0) {
639         g_cur_service->session_count--;
640         uint32_t session_id = set_session_context_bit(g_cur_service->index, g_cur_session->session_id);
641         int32_t ret = sre_task_delete_ex(g_cur_session->task_id, false, session_id);
642         if (ret != SUCC_RET)
643             tloge("task del fail errorno =%d\n", ret);
644         return ret;
645     }
646     tloge("here session count never be 0, some bad things must happen\n");
647     return SUCC_RET;
648 }
649 
add_new_session_into_list(struct session_struct ** session,uint32_t * session_id,uint32_t ta2ta_level)650 TEE_Result add_new_session_into_list(struct session_struct **session, uint32_t *session_id,
651                                      uint32_t ta2ta_level)
652 {
653     if (session == NULL || session_id == NULL || g_cur_service == NULL)
654         return TEE_ERROR_GENERIC;
655 
656     /* session id will never be bigger than SESSION_MAX=8 */
657     int32_t tmp_id = get_session_id();
658     if (tmp_id == ERROR_SESSION_ID) {
659         tloge("failed to get session id, return TEE_ERROR_SESSION_MAXIMUM\n");
660         return TEE_ERROR_SESSION_MAXIMUM;
661     }
662     *session_id = (uint32_t)tmp_id;
663 
664     *session = TEE_Malloc(sizeof(struct session_struct), 0);
665     if (*session == NULL)
666         return TEE_ERROR_OUT_OF_MEMORY;
667 
668     (*session)->agent_pending = false;
669     (*session)->ta2ta_level   = ta2ta_level;
670     (*session)->session_id    = *session_id;
671 
672     if (join_session_task_name(g_cur_service->name, *session) != 0) {
673         tloge("join session task name failed\n");
674         if (*session != NULL) {
675             TEE_Free(*session);
676             *session = NULL;
677         }
678         return TEE_ERROR_GENERIC;
679     }
680 
681     dlist_init(&(*session)->session_list);
682     SET_BIT(g_cur_service->session_bitmap[get_index_by_uint32(*session_id - 1)],
683             get_bit_by_uint32(*session_id - 1));
684     dlist_insert_tail(&(*session)->session_list, &g_cur_service->session_head);
685     g_cur_session = *session;
686 
687     /* Init list of locked agents */
688     dlist_init(&(*session)->locked_agents);
689     dlist_init(&(*session)->map_mem);
690 
691     (*session)->session_status = TA_STATUS_NORMAL;
692     dlist_init(&(*session)->child_ta_sess_head);
693     dlist_init(&(*session)->child_ta_sess_list);
694 
695     return TEE_SUCCESS;
696 }
697 
create_session(smc_cmd_t * cmd,uint32_t cmd_type,uint32_t caller_id,bool handle_ref_cnt)698 static TEE_Result create_session(smc_cmd_t *cmd, uint32_t cmd_type, uint32_t caller_id, bool handle_ref_cnt)
699 {
700     TEE_Result ret = TEE_ERROR_GENERIC;
701     uint32_t task_id;
702     uint32_t session_id;
703     uint32_t level;
704     struct tsk_init_param task_init_param;
705     struct session_struct *session = NULL;
706 
707     if (get_ta2ta_level(cmd_type, caller_id, &level) != 0)
708         goto generic_fail;
709 
710     ret = add_new_session_into_list(&session, &session_id, level);
711     if (ret != TEE_SUCCESS)
712         goto generic_fail;
713 
714     ta_task_init(&task_init_param);
715     int32_t sre_ret = sre_task_create(&task_init_param, &task_id);
716     if (sre_ret != 0) {
717         tloge("create task %s fail : errorno = 0x%x\n", g_cur_service->name, sre_ret);
718         ret = TEE_ERROR_GENERIC;
719         goto create_task_fail;
720     }
721     session->task_id            = task_id;
722     session->ta2ta_from_taskid  = caller_id;
723     add_session_to_ta2ta_list(cmd_type, caller_id, session);
724     session->wait_ta_back_msg = false;
725     set_session_context(cmd, g_cur_service->index, session_id);
726     g_cur_service->session_count++;
727     tlogd("create session-%d: %s: 0x%x\n", session_id, g_cur_service->name, task_id);
728     return ret;
729 
730 create_task_fail:
731     create_task_fail_gc(handle_ref_cnt, sre_ret);
732     return ret;
733 generic_fail:
734     release_srvc_gc(handle_ref_cnt, SUCC_RET);
735     return ret;
736 }
737 
check_session_accessible()738 static TEE_Result check_session_accessible()
739 {
740     if (is_system_service(g_cur_service)) {
741         tloge("session is denied\n");
742         return TEE_ERROR_ACCESS_DENIED;
743     }
744 
745     if (g_cur_service->property.multi_session == false && g_cur_service->session_count > 0) {
746         struct session_struct *tmp_session =
747             dlist_entry(&(g_cur_service->session_head.next), struct session_struct, session_list);
748 
749         if (true == tmp_session->cancelable) {
750             tloge("session[%s] is busy\n", tmp_session->name);
751             return TEE_ERROR_BUSY;
752         } else {
753             tloge("service[%s] only 1 session can be opened\n", g_cur_service->name);
754             return TEE_ERROR_ACCESS_CONFLICT;
755         }
756     }
757 
758     return TEE_SUCCESS;
759 }
760 
is_session_valid(const smc_cmd_t * cmd,uint32_t cmd_type)761 static TEE_Result is_session_valid(const smc_cmd_t *cmd, uint32_t cmd_type)
762 {
763     (void)cmd;
764     (void)cmd_type;
765 
766     return check_session_accessible();
767 }
768 
check_and_release_ta_elf(void)769 static void check_and_release_ta_elf(void)
770 {
771     if (!is_build_in_service(&(g_cur_service->property.uuid)) && g_cur_service->elf_state == ELF_EXIST) {
772         if (sre_release_dynamic_region(&g_cur_service->property.uuid, TA_REGION_RELEASE) != 0)
773             tloge("release elf failed\n");
774     }
775 }
776 
do_resc_release_work(bool handle_ref_cnt)777 static void do_resc_release_work(bool handle_ref_cnt)
778 {
779     /* after session is created, elf and ref_cnt can be released. */
780     if (handle_ref_cnt) {
781         decr_ref_cnt(g_cur_service);
782         tlogd("service: %s, session count is %d ref_cnt-- is %d\n", g_cur_service->name, g_cur_service->session_count,
783               g_cur_service->ref_cnt);
784     }
785     check_and_release_ta_elf();
786 }
787 
check_handle_ref_cnt(uint32_t cmd_type,const struct ta2ta_info_t * ta2ta_info)788 static bool check_handle_ref_cnt(uint32_t cmd_type, const struct ta2ta_info_t *ta2ta_info)
789 {
790     /*
791      * 1.ta2ta and ta elf is not loaded by secfile load agent
792      * 2.built-in service;
793      * don't need to handle ref_cnt
794      */
795     bool check_value = (cmd_type == CMD_TYPE_SECURE_TO_SECURE && ta2ta_info->is_load_worked == false) ||
796                         is_build_in_service(&((g_cur_service->property).uuid));
797     if (check_value)
798         return false;
799     return true;
800 }
801 
open_session(smc_cmd_t * cmd,uint32_t cmd_type,uint32_t caller_id,const struct ta2ta_info_t * ta2ta_info)802 TEE_Result open_session(smc_cmd_t *cmd, uint32_t cmd_type, uint32_t caller_id,
803                         const struct ta2ta_info_t *ta2ta_info)
804 {
805     TEE_Result ret;
806     int sre_ret;
807 
808     bool check_value = (g_cur_service == NULL || cmd == NULL);
809     if (check_value)
810         return TEE_ERROR_BAD_PARAMETERS;
811 
812     check_value = (cmd_type == CMD_TYPE_SECURE_TO_SECURE && ta2ta_info == NULL);
813     if (check_value) {
814         tloge("ta2ta info is null, something bad must happened\n");
815         return TEE_ERROR_GENERIC;
816     }
817 
818     bool handle_ref_cnt = check_handle_ref_cnt(cmd_type, ta2ta_info);
819 
820     ret = is_session_valid(cmd, cmd_type);
821     if (ret != TEE_SUCCESS) {
822         create_task_fail_gc(handle_ref_cnt, SUCC_RET);
823         return ret;
824     }
825     ret = create_session(cmd, cmd_type, caller_id, handle_ref_cnt);
826     if (ret != TEE_SUCCESS) {
827         tloge("create session of service failed:0x%x\n", ret);
828         return ret;
829     }
830 
831     g_cur_session->cmd_type = cmd_type;
832     if (memcpy_s(&g_cur_session->cmd_in, sizeof(g_cur_session->cmd_in), cmd, sizeof(*cmd)) != EOK) {
833         ret = TEE_ERROR_GENERIC;
834         goto open_fail;
835     }
836     ret = async_call_ta_entry(cmd, cmd_type, CALL_TA_OPEN_SESSION);
837     if (is_err_ret(ret)) {
838         tloge("Call TA Entry of service failed: 0x%x\n", ret);
839         goto open_fail;
840     }
841     g_cur_session->ta2ta_handle =
842         ((cmd_type != CMD_TYPE_SECURE_TO_SECURE) ? (INVALID_SESSION_HANDLE) : (ta2ta_info->handle));
843     do_resc_release_work(handle_ref_cnt);
844     return ret;
845 open_fail:
846     sre_ret = open_session_fail_gc();
847     create_task_fail_gc(handle_ref_cnt, sre_ret);
848     return ret;
849 }
850 
release_session(struct service_struct * service,struct session_struct * session)851 int32_t release_session(struct service_struct *service, struct session_struct *session)
852 {
853     int32_t sre_ret;
854     uint32_t session_id;
855     struct service_struct *backup_service = NULL;
856     struct session_struct *backup_session = NULL;
857 
858     if (service == NULL || session == NULL)
859         return (int32_t)TEE_ERROR_BAD_PARAMETERS;
860 
861     task_adapt_unregister_ta(&service->property.uuid, session->task_id);
862     service->session_count--;
863 
864     backup_service = g_cur_service;
865     backup_session = g_cur_session;
866     g_cur_service  = service;
867     g_cur_session  = session;
868     session_id     = set_session_context_bit(service->index, session->session_id);
869     sre_ret = sre_task_delete_ex(session->task_id, service->is_service_dead, session_id);
870     if (sre_ret != SUCC_RET)
871         tloge("task del error fail 1\n");
872 
873     release_pam_node(session->pam_node);
874     task_del_mem_region(&(session->map_mem), service->is_service_dead);
875 
876     CLR_BIT(service->session_bitmap[get_index_by_uint32(session->session_id - 1)],
877             get_bit_by_uint32(session->session_id - 1));
878     dlist_delete(&session->session_list);
879     dlist_delete(&session->child_ta_sess_list);
880 
881     /* Lose the locks held on agents */
882     tee_unlock_agents(session);
883 
884     g_cur_service = backup_service;
885     g_cur_session = backup_session;
886     /* If we are on a waiting list remove it */
887     if (session->waiting_agent.next != NULL)
888         dlist_delete(&session->waiting_agent);
889 
890     /*
891      * We are the last one to go, next
892      * open session will need to reinit
893      */
894     TEE_Free(session);
895 
896     return sre_ret;
897 }
898 
process_close_session_entry(struct service_struct ** service_in,struct session_struct ** session_in)899 TEE_Result process_close_session_entry(struct service_struct **service_in, struct session_struct **session_in)
900 {
901     struct service_struct *service = NULL;
902     struct session_struct *session = NULL;
903     bool check_status              = ((service_in == NULL) || (session_in == NULL));
904     int32_t sre_ret;
905 
906     if (check_status)
907         return TEE_ERROR_BAD_PARAMETERS;
908 
909     service = *service_in;
910     session = *session_in;
911 
912     check_status = ((service == NULL) || (session == NULL));
913     if (check_status)
914         return TEE_ERROR_BAD_PARAMETERS;
915 
916     sre_ret = release_session(service, session);
917     session     = NULL;
918     *session_in = NULL;
919 
920     /* when service thread is blocked and session count is 0, we release service thread */
921     if (sre_ret == TIMEOUT_FAIL_RET) {
922         tloge("%s is blocked and session count is %u\n", service->name,
923             service->session_count);
924         if (service->session_count == 0) {
925             if (!is_build_in_service(&(service->property.uuid))) {
926                     process_release_service(service, TA_REGION_RELEASE);
927                     service     = NULL;
928                     *service_in = NULL;
929             } else {
930                     service->init_build = 0;
931                     recycle_srvc_thread(service);
932             }
933         }
934         return TEE_SUCCESS;
935     }
936 
937     if (service->session_count == 0 && service->ref_cnt == 0) {
938         if (!is_build_in_service(&(service->property.uuid))) {
939             /* for non-keepalive TA, we release service node and service thread */
940             if (!service->property.keep_alive) {
941                 process_release_service(service, TA_REGION_RELEASE);
942                 service     = NULL;
943                 *service_in = NULL;
944             }
945         } else {
946             /*
947              * for non-keepalive TA, we need to recycle service thread
948              * and set init_build to 0 for restarting process.
949              */
950             if (!service->property.keep_alive) {
951                 service->init_build = 0;
952                 recycle_srvc_thread(service);
953             }
954         }
955     }
956     return TEE_SUCCESS;
957 }
958 
do_target_session_close(struct session_struct * sess_context,struct service_struct * service_entry,uint32_t from_taskid,uint32_t level)959 static bool do_target_session_close(struct session_struct *sess_context, struct service_struct *service_entry,
960                                     uint32_t from_taskid, uint32_t level)
961 {
962     TEE_Result ret;
963     struct session_struct *sess = sess_context;
964     struct service_struct *srvc = service_entry;
965 
966     if (sess->ta2ta_from_taskid == from_taskid) {
967         tlogd("ta2ta targert call session : %u\n", sess->session_id);
968 
969         /* if level == MAX_TA2TA_LEVEL, it is the last level session */
970         if (level < MAX_TA2TA_LEVEL) {
971             tlogi("close next TA session level:%u\n", level);
972             process_close_ta2ta_target_sessions(sess->task_id, (level + 1));
973         }
974 
975         ret = process_close_session_entry(&srvc, &sess);
976         if (ret != TEE_SUCCESS)
977             tloge("close ta2ta object session failed: errorno =0x%x\n", ret);
978         /*
979          * once service or session is released,
980          * we need to reiterate service list, otherwise,
981          * service_tmp or sess_tmp point to mem which has been released.
982          */
983         if (srvc == NULL || sess == NULL) {
984             tlogd("goto retry service list\n");
985             return true;
986         }
987     }
988     return false;
989 }
990 
process_close_ta2ta_target_sessions(uint32_t from_taskid,uint32_t level)991 void process_close_ta2ta_target_sessions(uint32_t from_taskid, uint32_t level)
992 {
993     bool need_reiterate                  = false;
994     struct session_struct *sess_context  = NULL;
995     struct session_struct *sess_tmp      = NULL;
996     struct service_struct *service_entry = NULL;
997     struct service_struct *service_tmp   = NULL;
998 
999     /* Go through all the services and all sessions */
1000     do {
1001         dlist_for_each_entry_safe (service_entry, service_tmp, get_service_head_ptr(),
1002                                    struct service_struct, service_list) {
1003             if (service_entry->is_service_dead)
1004                 continue;
1005             need_reiterate = false;
1006             tlogd("iterate service %s \n", service_entry->name);
1007             dlist_for_each_entry_safe (sess_context, sess_tmp, &service_entry->session_head, struct session_struct,
1008                                 session_list) {
1009                 tlogd("iterate session %u \n", sess_context->session_id);
1010                 need_reiterate = do_target_session_close(sess_context, service_entry, from_taskid, level);
1011                 if (need_reiterate)
1012                     break;
1013             }
1014             if (need_reiterate)
1015                 break;
1016         }
1017     } while (need_reiterate);
1018 }
1019 
process_close_session(void)1020 TEE_Result process_close_session(void)
1021 {
1022     TEE_Result ret;
1023 
1024     if (g_cur_session == NULL)
1025         return TEE_ERROR_BAD_PARAMETERS;
1026 
1027     process_close_ta2ta_target_sessions(g_cur_session->task_id, g_cur_session->ta2ta_level);
1028 
1029     /* close current session itself */
1030     ret = process_close_session_entry(&g_cur_service, &g_cur_session);
1031     return ret;
1032 }
1033 
process_open_session(const smc_cmd_t * cmd,uint32_t cmd_type)1034 TEE_Result process_open_session(const smc_cmd_t *cmd, uint32_t cmd_type)
1035 {
1036     global_to_ta_msg entry_msg = { 0 };
1037     uint32_t ret;
1038 
1039     if (cmd == NULL)
1040         return TEE_ERROR_BAD_PARAMETERS;
1041 
1042     bool check_stat = (g_cur_service == NULL || g_cur_session == NULL);
1043     if (check_stat)
1044         return TEE_ERROR_SESSION_NOT_EXIST;
1045 
1046     if (g_cur_service->session_count == 1)
1047         entry_msg.first_session = 1;
1048 
1049     entry_msg.session_id      = set_session_context_bit(g_cur_service->index, g_cur_session->session_id);
1050     entry_msg.session_context = g_cur_session->session_context;
1051     entry_msg.cmd_id          = cmd->cmd_id;
1052     entry_msg.dev_id          = cmd->dev_file_id;
1053     entry_msg.started         = cmd->started;
1054 
1055     if (cmd_type == CMD_TYPE_NS_TO_SECURE) {
1056         if (cmd_ns_get_params(g_cur_session->task_id, cmd, &entry_msg.param_type, &entry_msg.params) != TEE_SUCCESS) {
1057             tloge("cmd_ns_get_params failed\n");
1058             goto map_error;
1059         }
1060         entry_msg.session_type = SESSION_FROM_CA;
1061     } else {
1062         if (TEE_SUCCESS !=
1063             cmd_secure_get_params(g_cur_session->task_id, cmd, &entry_msg.param_type, &entry_msg.params)) {
1064             tloge("cmd_secure_get_params failed\n");
1065             goto map_error;
1066         }
1067         entry_msg.session_type = SESSION_FROM_TA;
1068     }
1069 
1070     ret = send_global2ta_msg(&entry_msg, CALL_TA_OPEN_SESSION, g_cur_session->task_id, NULL);
1071     if (ret != 0) {
1072         tloge("CALL_TA_OPEN_SESSION msg send to ta failed:0x%x\n", ret);
1073         return (TEE_Result)ret;
1074     }
1075     g_cur_session->wait_ta_back_msg = true;
1076     return TEE_SUCCESS;
1077 map_error:
1078     process_open_session_error();
1079     return TEE_ERROR_GENERIC;
1080 }
1081 
process_open_session_error(void)1082 void process_open_session_error(void)
1083 {
1084     int sre_ret;
1085     uint32_t session_id;
1086 
1087     task_adapt_unregister_ta(&g_cur_service->property.uuid, g_cur_session->task_id);
1088     release_pam_node(g_cur_session->pam_node);
1089     task_del_mem_region(&(g_cur_session->map_mem), false);
1090 
1091     g_cur_service->session_count--;
1092 
1093     session_id = set_session_context_bit(g_cur_service->index, g_cur_session->session_id);
1094     sre_ret    = sre_task_delete_ex(g_cur_session->task_id, false, session_id);
1095     /* no return here, there's other clean work to do. */
1096     if (sre_ret != SUCC_RET)
1097         tloge("task del error fail 2: errorno =%d\n", sre_ret);
1098 
1099     CLR_BIT(g_cur_service->session_bitmap[get_index_by_uint32(g_cur_session->session_id - 1)],
1100             get_bit_by_uint32(g_cur_session->session_id - 1));
1101     dlist_delete(&g_cur_session->session_list);
1102     dlist_delete(&g_cur_session->child_ta_sess_list);
1103     TEE_Free(g_cur_session);
1104     g_cur_session = (struct session_struct *)NULL;
1105 
1106     /* when service thread is blocked and session count is 0, we release service thread */
1107     if (sre_ret == TIMEOUT_FAIL_RET) {
1108         tloge("%s is blocked and session count is %u\n", g_cur_service->name,
1109             g_cur_service->session_count);
1110         if (g_cur_service->session_count == 0) {
1111             if (!is_build_in_service(&(g_cur_service->property.uuid))) {
1112                     process_release_service(g_cur_service, TA_REGION_RELEASE);
1113                     g_cur_service = NULL;
1114             } else {
1115                     g_cur_service->init_build = 0;
1116                     recycle_srvc_thread(g_cur_service);
1117             }
1118         }
1119         return;
1120     }
1121 
1122     /* release dynamic loaded TA's resource */
1123     if (g_cur_service->session_count == 0 && g_cur_service->ref_cnt == 0) {
1124         /* for non-keepalive TA, we release service node and service thread; */
1125         if (!is_build_in_service(&(g_cur_service->property.uuid))) {
1126             bool need_release_service = (!g_cur_service->property.keep_alive ||
1127                                          (g_cur_service->property.keep_alive && g_cur_service->first_open));
1128             if (need_release_service) {
1129                 process_release_service(g_cur_service, TA_REGION_RELEASE);
1130                 g_cur_service = NULL;
1131             }
1132         } else {
1133             /*
1134              * for  non-keepalive TA, we release service thread
1135              * and set init_build to 0 for restarting process.
1136              */
1137             if (!g_cur_service->property.keep_alive) {
1138                 g_cur_service->init_build = 0;
1139                 recycle_srvc_thread(g_cur_service);
1140             }
1141         }
1142     }
1143 }
1144 
process_init_session(void)1145 bool process_init_session(void)
1146 {
1147     if (g_cur_service == NULL || g_cur_session == NULL)
1148         return false;
1149 
1150     /* send non-standard property */
1151     if (g_cur_service->property.other_buff != NULL && g_cur_service->property.other_len != 0) {
1152         tlogd("Have non-standard property!");
1153         uint32_t ret = ipc_msg_snd(CALL_TA_OPEN_SESSION_PROP, g_cur_session->task_id,
1154                                    g_cur_service->property.other_buff, (uint16_t)g_cur_service->property.other_len);
1155         if (ret != 0) {
1156             tloge("CALL_TA_OPEN_SESSION_PROP msg send to ta failed:0x%x\n", ret);
1157             return false;
1158         }
1159         g_cur_session->wait_ta_back_msg = true;
1160         return true;
1161     }
1162     return false;
1163 }
1164 
close_session(const smc_cmd_t * cmd,uint32_t cmd_type,bool * sync)1165 TEE_Result close_session(const smc_cmd_t *cmd, uint32_t cmd_type, bool *sync)
1166 {
1167     TEE_Result ret;
1168 
1169     if (cmd == NULL || sync == NULL || g_cur_service == NULL)
1170         return TEE_ERROR_BAD_PARAMETERS;
1171 
1172     *sync = false;
1173 
1174     if (is_gtask_by_uuid(&g_cur_service->property.uuid)) {
1175         /* Send the answer to caller right away since the command was already processed */
1176         *sync = true;
1177         return TEE_SUCCESS;
1178     }
1179 
1180     bool check_stat = (g_cur_session == NULL || g_cur_session->session_id == 0 ||
1181                        g_cur_session->session_id > MAX_SESSION_ID);
1182     if (check_stat) {
1183         tloge("close session not exist\n");
1184         return TEE_ERROR_SESSION_NOT_EXIST;
1185     }
1186 
1187     if (memcpy_s(&g_cur_session->cmd_in, sizeof(smc_cmd_t), cmd, sizeof(smc_cmd_t)))
1188         return TEE_ERROR_GENERIC;
1189 
1190     ret = async_call_ta_entry(cmd, cmd_type, CALL_TA_CLOSE_SESSION);
1191 
1192     return ret;
1193 }
1194 
close_session_async(struct session_struct * sess)1195 TEE_Result close_session_async(struct session_struct *sess)
1196 {
1197     if (sess == NULL) {
1198         tloge("invalid params\n");
1199         return TEE_ERROR_BAD_PARAMETERS;
1200     }
1201 
1202     struct service_struct *service = find_service_by_task_id(sess->task_id);
1203     if (service == NULL) {
1204         tloge("find service by task id 0x%x failed, session id is 0x%x\n", sess->task_id, sess->session_id);
1205         return TEE_ERROR_SERVICE_NOT_EXIST;
1206     }
1207 
1208     g_cur_service = service;
1209     g_cur_session = sess;
1210     tlogi("begin close service %s, session 0x%x async\n", service->name, sess->session_id);
1211     /* we reuse sess->cmd_in to do close session, operation_phys is invalid, so we clear it */
1212     sess->cmd_in.operation_phys = 0;
1213     sess->cmd_in.operation_h_phys = 0;
1214     return async_call_ta_entry(&(sess->cmd_in), sess->cmd_type, CALL_TA_CLOSE_SESSION);
1215 }
1216