• 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_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, &params->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