• 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 "task_adaptor.h"
14 #include <stddef.h>
15 #include <string.h>
16 #include <securec.h>
17 #include <ipclib.h>
18 #include "gtask_inner.h"
19 #include "service_manager.h"
20 #include "task_ssa_adaptor.h"
21 #include "task_perm_service_adaptor.h"
22 #include "task_se_service_adaptor.h"
23 #include "permsrv_api.h"
24 #include "task_adaptor_pub.h"
25 #include "task_dynamic_adaptor.h"
26 #include "task_register.h"
27 #include <ipclib_hal.h>
28 
29 #define MAX_TASK_NUM    20
30 static struct dlist_node g_task_list_head;
31 static uint32_t g_task_list_num = 0;
32 
find_task_by_taskid(uint32_t task_id)33 struct task_adaptor_info *find_task_by_taskid(uint32_t task_id)
34 {
35     struct dlist_node *pos               = NULL;
36     struct task_adaptor_info *task_entry = NULL;
37 
38     if (task_id == INVALID_TASK_ID) {
39         tloge("task id is invalid\n");
40         return NULL;
41     }
42 
43     dlist_for_each(pos, &g_task_list_head) {
44         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
45         if (taskid_to_pid(task_entry->task_id) == taskid_to_pid(task_id))
46             return task_entry;
47     }
48     return NULL;
49 }
50 
find_task_by_uuid(const TEE_UUID * uuid)51 struct task_adaptor_info *find_task_by_uuid(const TEE_UUID *uuid)
52 {
53     struct dlist_node *pos               = NULL;
54     struct task_adaptor_info *task_entry = NULL;
55 
56     if (uuid == NULL) {
57         tloge("uuid is null\n");
58         return NULL;
59     }
60 
61     dlist_for_each(pos, &g_task_list_head) {
62         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
63         if (memcmp(&task_entry->uuid, uuid, sizeof(task_entry->uuid)) == 0)
64             return task_entry;
65     }
66     return NULL;
67 }
68 
add_task_to_list(const TEE_UUID * uuid,const char * task_name,const struct srv_adaptor_config_t * srv_config)69 static struct task_adaptor_info *add_task_to_list(const TEE_UUID *uuid, const char *task_name,
70     const struct srv_adaptor_config_t *srv_config)
71 {
72     if (uuid == NULL) {
73         tloge("uuid is null\n");
74         return NULL;
75     }
76 
77     /* already exist, return directly */
78     struct task_adaptor_info *task = find_task_by_uuid(uuid);
79     if (task != NULL)
80         return task;
81 
82     if (g_task_list_num >= MAX_TASK_NUM)
83         return NULL;
84 
85     task = TEE_Malloc(sizeof(*task), 0);
86     if (task == NULL) {
87         tloge("malloc task adaptor info failed\n");
88         return NULL;
89     }
90 
91     errno_t ret = memset_s(task, sizeof(*task), 0, sizeof(*task));
92     if (ret != EOK) {
93         tloge("memset task adaptor info failed\n");
94         TEE_Free(task);
95         return NULL;
96     }
97     ret = memcpy_s(&task->uuid, sizeof(task->uuid), uuid, sizeof(*uuid));
98     if (ret != EOK) {
99         tloge("memcpy uuid failed\n");
100         TEE_Free(task);
101         return NULL;
102     }
103 
104     ret = memcpy_s(&task->task_name, sizeof(task->task_name), task_name, strlen(task_name));
105     if (ret != EOK) {
106         tloge("memcpy task name failed\n");
107         TEE_Free(task);
108         return NULL;
109     }
110 
111     if (srv_config != NULL) {
112         task->agent_id = srv_config->agent_id;
113         task->is_need_release_ta_res = srv_config->is_need_release_ta_res;
114         task->crash_callback = srv_config->crash_callback;
115         task->is_need_create_msg = srv_config->is_need_create_msg;
116         task->is_need_release_msg = srv_config->is_need_release_msg;
117     }
118 
119     /* here Initialize the struct member to an illegal value */
120     task->task_id  = INVALID_TASK_ID;
121     task->is_agent = false;
122     dlist_insert_tail(&task->task_node, &g_task_list_head);
123     g_task_list_num++;
124     return task;
125 }
126 
del_task_from_list(const TEE_UUID * uuid)127 void del_task_from_list(const TEE_UUID *uuid)
128 {
129     struct dlist_node *pos               = NULL;
130     struct dlist_node *next              = NULL;
131     struct task_adaptor_info *task_entry = NULL;
132 
133     if (uuid == NULL) {
134         tloge("uuid is null\n");
135         return;
136     }
137 
138     dlist_for_each_safe(pos, next, &g_task_list_head) {
139         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
140         if (memcmp(&task_entry->uuid, uuid, sizeof(task_entry->uuid)) == 0) {
141             dlist_delete(pos);
142             TEE_Free(task_entry);
143             if (g_task_list_num > 0)
144                 g_task_list_num--;
145             return;
146         }
147     }
148 }
149 
is_internal_task_by_task_id(uint32_t task_id)150 bool is_internal_task_by_task_id(uint32_t task_id)
151 {
152     struct task_adaptor_info *task = find_task_by_taskid(task_id);
153     if (task == NULL)
154         return false;
155     return true;
156 }
157 
is_internal_task_by_uuid(const TEE_UUID * uuid)158 bool is_internal_task_by_uuid(const TEE_UUID *uuid)
159 {
160     struct task_adaptor_info *task = find_task_by_uuid(uuid);
161     if (task == NULL)
162         return false;
163     return true;
164 }
165 
task_adapt_set_caller_info(uint32_t cmd_id,uint32_t task_id,const uint8_t * msg_buf,uint32_t msg_size)166 int32_t task_adapt_set_caller_info(uint32_t cmd_id, uint32_t task_id, const uint8_t *msg_buf, uint32_t msg_size)
167 {
168     TEE_Result ret = TEE_SUCCESS;
169     uint32_t sre_ret;
170 
171     (void)cmd_id;
172     struct task_adaptor_info *task = find_task_by_taskid(task_id);
173     if (task == NULL) {
174         tloge("unknown task_id, 0x%x", task_id);
175         return GT_ERR_END_CMD;
176     }
177 
178     if (msg_buf == NULL) {
179         tloge("set caller info failed, param is null");
180         ret = TEE_ERROR_BAD_PARAMETERS;
181         goto send_ack;
182     }
183     if (msg_size < sizeof(struct task_caller_info)) {
184         tloge("invalid msg size %u for caller info", msg_size);
185         ret = TEE_ERROR_BAD_PARAMETERS;
186         goto send_ack;
187     }
188 
189     errno_t rc = memcpy_s(&task->caller_info, sizeof(task->caller_info), msg_buf, sizeof(task->caller_info));
190     if (rc != EOK) {
191         tloge("mem copy caller info msg failed, rc=%d\n", rc);
192         ret = TEE_ERROR_GENERIC;
193         goto send_ack;
194     }
195 send_ack:
196     sre_ret = ipc_msg_snd(TEE_TASK_SET_CALLER_INFO_ACK, task_id, (void *)(&ret), sizeof(ret));
197     if (sre_ret != SRE_OK || ret != TEE_SUCCESS) {
198         tloge("set caller info from task 0x%x failed\n", task_id);
199         return GT_ERR_END_CMD;
200     }
201     return GT_ERR_OK;
202 }
203 
task_adapt_crash_callback(uint32_t task_id)204 void task_adapt_crash_callback(uint32_t task_id)
205 {
206     struct task_adaptor_info *task = find_task_by_taskid(task_id);
207     if (task == NULL) {
208         tloge("unknown task_id, 0x%x", task_id);
209         return;
210     }
211 
212     task->task_id = INVALID_TASK_ID;
213     if (task->task_crash_callback == NULL) {
214         tloge("failed to find task crash callback func, task_id 0x%x", task_id);
215         return;
216     }
217 
218     struct srv_adaptor_config_t config = {0};
219     config.task_prio = task->task_prio;
220     config.agent_id = task->agent_id;
221     config.is_need_release_ta_res = task->is_need_release_ta_res;
222     config.crash_callback = task->crash_callback;
223     config.is_need_create_msg = task->is_need_create_msg;
224     config.is_need_release_msg = task->is_need_release_msg;
225 
226     task->task_crash_callback(&task->uuid, task->task_name, &config);
227 }
228 
send_register_ta_to_task(const struct reg_ta_info * reg_msg,uint32_t dest_task_id)229 void send_register_ta_to_task(const struct reg_ta_info *reg_msg, uint32_t dest_task_id)
230 {
231     if (reg_msg == NULL) {
232         tloge("msg is null, send reg ta failed\n");
233         return;
234     }
235 
236     uint32_t ret = ipc_msg_snd(TEE_TASK_OPEN_TA_SESSION, dest_task_id, reg_msg, sizeof(*reg_msg));
237     if (ret != SRE_OK)
238         tloge("send reg ta msg to task 0x%x failed\n", dest_task_id);
239 }
240 
241 /* param ssa_enum_enable is just for task ssa */
task_adapt_register_ta(uint32_t ta_task_id,uint32_t userid,bool ssa_enum_enable,const TEE_UUID * uuid)242 void task_adapt_register_ta(uint32_t ta_task_id, uint32_t userid, bool ssa_enum_enable, const TEE_UUID *uuid)
243 {
244     struct reg_ta_info reg_msg;
245     struct dlist_node *pos               = NULL;
246     struct task_adaptor_info *task_entry = NULL;
247 
248     if (uuid == NULL) {
249         tloge("uuid is null, reg ta failed\n");
250         return;
251     }
252 
253     reg_msg.taskid          = ta_task_id;
254     reg_msg.userid          = userid;
255     reg_msg.ssa_enum_enable = ssa_enum_enable;
256     errno_t ret             = memcpy_s(&reg_msg.uuid, sizeof(reg_msg.uuid), uuid, sizeof(*uuid));
257     if (ret != EOK) {
258         tloge("memcpy uuid failed\n");
259         return;
260     }
261 
262     dlist_for_each(pos, &g_task_list_head) {
263         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
264         if (task_entry->register_ta_to_task != NULL && task_entry->task_id != INVALID_TASK_ID &&
265             ta_task_id != task_entry->task_id)
266             task_entry->register_ta_to_task(&reg_msg, task_entry->task_id);
267     }
268 }
269 
send_unregister_ta_to_task(const char * cur_task_name,const struct reg_ta_info * reg_msg,uint32_t dest_task_id)270 void send_unregister_ta_to_task(const char *cur_task_name, const struct reg_ta_info *reg_msg,
271     uint32_t dest_task_id)
272 {
273     (void)cur_task_name;
274     if (reg_msg == NULL) {
275         tloge("msg is null, send unreg ta failed\n");
276         return;
277     }
278 
279     uint32_t ret = ipc_msg_snd(TEE_TASK_CLOSE_TA_SESSION, dest_task_id, reg_msg, sizeof(*reg_msg));
280     if (ret != SRE_OK)
281         tloge("send unreg ta msg to task 0x%x failed\n", dest_task_id);
282 }
283 
task_adapt_unregister_ta(const TEE_UUID * ta_uuid,uint32_t ta_task_id)284 void task_adapt_unregister_ta(const TEE_UUID *ta_uuid, uint32_t ta_task_id)
285 {
286     struct reg_ta_info reg_msg;
287     struct dlist_node *pos               = NULL;
288     struct task_adaptor_info *task_entry = NULL;
289 
290     if (ta_uuid == NULL) {
291         tloge("uuid is null, unreg ta failed\n");
292         return;
293     }
294 
295     errno_t ret = memset_s(&reg_msg, sizeof(reg_msg), 0, sizeof(reg_msg));
296     if (ret != EOK)
297         tloge("memset reg msg failed\n");
298 
299     (void)memcpy_s(&reg_msg.uuid, sizeof(TEE_UUID), ta_uuid, sizeof(TEE_UUID));
300     reg_msg.taskid = ta_task_id;
301     dlist_for_each(pos, &g_task_list_head) {
302         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
303         if (task_entry->unregister_ta_to_task != NULL && task_entry->task_id != INVALID_TASK_ID &&
304             ta_task_id != task_entry->task_id)
305             task_entry->unregister_ta_to_task(task_entry->task_name, &reg_msg, task_entry->task_id);
306     }
307 }
308 
task_adapt_send_ta_create_msg(const struct reg_ta_info * msg,uint32_t dest_task_id)309 void task_adapt_send_ta_create_msg(const struct reg_ta_info *msg, uint32_t dest_task_id)
310 {
311     if (msg == NULL) {
312         tloge("msg is null, send ta create msg failed\n");
313         return;
314     }
315 
316     uint32_t ret = ipc_msg_snd(TEE_TASK_CREATE_TA_SERVICE, dest_task_id, msg, sizeof(*msg));
317     if (ret != SRE_OK)
318         tloge("send ta create msg to task 0x%x failed\n", dest_task_id);
319 }
320 
task_adapt_ta_create(uint32_t pid,const TEE_UUID * uuid)321 void task_adapt_ta_create(uint32_t pid, const TEE_UUID *uuid)
322 {
323     struct reg_ta_info msg;
324     struct dlist_node *pos               = NULL;
325     struct task_adaptor_info *task_entry = NULL;
326 
327     if (uuid == NULL) {
328         tloge("uuid is null, task adapt proc ta create failed\n");
329         return;
330     }
331 
332     errno_t ret = memset_s(&msg, sizeof(msg), 0, sizeof(msg));
333     if (ret != EOK) {
334         tloge("memset task reg ta info failed\n");
335         return;
336     }
337 
338     msg.taskid = pid;
339     ret = memcpy_s(&msg.uuid, sizeof(msg.uuid), uuid, sizeof(*uuid));
340     if (ret != EOK) {
341         tloge("memcpy uuid failed\n");
342         return;
343     }
344 
345     dlist_for_each(pos, &g_task_list_head) {
346         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
347         if (task_entry->send_ta_create_msg_to_task != NULL &&
348             task_entry->task_id != INVALID_TASK_ID &&
349             memcmp(uuid, &(task_entry->uuid), sizeof(*uuid)) != 0)
350             task_entry->send_ta_create_msg_to_task(task_entry->task_name, &msg, task_entry->task_id);
351     }
352 }
353 
task_adapt_send_ta_release_msg(const struct reg_ta_info * msg,uint32_t dest_task_id)354 void task_adapt_send_ta_release_msg(const struct reg_ta_info *msg, uint32_t dest_task_id)
355 {
356     if (msg == NULL) {
357         tloge("msg is null, send ta release msg failed\n");
358         return;
359     }
360 
361     uint32_t ret = ipc_msg_snd(TEE_TASK_RELEASE_TA_SERVICE, dest_task_id, msg, sizeof(*msg));
362     if (ret != SRE_OK)
363         tloge("send ta release msg to task 0x%x failed\n", dest_task_id);
364 }
365 
task_adapt_ta_release(const TEE_UUID * uuid)366 void task_adapt_ta_release(const TEE_UUID *uuid)
367 {
368     struct reg_ta_info msg;
369     struct dlist_node *pos               = NULL;
370     struct task_adaptor_info *task_entry = NULL;
371 
372     if (uuid == NULL) {
373         tloge("uuid is null, task adapt proc ta release failed\n");
374         return;
375     }
376 
377     errno_t ret = memset_s(&msg, sizeof(msg), 0, sizeof(msg));
378     if (ret != EOK) {
379         tloge("memset task reg ta info failed\n");
380         return;
381     }
382 
383     ret = memcpy_s(&msg.uuid, sizeof(msg.uuid), uuid, sizeof(*uuid));
384     if (ret != EOK) {
385         tloge("memcpy uuid failed\n");
386         return;
387     }
388 
389     dlist_for_each(pos, &g_task_list_head) {
390         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
391         if (task_entry->send_ta_release_msg_to_task != NULL &&
392             task_entry->task_id != INVALID_TASK_ID &&
393             memcmp(uuid, &(task_entry->uuid), sizeof(*uuid)) != 0)
394             task_entry->send_ta_release_msg_to_task(task_entry->task_name, &msg, task_entry->task_id);
395     }
396 }
397 
register_task_proc(const TEE_UUID * uuid,uint16_t task_prio,const char * task_name,const task_init_priv_info_f task_init_priv_info,const struct srv_adaptor_config_t * srv_config)398 struct task_adaptor_info *register_task_proc(const TEE_UUID *uuid, uint16_t task_prio,
399     const char *task_name, const task_init_priv_info_f task_init_priv_info,
400     const struct srv_adaptor_config_t *srv_config)
401 {
402     uint32_t task_id;
403 
404     if (uuid == NULL || task_name == NULL || task_init_priv_info == NULL) {
405         tloge("input param is invalid\n");
406         return NULL;
407     }
408 
409     struct task_adaptor_info *task = add_task_to_list(uuid, task_name, srv_config);
410     if (task == NULL) {
411         tloge("add task to list failed\n");
412         return NULL;
413     }
414 
415     if (start_internal_task(uuid, task_prio, task_name, &task_id) != TEE_SUCCESS) {
416         tloge("Failed to start task\n");
417         del_task_from_list(uuid);
418         return NULL;
419     }
420 
421     task->task_id = task_id;
422     task_init_priv_info(task);
423     return task;
424 }
425 
task_adapt_init(void)426 void task_adapt_init(void)
427 {
428     dlist_init(&g_task_list_head);
429 
430     /* there is no need to process return value here */
431     register_multi_task();
432     (void)register_task_ssa();
433 #if defined(CONFIG_APP_TEE_PERM) || defined(CONFIG_APP_TEE_PERM_A32)
434     register_task_perm_serv();
435 #endif
436     (void)register_task_se_srv();
437 #if (defined CONFIG_APP_TEE_TEST_SERVICE || defined CONFIG_APP_TEE_TEST_SERVICE_A64)
438     (void)register_task_test_srv();
439 #endif
440 }
441 
442 /* -----------------------------------------for agent task------------------------------------------ */
is_service_agent_request(uint32_t agent_task_id,uint32_t * caller_task_id,uint32_t ** agent_status)443 bool is_service_agent_request(uint32_t agent_task_id, uint32_t *caller_task_id, uint32_t **agent_status)
444 {
445     struct task_adaptor_info *task = NULL;
446 
447     if (caller_task_id == NULL || agent_status == NULL) {
448         tloge("in param is null, agent request check failed\n");
449         return false;
450     }
451 
452     task = find_task_by_taskid(agent_task_id);
453     if (task == NULL)
454         return false;
455 
456     if (task->is_agent) {
457         *caller_task_id = task->caller_info.taskid;
458         *agent_status   = &task->agent_status;
459         return true;
460     }
461     return false;
462 }
463 
is_agent_response(uint32_t agent_id,uint32_t * agent_task_id,uint32_t * caller_task_id,uint32_t ** agent_status)464 bool is_agent_response(uint32_t agent_id, uint32_t *agent_task_id, uint32_t *caller_task_id,
465                        uint32_t **agent_status)
466 {
467     struct dlist_node *pos               = NULL;
468     struct task_adaptor_info *task_entry = NULL;
469 
470     if (agent_task_id == NULL || caller_task_id == NULL || agent_status == NULL) {
471         tloge("in param is null, agent response check failed\n");
472         return false;
473     }
474 
475     dlist_for_each(pos, &g_task_list_head) {
476         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
477         if (task_entry->agent_id == agent_id && task_entry->is_agent) {
478             *caller_task_id = task_entry->caller_info.taskid;
479             *agent_task_id  = task_entry->task_id;
480             *agent_status   = &task_entry->agent_status;
481             return true;
482         }
483     }
484     return false;
485 }
486 
487 /* for system agent buffer, we only allow system agent task to access */
check_system_agent_permission(uint32_t task_id,uint32_t agent_id)488 bool check_system_agent_permission(uint32_t task_id, uint32_t agent_id)
489 {
490     struct dlist_node *pos               = NULL;
491     struct task_adaptor_info *task_entry = NULL;
492 
493     dlist_for_each(pos, &g_task_list_head) {
494         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
495         if (task_entry->is_agent) {
496             if ((agent_id == task_entry->agent_id) && (task_id != task_entry->task_id))
497                 return false;
498         }
499     }
500     return true;
501 }
502 
503 /*
504  * gtask will send agent buffer to ssa when receive register ssa agent msg.
505  * so only ssa need this interface
506  */
task_adapt_register_agent(uint32_t agent_id)507 void task_adapt_register_agent(uint32_t agent_id)
508 {
509     struct dlist_node *pos               = NULL;
510     struct task_adaptor_info *task_entry = NULL;
511 
512     dlist_for_each(pos, &g_task_list_head) {
513         task_entry = dlist_entry(pos, struct task_adaptor_info, task_node);
514         if (task_entry->is_agent && task_entry->agent_id == agent_id) {
515             if (task_entry->register_agent_buffer_to_task != NULL && task_entry->task_id != INVALID_TASK_ID)
516                 task_entry->register_agent_buffer_to_task(agent_id, task_entry->task_id);
517             return;
518         }
519     }
520 }
521 
fs_agent_late_init(void)522 void fs_agent_late_init(void)
523 {
524     tee_ext_load_file();
525     task_ssa_load_manage_info();
526 }
527