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(®_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(®_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(®_msg, sizeof(reg_msg), 0, sizeof(reg_msg));
296 if (ret != EOK)
297 tloge("memset reg msg failed\n");
298
299 (void)memcpy_s(®_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, ®_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