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_mgr.h"
14 #include <tee_log.h>
15 #include <ipclib.h>
16 #include <libdrv_frame.h>
17 #include <dyn_conf_dispatch_inf.h>
18 #include <target_type.h>
19 #include <drv_thread.h>
20 #include <ta_lib_img_unpack.h>
21 #include "drv_fd_ops.h"
22 #include "drv_process_mgr.h"
23 #include "drv_dyn_policy_mgr.h"
24 #include "drv_index_mgr.h"
25 #include "drv_dyn_conf_mgr.h"
26 #include <securec.h>
27
28 static struct dlist_node g_task_list = dlist_head_init(g_task_list);
29 static pthread_mutex_t g_task_mtx = PTHREAD_MUTEX_INITIALIZER;
30
init_drv_node(struct task_node * node)31 static int32_t init_drv_node(struct task_node *node)
32 {
33 int32_t drv_index = alloc_drv_index();
34 if (drv_index == -1) {
35 tloge("alloc drv index fail\n");
36 return -1;
37 }
38
39 node->drv_task.drv_index = drv_index;
40 node->drv_task.register_policy = false;
41 node->ref_cnt = 0; /* not support dynamic load */
42 node->state = TASK_LOAD;
43 node->target_type = DRV_TARGET_TYPE;
44
45 return 0;
46 }
47
init_ta_node(struct task_node * node)48 static int32_t init_ta_node(struct task_node *node)
49 {
50 node->ref_cnt = 1; /* will dec when unregister ta */
51 node->state = TASK_NORMAL;
52 node->target_type = TA_TARGET_TYPE;
53
54 return 0;
55 }
56
init_task_node(struct task_node * node)57 static int32_t init_task_node(struct task_node *node)
58 {
59 dlist_init(&node->node_list);
60 node->pid = INVALID_CALLER_PID;
61
62 /* TA will not use this */
63 node->drv_task.drv_index = -1;
64 node->drv_task.channel = -1;
65 node->tlv.drvcall_perm_apply_list = NULL;
66 node->tlv.drv_conf = NULL;
67
68 dlist_init(&node->fd_head);
69 if (drv_mutex_init(&node->fd_mtx) != 0) {
70 tloge("fd mtx init fail\n");
71 return -1;
72 }
73
74 node->fd_count = 0;
75
76 if (pthread_cond_init(&node->state_cond, NULL) != 0) {
77 tloge("state cond init fail\n");
78 return -1;
79 }
80
81 if (drv_mutex_init(&node->state_mtx) != 0) {
82 tloge("state mtx init fail\n");
83 return -1;
84 }
85
86 return 0;
87 }
88
init_drvcall_perm(const struct drvcall_perm_apply_t * drvcall_in,struct task_node * node)89 static int32_t init_drvcall_perm(const struct drvcall_perm_apply_t *drvcall_in, struct task_node *node)
90 {
91 struct drvcall_perm_apply_t drvcall_perm;
92 if (memset_s(&drvcall_perm, sizeof(drvcall_perm), 0, sizeof(drvcall_perm)) != 0) {
93 tloge("memset for drvcall_perm failed\n");
94 return -1;
95 }
96
97 drvcall_perm.drvcall_perm_apply_list_size = drvcall_in->drvcall_perm_apply_list_size;
98 drvcall_perm.drvcall_perm_apply_list = drvcall_in->drvcall_perm_apply_list;
99 drvcall_perm.base_perm = drvcall_in->base_perm;
100
101 if (receive_perm_apply_list(&drvcall_perm) != 0)
102 return -1;
103
104 node->tlv.drvcall_perm_apply_list = drvcall_perm.drvcall_perm_apply_list;
105 node->tlv.drvcall_perm_apply_list_size = drvcall_perm.drvcall_perm_apply_list_size;
106
107 return 0;
108 }
109
init_drv_conf(const struct drv_conf_t * drv_conf,struct task_node * node)110 static int32_t init_drv_conf(const struct drv_conf_t *drv_conf, struct task_node *node)
111 {
112 struct drv_conf_t *temp_drv_conf = malloc(sizeof(struct drv_conf_t));
113 if (temp_drv_conf == NULL) {
114 tloge("alloc drv conf fail\n");
115 return -1;
116 }
117
118 if (memcpy_s(temp_drv_conf, sizeof(*temp_drv_conf), drv_conf, sizeof(*drv_conf)) != 0) {
119 tloge("copy drv conf fail\n");
120 goto free_temp;
121 }
122
123 if (do_receive_drv_conf(temp_drv_conf) != 0) {
124 tloge("receive drv conf fail\n");
125 goto free_temp;
126 }
127
128 node->tlv.drv_conf = temp_drv_conf;
129 return 0;
130
131 free_temp:
132 free(temp_drv_conf);
133 return -1;
134 }
135
alloc_and_init_drv_node(struct drv_tlv * tlv)136 struct task_node *alloc_and_init_drv_node(struct drv_tlv *tlv)
137 {
138 if (tlv == NULL) {
139 tloge("invalid drv tlv\n");
140 return NULL;
141 }
142
143 struct task_node *node = malloc(sizeof(*node));
144 if (node == NULL) {
145 tloge("alloc drv node fail\n");
146 return NULL;
147 }
148
149 (void)memset_s(node, sizeof(*node), 0, sizeof(*node));
150 node->tlv.uuid = tlv->uuid;
151
152 if (init_task_node(node) != 0)
153 goto free_node;
154
155 if (init_drv_node(node) != 0)
156 goto free_node;
157
158 if (tlv->drvcall_perm_apply.drvcall_perm_apply_list_size != 0) {
159 /* drv may not has drvcall perm */
160 if (init_drvcall_perm(&tlv->drvcall_perm_apply, node) != 0)
161 goto free_node;
162 }
163
164 if (init_drv_conf(&tlv->drv_conf, node) != 0)
165 goto free_node;
166
167 return node;
168
169 free_node:
170 free_task_node(node);
171 return NULL;
172 }
173
alloc_and_init_ta_node(const struct drvcall_conf_t * tlv)174 struct task_node *alloc_and_init_ta_node(const struct drvcall_conf_t *tlv)
175 {
176 if (tlv == NULL) {
177 tloge("invalid tlv\n");
178 return NULL;
179 }
180
181 struct task_node *node = malloc(sizeof(*node));
182 if (node == NULL) {
183 tloge("alloc task node fail\n");
184 return NULL;
185 }
186
187 if (memset_s(node, sizeof(*node), 0, sizeof(*node)) != 0) {
188 tloge("memset_s for task node fail\n");
189 free(node);
190 return NULL;
191 }
192
193 node->tlv.uuid = tlv->uuid;
194
195 if (init_task_node(node) != 0)
196 goto free_node;
197
198 if (init_ta_node(node) != 0)
199 goto free_node;
200
201 if (init_drvcall_perm(&tlv->drvcall_perm_apply, node) != 0)
202 goto free_node;
203
204 return node;
205
206 free_node:
207 free_task_node(node);
208 return NULL;
209 }
210
free_drv_node(struct task_node * node)211 static void free_drv_node(struct task_node *node)
212 {
213 if (node->drv_task.drv_index != -1) {
214 clear_drv_index(node->drv_task.drv_index);
215 node->drv_task.drv_index = -1;
216 }
217
218 release_driver(node);
219
220 if (node->tlv.drv_conf != NULL) {
221 free_drv_conf_list(node->tlv.drv_conf, RECEIVE_MAX_TAG);
222 free(node->tlv.drv_conf);
223 node->tlv.drv_conf = NULL;
224 }
225 }
226
free_task_node(struct task_node * node)227 void free_task_node(struct task_node *node)
228 {
229 if (node == NULL) {
230 tloge("invalid task node\n");
231 return;
232 }
233
234 if (node->tlv.drvcall_perm_apply_list != NULL) {
235 free(node->tlv.drvcall_perm_apply_list);
236 node->tlv.drvcall_perm_apply_list = NULL;
237 }
238
239 if (node->target_type == DRV_TARGET_TYPE)
240 free_drv_node(node);
241
242 free(node);
243 }
244
inc_drv_node(struct task_node * node)245 static int32_t inc_drv_node(struct task_node *node)
246 {
247 if (node->ref_cnt == UINT32_MAX) {
248 tloge("something wrong, ref cnt is overflow\n");
249 return -1;
250 }
251
252 node->ref_cnt++;
253 return 0;
254 }
255
is_state_match(struct task_node * node,enum node_state except_state)256 static bool is_state_match(struct task_node *node, enum node_state except_state)
257 {
258 bool match_flag = true;
259 int32_t ret = drv_mutex_lock(&node->state_mtx);
260 if (ret != 0) {
261 tloge("get state mtx fail\n");
262 return false;
263 }
264
265 if (node->state != except_state) {
266 tlogd("node state:%d not match except state:%d\n", node->state, except_state);
267 match_flag = false;
268 }
269
270 ret = pthread_mutex_unlock(&node->state_mtx);
271 if (ret != 0)
272 tloge("unlock state mtx fail\n");
273
274 return match_flag;
275 }
276
find_normal_node(const struct tee_uuid * uuid,uint32_t taskid)277 static struct task_node *find_normal_node(const struct tee_uuid *uuid, uint32_t taskid)
278 {
279 struct dlist_node *pos = NULL;
280 dlist_for_each(pos, &g_task_list) {
281 struct task_node *temp = dlist_entry(pos, struct task_node, node_list);
282 if (memcmp(uuid, &temp->tlv.uuid, sizeof(*uuid)) == 0) {
283 if (!is_state_match(temp, TASK_NORMAL))
284 continue;
285
286 tlogd("find uuid:0x%x\n", uuid->timeLow);
287 /* taskid is INVALID_CALLER_PID when uninstall ta */
288 if (taskid == (uint32_t)INVALID_CALLER_PID)
289 return temp;
290
291 /* temp->pid is INVALID_CALLER_PID when ta open drv in the first time */
292 if (temp->pid == (uint32_t)INVALID_CALLER_PID) {
293 temp->pid = taskid_to_pid(taskid);
294 } else if (temp->pid != taskid_to_pid(taskid)) {
295 tloge("something wrong, uuid:0x%x pid:0x%x not match taskid:0x%x\n",
296 uuid->timeLow, temp->pid, taskid);
297 continue;
298 }
299
300 return temp;
301 }
302 }
303
304 return NULL;
305 }
306
307 /* find node whose state not set TASK_EXIT */
find_effective_node(const struct tee_uuid * uuid)308 static struct task_node *find_effective_node(const struct tee_uuid *uuid)
309 {
310 struct dlist_node *pos = NULL;
311 dlist_for_each(pos, &g_task_list) {
312 struct task_node *temp = dlist_entry(pos, struct task_node, node_list);
313 if (memcmp(uuid, &temp->tlv.uuid, sizeof(*uuid)) == 0) {
314 if (!is_state_match(temp, TASK_EXIT)) {
315 tlogd("find uuid:0x%x\n", uuid->timeLow);
316 return temp;
317 }
318 }
319 }
320
321 return NULL;
322 }
323
find_node_by_name(const char * drv_name,uint32_t len)324 static struct task_node *find_node_by_name(const char *drv_name, uint32_t len)
325 {
326 struct dlist_node *pos = NULL;
327 dlist_for_each(pos, &g_task_list) {
328 struct task_node *temp = dlist_entry(pos, struct task_node, node_list);
329 if (temp->target_type == DRV_TARGET_TYPE &&
330 temp->tlv.drv_conf != NULL &&
331 temp->tlv.drv_conf->mani.service_name_size == len &&
332 strncmp(temp->tlv.drv_conf->mani.service_name, drv_name, len + 1) == 0) {
333 if (is_state_match(temp, TASK_EXIT)) {
334 tloge("something wrong, drv state is exit\n");
335 continue;
336 }
337
338 tlogd("find drv:%s\n", drv_name);
339 return temp;
340 }
341 }
342
343 return NULL;
344 }
345
346 /*
347 * called by get_valid_drv_node
348 * it must be drv node
349 * the state will be checked in check_drv_node_state so no need check state in find_node_by_name
350 */
get_drv_node_by_name_with_lock(const char * drv_name,uint32_t len)351 struct task_node *get_drv_node_by_name_with_lock(const char *drv_name, uint32_t len)
352 {
353 if (drv_name == NULL || len == 0) {
354 tloge("invalid drv name\n");
355 return NULL;
356 }
357
358 if (drv_mutex_lock(&g_task_mtx) != 0) {
359 tloge("something wrong, get task mtx fail\n");
360 return NULL;
361 }
362
363 struct task_node *temp = find_node_by_name(drv_name, len);
364 if (temp == NULL) {
365 tloge("cannot find drv:%s\n", drv_name);
366 goto unlock_mtx;
367 }
368
369 if (inc_drv_node(temp) != 0)
370 temp = NULL;
371
372 unlock_mtx:
373 if (pthread_mutex_unlock(&g_task_mtx) != 0)
374 tloge("something wrong, cannot unlock task mtx\n");
375
376 return temp;
377 }
378
set_task_exit_state(struct task_node * node)379 static int32_t set_task_exit_state(struct task_node *node)
380 {
381 int32_t ret = drv_mutex_lock(&node->state_mtx);
382 if (ret != 0) {
383 tloge("get state mtx fail\n");
384 return -1;
385 }
386
387 node->state = TASK_EXIT;
388
389 ret = pthread_mutex_unlock(&node->state_mtx);
390 if (ret != 0)
391 tloge("unlock state mtx fail\n");
392
393 return 0;
394 }
395
get_node_by_uuid(const struct tee_uuid * uuid,uint32_t taskid,bool exit_flag,int32_t target_type)396 static struct task_node *get_node_by_uuid(const struct tee_uuid *uuid, uint32_t taskid,
397 bool exit_flag, int32_t target_type)
398 {
399 struct task_node *temp = find_normal_node(uuid, taskid);
400 if (temp == NULL) {
401 if (!exit_flag)
402 tlogd("cannot find node:0x%x\n", uuid->timeLow);
403 return NULL;
404 }
405
406 /* ignore target_type of node when input is -1 */
407 if (target_type != -1 && temp->target_type != target_type) {
408 tloge("uuid:0x%x target_type:%u not match %u\n", uuid->timeLow, temp->target_type, target_type);
409 return NULL;
410 }
411
412 if (inc_drv_node(temp) != 0)
413 return NULL;
414
415 if (exit_flag) {
416 if (set_task_exit_state(temp) != 0) {
417 temp->ref_cnt--;
418 return NULL;
419 }
420 }
421
422 return temp;
423 }
424
get_node_by_uuid_handle(const struct tee_uuid * uuid,uint32_t taskid,bool exit_flag,int32_t target_type)425 static struct task_node *get_node_by_uuid_handle(const struct tee_uuid *uuid, uint32_t taskid,
426 bool exit_flag, int32_t target_type)
427 {
428 if (uuid == NULL) {
429 tloge("invalid uuid\n");
430 return NULL;
431 }
432
433 if (drv_mutex_lock(&g_task_mtx) != 0) {
434 tloge("something wrong, get task mtx fail\n");
435 return NULL;
436 }
437
438 struct task_node *temp = get_node_by_uuid(uuid, taskid, exit_flag, target_type);
439
440 if (pthread_mutex_unlock(&g_task_mtx) != 0)
441 tloge("something wrong, cannot unlock task mtx\n");
442
443 return temp;
444 }
445
446 /*
447 * called by get_valid_drvcall_node
448 * it can be ta node or drv node
449 * the state must be TASK_NORMAL for both ta and drv node
450 */
get_node_by_uuid_with_lock(const struct tee_uuid * uuid,uint32_t taskid)451 struct task_node *get_node_by_uuid_with_lock(const struct tee_uuid *uuid, uint32_t taskid)
452 {
453 return get_node_by_uuid_handle(uuid, taskid, false, -1);
454 }
455
456 /*
457 * called by drvcall_conf_unregister_handle
458 * the node must be TA_TARGET_TYPE
459 * the state must be TASK_NORMAL
460 */
get_ta_node_and_set_exit(const struct tee_uuid * uuid)461 struct task_node *get_ta_node_and_set_exit(const struct tee_uuid *uuid)
462 {
463 return get_node_by_uuid_handle(uuid, INVALID_CALLER_PID, true, TA_TARGET_TYPE);
464 }
465
get_drvcall_and_fd_node(int64_t fd,const struct tee_drv_param * params,struct task_node ** call_node,struct fd_node ** fdata)466 int32_t get_drvcall_and_fd_node(int64_t fd, const struct tee_drv_param *params,
467 struct task_node **call_node, struct fd_node **fdata)
468 {
469 if (params == NULL || call_node == NULL || fdata == NULL) {
470 tloge("invalid param\n");
471 return -1;
472 }
473
474 struct fd_node *data = NULL;
475 struct task_node *node = NULL;
476
477 if (drv_mutex_lock(&g_task_mtx) != 0) {
478 tloge("something wrong, get task mtx fail\n");
479 return -1;
480 }
481
482 struct dlist_node *pos = NULL;
483 dlist_for_each(pos, &g_task_list) {
484 struct task_node *temp = dlist_entry(pos, struct task_node, node_list);
485 if (memcmp(&temp->tlv.uuid, ¶ms->uuid, sizeof(struct tee_uuid)) == 0 &&
486 temp->pid == taskid_to_pid(params->caller_pid)) {
487 /*
488 * fd must match in case of the drvcall node exit abnormally,
489 * and restart soon before the first process open has not return.
490 * drvcall which uuid is uuid1:
491 * 1.drvcall process start, alloc pid1 and drvcall node1
492 * 2.thread 0 of pid1 call open in cpux and thread 1 of pid1 abort in cpuy at the same time
493 * 3.gtask handle pid1 crash msg, and send to drvmgr, drvmgr set the node1 exit status
494 * 4.uuid1 drvcall restart, it reuse the pid1 and alloc new drvcall node2
495 * in this case, it will cannot find fd data if we just check whether the uuid and pid are equal,
496 * since the drvcall node2 also match
497 */
498 data = close_get_fd_node_with_lock(node, fd);
499 if (data == NULL)
500 continue;
501
502 if (node->ref_cnt == UINT32_MAX) {
503 tloge("something wrong, cannot get drvcall node:0x%x task:0x%x for fd:0x%llx, just del\n",
504 params->uuid.timeLow, node->pid, fd);
505 del_fd_to_drvcall_node(&data, node);
506 data = NULL;
507 continue;
508 } else {
509 node->ref_cnt++;
510 }
511 break;
512 }
513 }
514
515 if (pthread_mutex_unlock(&g_task_mtx) != 0)
516 tloge("something wrong, cannot unlock task mtx\n");
517
518 if (data != NULL) {
519 *call_node = node;
520 *fdata = data;
521 return 0;
522 }
523
524 return -1;
525 }
526
put_node(struct task_node * node,uint32_t dec_cnt)527 static void put_node(struct task_node *node, uint32_t dec_cnt)
528 {
529 if (node->ref_cnt < dec_cnt)
530 tloge("something wrong, uuid:0x%x ref_cnt:%u dec_cnt:%u invalid\n",
531 node->tlv.uuid.timeLow, node->ref_cnt, dec_cnt);
532 else
533 node->ref_cnt = node->ref_cnt - dec_cnt;
534
535 if (node->ref_cnt == 0) {
536 /*
537 * do not release drv since it not support dynamic load
538 * in current time, drv can only be delete when register fail
539 * which will call free_drv_conf_by_service_name
540 */
541 if (node->target_type == DRV_TARGET_TYPE) {
542 tlogd("drv:0x%x cannot free\n", node->tlv.uuid.timeLow);
543 return;
544 }
545
546 dlist_delete(&node->node_list);
547 free_task_node(node);
548 }
549 }
550
put_node_with_lock(struct task_node * node,uint32_t dec_cnt)551 void put_node_with_lock(struct task_node *node, uint32_t dec_cnt)
552 {
553 if (node == NULL) {
554 tloge("invalid node\n");
555 return;
556 }
557
558 if (drv_mutex_lock(&g_task_mtx) != 0) {
559 tloge("something wrong, get task mtx fail\n");
560 return;
561 }
562
563 put_node(node, dec_cnt);
564
565 if (pthread_mutex_unlock(&g_task_mtx) != 0)
566 tloge("something wrong, cannot unlock task mtx\n");
567 }
568
check_hardware_type(const struct task_node * node,uint16_t type)569 bool check_hardware_type(const struct task_node *node, uint16_t type)
570 {
571 if (node == NULL) {
572 tloge("invalid node while check hardware type");
573 return false;
574 }
575
576 struct drv_conf_t *drv_conf = node->tlv.drv_conf;
577 if (node->target_type == DRV_TARGET_TYPE && drv_conf != NULL && drv_conf->mani.hardware_type == type)
578 return true;
579
580 return false;
581 }
582
583 /*
584 * since not support load drv dynamically, one drv must have only one node,
585 * ignore its state
586 */
drv_is_exist(const struct task_tlv * tlv)587 static bool drv_is_exist(const struct task_tlv *tlv)
588 {
589 struct task_node *node = find_effective_node(&tlv->uuid);
590 if (node != NULL) {
591 tloge("this uuid:0x%x cannot register again\n", tlv->uuid.timeLow);
592 return true;
593 }
594
595 node = find_node_by_name(tlv->drv_conf->mani.service_name, tlv->drv_conf->mani.service_name_size);
596 if (node != NULL) {
597 tloge("this drv:%s cannot register again\n", tlv->drv_conf->mani.service_name);
598 return true;
599 }
600
601 return false;
602 }
603
check_drv_name_invalid(const char * drv_name,uint32_t len)604 static bool check_drv_name_invalid(const char *drv_name, uint32_t len)
605 {
606 if (len == 0 || len >= DRV_NAME_MAX_LEN) {
607 tloge("invalid drv name len:%u\n", len);
608 return true;
609 }
610
611 if (strnlen(drv_name, DRV_NAME_MAX_LEN) != len) {
612 tloge("drv name not match drv len:%u\n", len);
613 return true;
614 }
615
616 return false;
617 }
618
receive_drv_conf(struct task_node * node)619 static int32_t receive_drv_conf(struct task_node *node)
620 {
621 if (node->tlv.drv_conf == NULL) {
622 tloge("invalid drv conf\n");
623 return -1;
624 }
625
626 if (check_drv_name_invalid(node->tlv.drv_conf->mani.service_name, node->tlv.drv_conf->mani.service_name_size))
627 return -1;
628
629 if (drv_is_exist(&node->tlv))
630 return -1;
631
632 if (register_drv_policy(node) != 0)
633 return -1;
634
635 return 0;
636 }
637
receive_ta_conf(struct task_node * node)638 static int32_t receive_ta_conf(struct task_node *node)
639 {
640 /* state cannot be TASK_EXIT */
641 if (find_effective_node(&node->tlv.uuid) != NULL) {
642 tloge("ta uuid:0x%x cannot register again\n", node->tlv.uuid.timeLow);
643 return -1;
644 }
645
646 return 0;
647 }
648
check_drv_conf_target_is_valid(const struct drv_conf_t * dst)649 static int32_t check_drv_conf_target_is_valid(const struct drv_conf_t *dst)
650 {
651 if (dst->io_map_list_size != 0 || dst->io_map_list != NULL) {
652 tloge("drv conf target io map list is invalied\n");
653 return -1;
654 }
655
656 if (dst->irq_list_size != 0 || dst->irq_list != NULL) {
657 tloge("drv conf target irq list is invalied\n");
658 return -1;
659 }
660
661 if (dst->map_secure_list_size != 0 || dst->map_secure_list != NULL) {
662 tloge("drv conf target map secure list is invalied\n");
663 return -1;
664 }
665
666 if (dst->map_nosecure_list_size != 0 || dst->map_nosecure_list != NULL) {
667 tloge("drv conf target io map nosecure is invalied\n");
668 return -1;
669 }
670
671 if (dst->mac_info_list_size != 0 || dst->mac_info_list != NULL) {
672 tloge("drv conf target mac info list is invalied\n");
673 return -1;
674 }
675
676 if (dst->cmd_perm_list_size != 0 || dst->cmd_perm_list != NULL) {
677 tloge("drv conf target cmd perm list is invalied\n");
678 return -1;
679 }
680
681 return 0;
682 }
683
do_copy_drv_conf_to_target(const void * src_list,uint16_t src_list_size,void ** dst_list,uint16_t * dst_list_size,uint32_t unit_size)684 static int32_t do_copy_drv_conf_to_target(const void *src_list, uint16_t src_list_size, void **dst_list,
685 uint16_t *dst_list_size, uint32_t unit_size)
686 {
687 if (src_list_size == 0)
688 return 0;
689
690 if (unit_size == 0 || src_list_size >= MAX_IMAGE_LEN / unit_size) {
691 tloge("invalied src list size\n");
692 return -1;
693 }
694
695 uint32_t size = src_list_size * unit_size;
696 *dst_list = malloc(size);
697 if (*dst_list == NULL) {
698 tloge("malloc for dst list failed\n");
699 return -1;
700 }
701
702 if (memcpy_s(*dst_list, size, src_list, size) != 0) {
703 tloge("memcpy for dst list failed\n");
704 free(*dst_list);
705 *dst_list = NULL;
706 return -1;
707 }
708
709 *dst_list_size = src_list_size;
710 return 0;
711 }
712
copy_drv_conf_to_target(struct drv_conf_t * src,struct drv_conf_t * dst)713 static int32_t copy_drv_conf_to_target(struct drv_conf_t *src, struct drv_conf_t *dst)
714 {
715 if (check_drv_conf_target_is_valid(dst) != 0)
716 return -1;
717
718 if (do_copy_drv_conf_to_target((void *)src->io_map_list, src->io_map_list_size,
719 (void **)&dst->io_map_list, &dst->io_map_list_size,
720 sizeof(struct addr_region_t)) != 0)
721 goto out;
722
723 if (do_copy_drv_conf_to_target((void *)src->irq_list, src->irq_list_size,
724 (void **)&dst->irq_list, &dst->irq_list_size,
725 sizeof(uint64_t)) != 0)
726 goto out;
727
728 if (do_copy_drv_conf_to_target((void *)src->map_secure_list, src->map_secure_list_size,
729 (void **)&dst->map_secure_list, &dst->map_secure_list_size,
730 sizeof(struct drv_map_secure_t)) != 0)
731 goto out;
732
733 if (do_copy_drv_conf_to_target((void *)src->map_nosecure_list, src->map_nosecure_list_size,
734 (void **)&dst->map_nosecure_list, &dst->map_nosecure_list_size,
735 sizeof(struct drv_map_nosecure_t)) != 0)
736 goto out;
737
738 if (do_copy_drv_conf_to_target((void *)src->mac_info_list, src->mac_info_list_size,
739 (void **)&dst->mac_info_list, &dst->mac_info_list_size,
740 sizeof(struct drv_mac_info_t)) != 0)
741 goto out;
742
743 if (do_copy_drv_conf_to_target((void *)src->cmd_perm_list, src->cmd_perm_list_size,
744 (void **)&dst->cmd_perm_list, &dst->cmd_perm_list_size,
745 sizeof(struct drv_cmd_perm_info_t)) != 0)
746 goto out;
747
748 dst->drv_basic_info.upgrade = src->drv_basic_info.upgrade;
749 dst->drv_basic_info.virt2phys = src->drv_basic_info.virt2phys;
750 dst->drv_basic_info.exception_mode = src->drv_basic_info.exception_mode;
751
752 return 0;
753
754 out:
755 free_drv_conf_list(dst, RECEIVE_MAX_TAG);
756 return -1;
757 }
758
free_drv_perm_apply_list(struct task_tlv * dst)759 static void free_drv_perm_apply_list(struct task_tlv *dst)
760 {
761 free((void *)dst->drvcall_perm_apply_list);
762 dst->drvcall_perm_apply_list = NULL;
763 dst->drvcall_perm_apply_list_size = 0;
764 }
765
copy_drv_perm_apply_to_target(struct task_tlv * src,struct task_tlv * dst)766 static int32_t copy_drv_perm_apply_to_target(struct task_tlv *src, struct task_tlv *dst)
767 {
768 if (dst->drvcall_perm_apply_list_size != 0 || dst->drvcall_perm_apply_list != NULL) {
769 tloge("drvcall perm apply list is invalied\n");
770 return -1;
771 }
772
773 uint32_t uint_size = sizeof(struct drvcall_perm_apply_item_t);
774 if (uint_size == 0 || src->drvcall_perm_apply_list_size >= MAX_IMAGE_LEN / uint_size)
775 return -1;
776
777 if (src->drvcall_perm_apply_list_size == 0)
778 return 0;
779
780 uint32_t size = src->drvcall_perm_apply_list_size * uint_size;
781 dst->drvcall_perm_apply_list = malloc(size);
782 if (dst->drvcall_perm_apply_list == NULL) {
783 tloge("malloc for dst list failed\n");
784 return -1;
785 }
786
787 if (memcpy_s((void **)dst->drvcall_perm_apply_list, size, (void **)src->drvcall_perm_apply_list, size) != 0) {
788 tloge("memcpy for dst list failed\n");
789 free_drv_perm_apply_list(dst);
790 return -1;
791 }
792
793 dst->drvcall_perm_apply_list_size = src->drvcall_perm_apply_list_size;
794 return 0;
795 }
796
inherit_drv_node(struct task_tlv * tlv)797 static int32_t inherit_drv_node(struct task_tlv *tlv)
798 {
799 if (tlv == NULL || tlv->drv_conf == NULL) {
800 tloge("invalid node while inherit drv node\n");
801 return -1;
802 }
803
804 struct dlist_node *pos = NULL;
805
806 dlist_for_each(pos, &g_task_list) {
807 struct task_node *temp = dlist_entry(pos, struct task_node, node_list);
808 if (temp->tlv.drv_conf != NULL &&
809 strcmp(tlv->drv_conf->mani.service_name, temp->tlv.drv_conf->mani.service_name) == 0) {
810 if (copy_drv_conf_to_target(tlv->drv_conf, temp->tlv.drv_conf) != 0) {
811 tloge("copy drv conf to %s failed\n", tlv->drv_conf->mani.service_name);
812 return -1;
813 }
814
815 if (copy_drv_perm_apply_to_target(tlv, &temp->tlv) != 0) {
816 free_drv_conf_list(temp->tlv.drv_conf, RECEIVE_MAX_TAG);
817 tloge("copy drv perm to %s failed\n", tlv->drv_conf->mani.service_name);
818 return -1;
819 }
820
821 if (add_dynamic_policy_to_drv(&temp->tlv) != 0) {
822 free_drv_perm_apply_list(&temp->tlv);
823 tloge("add dynamic policy to drv failed\n");
824 free_drv_conf_list(temp->tlv.drv_conf, RECEIVE_MAX_TAG);
825 return -1;
826 }
827
828 return 0;
829 }
830 }
831
832 tloge("inherit drv conf %s failed\n", tlv->drv_conf->mani.service_name);
833 return -1;
834 }
835
836 /*
837 * must init all conf before add to list
838 * otherwise it maybe used by another thread when it add to list before init all conf
839 * something bind with uuid, such as policy, must be registered
840 * after check this node is valid in g_task_mtx lock
841 * because this uuid may have been registerd to this list if we not lock
842 */
receive_task_conf(struct task_node * node)843 int32_t receive_task_conf(struct task_node *node)
844 {
845 int32_t ret = -1;
846 if (node == NULL || (node->target_type != DRV_TARGET_TYPE && node->target_type != TA_TARGET_TYPE)) {
847 tloge("invalid node\n");
848 return ret;
849 }
850
851 if (drv_mutex_lock(&g_task_mtx) != 0) {
852 tloge("something wrong, get task mtx fail\n");
853 return ret;
854 }
855
856 if (check_hardware_type(node, HARDWARE_ENGINE_CRYPTO)) {
857 ret = inherit_drv_node(&node->tlv);
858 goto unlock_mtx;
859 }
860
861 if (node->target_type == DRV_TARGET_TYPE)
862 ret = receive_drv_conf(node);
863 else
864 ret = receive_ta_conf(node);
865
866 if (ret != 0)
867 goto unlock_mtx;
868
869 dlist_insert_tail(&node->node_list, &g_task_list);
870
871 ret = 0;
872
873 unlock_mtx:
874 if (pthread_mutex_unlock(&g_task_mtx) != 0)
875 tloge("something wrong, cannot unlock task mtx\n");
876
877 return ret;
878 }
879
free_drv_conf_by_service_name(const char * drv_name,uint32_t len)880 int32_t free_drv_conf_by_service_name(const char *drv_name, uint32_t len)
881 {
882 int32_t ret = -1;
883 bool free_flag = false;
884
885 if (drv_name == NULL || len == 0) {
886 tloge("free drv conf invalid param\n");
887 return -1;
888 }
889
890 if (drv_mutex_lock(&g_task_mtx) != 0) {
891 tloge("something wrong, get task mtx fail\n");
892 return -1;
893 }
894
895 struct task_node *node = find_node_by_name(drv_name, len);
896 if (node == NULL) {
897 tloge("cannot find drv:%s node\n", drv_name);
898 goto unlock_mtx;
899 }
900
901 /* ref_cnt is not zero means this drv node has been used by other, cannot free */
902 if (node->ref_cnt != 0) {
903 tloge("something wrong, drv:%s ref_cnt:%d cannot unregister\n", drv_name, node->ref_cnt);
904 goto unlock_mtx;
905 }
906
907 /*
908 * drv node not TASK_LOAD means it has been opened by other
909 * add this because ref_cnt may be zero in some cases:
910 * drv_node has been opened and closed in the same time
911 */
912 if (!is_state_match(node, TASK_LOAD)) {
913 tloge("something wrong, drv:%s state not match, cannot unregister\n", drv_name);
914 goto unlock_mtx;
915 }
916
917 dlist_delete(&node->node_list);
918 free_flag = true;
919 ret = 0;
920
921 unlock_mtx:
922 if (pthread_mutex_unlock(&g_task_mtx) != 0)
923 tloge("something wrong, cannot unlock task mtx\n");
924
925 if (free_flag)
926 free_task_node(node);
927
928 return ret;
929 }
930
find_drv_node_by_taskid(uint32_t exit_pid)931 struct task_node *find_drv_node_by_taskid(uint32_t exit_pid)
932 {
933 struct task_node *node = NULL;
934 if (drv_mutex_lock(&g_task_mtx) != 0) {
935 tloge("something wrong, get task mtx fail\n");
936 return NULL;
937 }
938
939 struct dlist_node *pos = NULL;
940 dlist_for_each(pos, &g_task_list) {
941 struct task_node *temp = dlist_entry(pos, struct task_node, node_list);
942 if (temp->target_type == DRV_TARGET_TYPE && taskid_to_pid(temp->pid) == taskid_to_pid(exit_pid)) {
943 tlogd("find drv taskid:0x%x uuid:0x%x\n", exit_pid, temp->tlv.uuid.timeLow);
944 node = temp;
945 break;
946 }
947 }
948
949 if (pthread_mutex_unlock(&g_task_mtx) != 0)
950 tloge("something wrong, unlock task mtx fail\n");
951
952 return node;
953 }
954
955 #ifdef TEE_SUPPORT_DYN_CONF_DEBUG
dump_task_state(struct task_node * node)956 static void dump_task_state(struct task_node *node)
957 {
958 static const char *task_state[] = {
959 "TASK_LOAD",
960 "TASK_SPAWN",
961 "TASK_NORMAL",
962 "TASK_SPAWN_FAIL",
963 "TASK_EXIT",
964 "UNKNOWN",
965 };
966
967 int32_t ret = drv_mutex_lock(&node->state_mtx);
968 if (ret != 0) {
969 tloge("get state mtx fail\n");
970 return;
971 }
972
973 int32_t state = node->state;
974
975 ret = pthread_mutex_unlock(&node->state_mtx);
976 if (ret != 0)
977 tloge("unlock state mtx fail\n");
978
979 int32_t index = state - TASK_LOAD;
980 if (index < 0 || index > (TASK_EXIT - TASK_LOAD))
981 index = TASK_EXIT - TASK_LOAD + 1;
982
983 tlogi("[task node] state:%s\n", task_state[index]);
984 }
985
dump_drv_task(const struct task_node * node)986 static void dump_drv_task(const struct task_node *node)
987 {
988 if (node->target_type != DRV_TARGET_TYPE)
989 return;
990
991 tlogi("[drv task] index:%u channel:0x%llx\n",
992 node->drv_task.drv_index, node->drv_task.channel);
993
994 if (node->tlv.drv_conf == NULL) {
995 tloge("something wrong, not drv conf invalid\n");
996 return;
997 }
998
999 dump_drv_conf(node->tlv.drv_conf);
1000 }
1001
dump_drvcall_perm(const struct task_tlv * tlv)1002 static void dump_drvcall_perm(const struct task_tlv *tlv)
1003 {
1004 if (tlv->drvcall_perm_apply_list == NULL || tlv->drvcall_perm_apply_list_size == 0) {
1005 tlogi("[drvcall dyn conf] has nothing\n");
1006 return;
1007 }
1008
1009 uint32_t i;
1010
1011 for (i = 0; i < tlv->drvcall_perm_apply_list_size; i++) {
1012 struct drvcall_perm_apply_item_t item = tlv->drvcall_perm_apply_list[i];
1013 tlogi("[drvcall dyn conf] drv_name = %s, perm 0x%llx\n", item.name, (unsigned long long)item.perm);
1014 }
1015 }
1016
dump_task_node(void)1017 void dump_task_node(void)
1018 {
1019 if (drv_mutex_lock(&g_task_mtx) != 0) {
1020 tloge("something wrong, get task mtx fail\n");
1021 return;
1022 }
1023
1024 struct dlist_node *pos = NULL;
1025 dlist_for_each(pos, &g_task_list) {
1026 struct task_node *temp = dlist_entry(pos, struct task_node, node_list);
1027 tlogi("[task node begin] uuid:0x%x pid:0x%x type:%s ref_cnt:%u\n", temp->tlv.uuid.timeLow, temp->pid,
1028 (temp->target_type == DRV_TARGET_TYPE) ? "DRV" : "TA", temp->ref_cnt);
1029 dump_task_state(temp);
1030 dump_drvcall_perm(&temp->tlv);
1031 dump_drv_task(temp);
1032 dump_drvcall_fd(temp);
1033 }
1034
1035 if (pthread_mutex_unlock(&g_task_mtx) != 0)
1036 tloge("something wrong, cannot unlock task mtx\n");
1037 }
1038 #endif
1039