• 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 #include "drv_operations.h"
13 #include <stdint.h>
14 #include <securec.h>
15 #include <dlist.h>
16 #include <ipclib.h>
17 #include <tee_log.h>
18 #include <tee_bitmap.h>
19 #include <drv.h>
20 #include <tee_drv_internal.h>
21 #include <spawn_ext.h>
22 #include "tee_driver_module.h"
23 #include "tee_drv_entry.h"
24 #include "drv_param_ops.h"
25 
26 struct drv_cmd_perm {
27     struct drv_cmd_perm_info_t *base_vaddr;
28     uint32_t cmd_num;
29 };
30 
31 static struct drv_cmd_perm g_cmd_perm = {
32     .base_vaddr = NULL,
33     .cmd_num = 0,
34 };
35 static struct dlist_node g_drv_node = dlist_head_init(g_drv_node);
36 static pthread_mutex_t g_drv_mtx = PTHREAD_MUTEX_INITIALIZER;
37 
38 static uint8_t g_fd_bitmap[(FD_COUNT_MAX) >> MOVE_BIT];
39 static pthread_mutex_t g_fd_mtx = PTHREAD_MUTEX_INITIALIZER;
40 static void task_dump_fd(const struct drv_task *task);
41 
42 /*
43  * used when get_drv_task in driver_open
44  * will put one once operation are succeeded, and put another one in driver_close
45  */
46 #define DRV_TASK_OPEN_REF_CNT_STEP 2U
47 
drv_mutex_lock(pthread_mutex_t * mtx)48 int32_t drv_mutex_lock(pthread_mutex_t *mtx)
49 {
50     if (mtx == NULL)
51         return -1;
52 
53     int32_t ret = pthread_mutex_lock(mtx);
54 
55     return ret;
56 }
57 
drv_mutex_init(pthread_mutex_t * mtx)58 static int32_t drv_mutex_init(pthread_mutex_t *mtx)
59 {
60     int32_t ret;
61 
62     if (mtx == NULL) {
63         tloge("invalid mtx\n");
64         return -1;
65     }
66 
67     ret = pthread_mutex_init(mtx, NULL);
68     if (ret != 0) {
69         tloge("pthread mutex init failed with ret:%d\n", ret);
70     }
71 
72     return ret;
73 }
74 
75 /*
76  * this function is locked by g_drv_mtx
77  * so it can add to g_drv_node directly when alloc succ
78  */
alloc_and_add_drv_task(uint32_t pid)79 static struct drv_task *alloc_and_add_drv_task(uint32_t pid)
80 {
81     struct drv_task *new_task = malloc(sizeof(*new_task));
82     if (new_task == NULL) {
83         tloge("alloc new task failed\n");
84         return NULL;
85     }
86 
87     (void)memset_s(new_task, sizeof(*new_task), 0, sizeof(*new_task));
88 
89     dlist_init(&new_task->task_list);
90     new_task->task_pid = pid;
91     new_task->task_count = 0;
92     new_task->ref_cnt = DRV_TASK_OPEN_REF_CNT_STEP;
93     dlist_init(&new_task->data_head);
94 
95     int32_t ret = drv_mutex_init(&new_task->task_mtx);
96     if (ret != 0) {
97         free(new_task);
98         tloge("init task_mtx failed\n");
99         return NULL;
100     }
101 
102     dlist_insert_tail(&new_task->task_list, &g_drv_node);
103 
104     return new_task;
105 }
106 
update_drv_task_ref_cnt(struct drv_task * task,bool open)107 static int32_t update_drv_task_ref_cnt(struct drv_task *task, bool open)
108 {
109     if (open) {
110         if (task->ref_cnt >= (UINT32_MAX - DRV_TASK_OPEN_REF_CNT_STEP)) {
111             tloge("something wrong, pid:%u drv task ref_cnt:%u is overflow\n",
112                 task->task_pid, task->ref_cnt);
113             return -1;
114         }
115 
116         task->ref_cnt += DRV_TASK_OPEN_REF_CNT_STEP;
117         return 0;
118     }
119 
120     if (task->ref_cnt == UINT32_MAX) {
121         tloge("something wrong, pid:%u drv task ref_cnt is overflow\n", task->task_pid);
122         return -1;
123     }
124 
125     task->ref_cnt++;
126     return 0;
127 }
128 
find_and_get_drv_task_locked(uint32_t pid,bool open)129 static struct drv_task *find_and_get_drv_task_locked(uint32_t pid, bool open)
130 {
131     struct drv_task *task = NULL;
132     bool find_flag = false;
133 
134     int32_t ret = drv_mutex_lock(&g_drv_mtx);
135     if (ret != 0) {
136         tloge("lock drv mtx failed\n");
137         return task;
138     }
139 
140     struct dlist_node *pos = NULL;
141     struct dlist_node *next = NULL;
142     struct drv_task *temp = NULL;
143 
144     dlist_for_each_safe(pos, next, &g_drv_node) {
145         temp = dlist_entry(pos, struct drv_task, task_list);
146         if (temp->task_pid == pid) {
147             find_flag = true;
148             tlogd("find pid:%u\n", pid);
149             ret = update_drv_task_ref_cnt(temp, open);
150             if (ret != 0) {
151                 tloge("update drv task ref_cnt failed, pid:%u\n", pid);
152                 break;
153             }
154             task = temp;
155             break;
156         }
157     }
158 
159     /*
160      * when cannot find drv task in driver_open
161      * should create it
162      */
163     if (!find_flag && open) {
164         tlogd("cannot find task:%u in open, create it\n", pid);
165         task = alloc_and_add_drv_task(pid);
166     }
167 
168     ret = pthread_mutex_unlock(&g_drv_mtx);
169     if (ret != 0)
170         tloge("unlock drv mtx failed\n");
171 
172     return task;
173 }
174 
free_drv_task(struct drv_task * task)175 static void free_drv_task(struct drv_task *task)
176 {
177     free(task);
178 }
179 
put_drv_task_locked(struct drv_task * task,uint32_t put_cnt)180 static void put_drv_task_locked(struct drv_task *task, uint32_t put_cnt)
181 {
182     bool free_flag = false;
183 
184     int32_t ret = drv_mutex_lock(&g_drv_mtx);
185     if (ret != 0) {
186         tloge("lock drv mtx failed\n");
187         return;
188     }
189 
190     if (task->ref_cnt < put_cnt)
191         tloge("something wrong, pid:%u task ref_cnt:%u small than put_cnt:%u\n",
192             task->task_pid, task->ref_cnt, put_cnt);
193     else
194         task->ref_cnt = task->ref_cnt - put_cnt;
195 
196     if (task->ref_cnt == 0) {
197         dlist_delete(&task->task_list);
198         free_flag = true;
199     }
200 
201     ret = pthread_mutex_unlock(&g_drv_mtx);
202     if (ret != 0)
203         tloge("unlock drv mtx failed\n");
204 
205     if (free_flag)
206         free_drv_task(task);
207 }
208 
inc_fd_ref_locked(struct fd_data * data)209 static int32_t inc_fd_ref_locked(struct fd_data *data)
210 {
211     int32_t func_ret = -1;
212     int32_t ret = drv_mutex_lock(&data->ref_mtx);
213     if (ret != 0) {
214         tloge("get ref mtx fail\n");
215         return -1;
216     }
217 
218     if (data->ref_cnt == UINT32_MAX) {
219         tloge("something wrong, fd:%d ref cnt is overflow\n", data->drv.fd);
220     } else {
221         data->ref_cnt++;
222         func_ret = 0;
223     }
224 
225     ret = pthread_mutex_unlock(&data->ref_mtx);
226     if (ret != 0)
227         tloge("something wrong, unlock ref mtx fail\n");
228 
229     return func_ret;
230 }
231 
dec_fd_ref_locked(struct fd_data * data)232 static void dec_fd_ref_locked(struct fd_data *data)
233 {
234     int32_t ret = drv_mutex_lock(&data->ref_mtx);
235     if (ret != 0) {
236         tloge("dec fd ref get mtx fail\n");
237         return;
238     }
239 
240     if (data->ref_cnt == 0) {
241         tloge("something wrong, fd:%d ref cnt is 0, cannot put\n", data->drv.fd);
242     } else {
243         data->ref_cnt--;
244         tlogd("fd:%d ref_cnt:%u after dec\n", data->drv.fd, data->ref_cnt);
245     }
246 
247     if (data->ref_cnt == 0) {
248         tloge("fd:%d is closed before ioctl, signal other thread\n", data->drv.fd);
249         ret = pthread_cond_signal(&data->ref_cond);
250         if (ret != 0)
251             tloge("fd:%d signal to other thread fail:0x%x\n", data->drv.fd, ret);
252     }
253 
254     ret = pthread_mutex_unlock(&data->ref_mtx);
255     if (ret != 0)
256         tloge("something wrong, dec fd unlock ref mtx fail\n");
257 }
258 
find_fd_data(int32_t fd,const struct tee_uuid * uuid,const struct drv_task * task)259 static struct fd_data *find_fd_data(int32_t fd, const struct tee_uuid *uuid, const struct drv_task *task)
260 {
261     struct fd_data *data = NULL;
262 
263     struct dlist_node *pos = NULL;
264     struct dlist_node *next = NULL;
265     struct fd_data *temp = NULL;
266 
267     dlist_for_each_safe(pos, next, &task->data_head) {
268         temp = dlist_entry(pos, struct fd_data, data_list);
269         if (temp->drv.fd == fd) {
270             /*
271              * compare uuid to avoid this case:
272              * when task(pid1) crash, driver_close_fd_by_pid will call by gtask in cpux,
273              * and in cpuy, it may just receive pid1 drv_open cmd,
274              * when cpux handle the cmd before cpuy, although cpuy will call driver_close_fd
275              * after ipc_msg_reply fail, the fd1 opened by cpuy can be get from pid1
276              * since it will be added to pid1 task_drv in driver_open_fd.
277              * If the pid1 is reused by another ta, and this ta call drv_ioctl(fd1) maliciously,
278              * it cannot auth in driver. So, compare uuid after fd is matched, it can limit only
279              * the same ta used this fd. In this case, it has no effect for driver.
280              * And at the same time, it reduces the probability of reuse pid significantly
281              * since the same pid used by the same uuid.
282              */
283             if (memcmp(uuid, &temp->drv.uuid, sizeof(*uuid)) == 0) {
284                 tlogd("find fd:%d\n", fd);
285                 data = temp;
286                 break;
287             }
288 
289             tloge("find fd:%d which owner uuid:0x%x not match caller 0x%x",
290                 fd, temp->drv.uuid.timeLow, uuid->timeLow);
291             break;
292         }
293     }
294 
295     return data;
296 }
297 
find_and_get_fd_data_locked(int32_t fd,const struct tee_uuid * uuid,struct drv_task * task)298 static struct fd_data *find_and_get_fd_data_locked(int32_t fd,
299     const struct tee_uuid *uuid, struct drv_task *task)
300 {
301     struct fd_data *data = NULL;
302 
303     int32_t ret = drv_mutex_lock(&task->task_mtx);
304     if (ret != 0) {
305         tloge("lock task mtx failed\n");
306         return NULL;
307     }
308 
309     data = find_fd_data(fd, uuid, task);
310     if (data == NULL) {
311         tloge("cannot find fd:%d\n", fd);
312         goto unlock_task_mtx;
313     }
314 
315     if (inc_fd_ref_locked(data) != 0) {
316         tloge("something wrong, task:%u cannot inc fd ref\n", task->task_pid);
317         data = NULL;
318     }
319 
320 unlock_task_mtx:
321     ret = pthread_mutex_unlock(&task->task_mtx);
322     if (ret != 0)
323         tloge("unlock task mtx failed\n");
324 
325     return data;
326 }
327 
dec_task_count(struct drv_task * task)328 static void dec_task_count(struct drv_task *task)
329 {
330     if (task->task_count == 0)
331         tloge("something wrong, task:%u task_count is zero, cannot put\n", task->task_count);
332     else
333         task->task_count--;
334 }
335 
find_and_del_fd_data_locked(int32_t fd,const struct tee_uuid * uuid,struct drv_task * task)336 static struct fd_data *find_and_del_fd_data_locked(int32_t fd,
337     const struct tee_uuid *uuid, struct drv_task *task)
338 {
339     struct fd_data *data = NULL;
340 
341     int32_t ret = drv_mutex_lock(&task->task_mtx);
342     if (ret != 0) {
343         tloge("del lock task mtx failed\n");
344         return NULL;
345     }
346 
347     data = find_fd_data(fd, uuid, task);
348     if (data == NULL) {
349         tloge("del cannot find fd:%d\n", fd);
350         goto unlock_task_mtx;
351     }
352 
353     dec_task_count(task);
354     dlist_delete(&data->data_list);
355 
356 unlock_task_mtx:
357     ret = pthread_mutex_unlock(&task->task_mtx);
358     if (ret != 0)
359         tloge("del unlock task mtx failed\n");
360 
361     return data;
362 }
363 
free_fd_data(struct fd_data * data)364 static void free_fd_data(struct fd_data *data)
365 {
366     int32_t fd = data->drv.fd;
367 
368     free(data);
369     data = NULL;
370 
371     int32_t ret = drv_mutex_lock(&g_fd_mtx);
372     if (ret != 0) {
373         tloge("lock fd mtx failed, cannot clear fd:%d\n", fd);
374         return;
375     }
376 
377     clear_bitmap(g_fd_bitmap, FD_COUNT_MAX, (fd - 1));
378 
379     ret = pthread_mutex_unlock(&g_fd_mtx);
380     if (ret != 0)
381         tloge("unlock fd mtx failed\n");
382 }
383 
close_and_free_fd_data(struct fd_data * data)384 static void close_and_free_fd_data(struct fd_data *data)
385 {
386     const struct tee_driver_module *drv_func = get_drv_func();
387 
388     if (drv_func == NULL || drv_func->close == NULL) {
389         tloge("something wrong, fd:%d has invalid drv func\n", data->drv.fd);
390     } else {
391         /*
392          * do not dlclose so since drv not support load so dynamically,
393          * once it support, should dlclose after call so close function,
394          * and in this case, should add ref_cnt in so structure,
395          * when ref_cnt is zero, should delete so from so list and dlclose it
396          */
397         int64_t ret = drv_func->close(&data->drv);
398         if (ret != 0)
399             tloge("drv close fd:%d failed ret:0x%llx\n", data->drv.fd, ret);
400     }
401 
402     free_fd_data(data);
403 }
404 
close_fd_data_locked(struct fd_data * data)405 static void close_fd_data_locked(struct fd_data *data)
406 {
407     bool free_flag = true;
408     int32_t ret = drv_mutex_lock(&data->ref_mtx);
409     if (ret != 0) {
410         tloge("something wrong, close fd get ref mtx fail\n");
411         return;
412     }
413 
414     if (data->ref_cnt == 0) {
415         tloge("something wrong, fd:%d ref cnt is zero\n", data->drv.fd);
416     } else {
417         data->ref_cnt--;
418         while (data->ref_cnt != 0) {
419             tloge("fd:%d is used by other, cannot close, just wait\n", data->drv.fd);
420             ret = pthread_cond_wait(&data->ref_cond, &data->ref_mtx);
421             if (ret != 0) {
422                 tloge("something wrong, fd:%d cond wait fail:0x%x\n", data->drv.fd, ret);
423                 free_flag = false;
424                 goto unlock_ref_mtx;
425             }
426         }
427     }
428 
429 unlock_ref_mtx:
430     ret = pthread_mutex_unlock(&data->ref_mtx);
431     if (ret != 0)
432         tloge("something wrong, unlock ref fail\n");
433 
434     if (free_flag)
435         close_and_free_fd_data(data);
436 }
437 
alloc_fd(void)438 static int32_t alloc_fd(void)
439 {
440     int32_t ret = drv_mutex_lock(&g_fd_mtx);
441     if (ret != 0) {
442         tloge("get mtx failed\n");
443         return -1;
444     }
445 
446     int32_t fd = get_valid_bit(g_fd_bitmap, FD_COUNT_MAX);
447     if (fd == -1) {
448         tloge("cannot get fd bit, and dump in fd mtx\n");
449         driver_dump();
450         ret = pthread_mutex_unlock(&g_fd_mtx);
451         if (ret != 0)
452             tloge("unlock fd failed ret:%d\n", ret);
453         return -1;
454     }
455 
456     set_bitmap(g_fd_bitmap, FD_COUNT_MAX, fd);
457 
458     ret = pthread_mutex_unlock(&g_fd_mtx);
459     if (ret != 0)
460         tloge("unlock fd failed ret:%d\n", ret);
461 
462     return (fd + 1); /* cannot start from 0 */
463 }
464 
get_caller_uuid(const struct tee_drv_param * params,struct tee_uuid * caller_uuid)465 static int32_t get_caller_uuid(const struct tee_drv_param *params, struct tee_uuid *caller_uuid)
466 {
467     uint64_t *args = (uint64_t *)(uintptr_t)(params->args);
468     uint64_t uuid_time = args[DRV_UUID_TIME_INDEX];
469     uint64_t uuid_clock = args[DRV_UUID_CLOCK_INDEX];
470 
471     struct tee_uuid uuid;
472     (void)memset_s(&uuid, sizeof(uuid), 0, sizeof(uuid));
473     uuid.timeLow = (uuid_time >> UUID_TIME_LOW_OFFSET) & UUID_TIME_LOW_MASK;
474     uuid.timeMid = (uuid_time >> UUID_TIME_MID_OFFSET) & UUID_TIME_MASK;
475     uuid.timeHiAndVersion = uuid_time & UUID_TIME_MASK;
476 
477     uint32_t i;
478     for (i = 0; i < NODE_LEN; i++) {
479         uuid.clockSeqAndNode[NODE_LEN - i - 1] =  uuid_clock & UUID_TIME_CLOCK_MASK;
480         uuid_clock >>= BITS_NUM_PER_BYTE;
481     }
482 
483     if (memcpy_s(caller_uuid, sizeof(*caller_uuid), &uuid, sizeof(uuid)) != 0) {
484         tloge("copy uuid:0x%x fail\n", uuid.timeLow);
485         return -1;
486     }
487 
488     return 0;
489 }
490 
alloc_fd_data(uint32_t caller_taskid,const struct tee_drv_param * params,int32_t * fd_out)491 static struct fd_data *alloc_fd_data(uint32_t caller_taskid, const struct tee_drv_param *params, int32_t *fd_out)
492 {
493     struct fd_data *data = malloc(sizeof(*data));
494     if (data == NULL) {
495         tloge("alloc data failed\n");
496         return NULL;
497     }
498 
499     (void)memset_s(data, sizeof(*data), 0, sizeof(*data));
500     int32_t ret = get_caller_uuid(params, &(data->drv.uuid));
501     if (ret != 0) {
502         tloge("copy pid:%u uuid to fd failed\n", params->caller_pid);
503         goto free_data;
504     }
505 
506     if (pthread_cond_init(&data->ref_cond, NULL) != 0) {
507         tloge("ref cond init fail\n");
508         goto free_data;
509     }
510 
511     if (drv_mutex_init(&data->ref_mtx) != 0) {
512         tloge("ref mtx init fail\n");
513         goto free_data;
514     }
515 
516     int32_t fd = alloc_fd();
517     if (fd <= 0)
518         goto free_data;
519 
520     uint64_t *args = (uint64_t *)(uintptr_t)params->args;
521 
522     *fd_out = fd;
523     dlist_init(&data->data_list);
524     data->drv.fd = fd;
525     data->drv.taskid = caller_taskid;
526     data->drv.private_data = NULL;
527     data->ref_cnt = 1;
528     data->cmd_perm = args[DRV_PERM_INDEX];
529 
530     return data;
531 
532 free_data:
533     free(data);
534     return NULL;
535 }
536 
add_fd_data_locked(struct fd_data * data,struct drv_task * task)537 static int64_t add_fd_data_locked(struct fd_data *data, struct drv_task *task)
538 {
539     int32_t ret = drv_mutex_lock(&task->task_mtx);
540     if (ret != 0) {
541         tloge("get task mtx failed\n");
542         return -1;
543     }
544 
545     dlist_insert_tail(&data->data_list, &task->data_head);
546 
547     ret = pthread_mutex_unlock(&task->task_mtx);
548     if (ret != 0)
549         tloge("unlock task mtx failed\n");
550 
551     return 0;
552 }
553 
get_task_count(struct drv_task * task)554 static int32_t get_task_count(struct drv_task *task)
555 {
556     int32_t func_ret = -1;
557 
558     int32_t ret = drv_mutex_lock(&task->task_mtx);
559     if (ret != 0) {
560         tloge("check task count get drv mtx failed\n");
561         return -1;
562     }
563 
564     if (task->task_count >= TASK_FD_COUNT_MAX) {
565         tloge("task:%u task_count:%u is overflow, max:%u\n",
566             task->task_pid, task->task_count, TASK_FD_COUNT_MAX);
567         task_dump_fd(task);
568     } else {
569         /*
570          * add one to task_count when find drv_task in driver_open
571          * in order to reduce the probability of failure
572          * when add fd_data to drv_task after call dirver module open function
573          */
574         task->task_count++;
575         func_ret = 0;
576     }
577 
578     ret = pthread_mutex_unlock(&task->task_mtx);
579     if (ret != 0)
580         tloge("check task count unlock drv mtx failed\n");
581 
582     return func_ret;
583 }
584 
put_task_count(struct drv_task * task)585 static void put_task_count(struct drv_task *task)
586 {
587     int32_t ret = drv_mutex_lock(&task->task_mtx);
588     if (ret != 0) {
589         tloge("check task count get drv mtx failed\n");
590         return;
591     }
592 
593     dec_task_count(task);
594 
595     ret = pthread_mutex_unlock(&task->task_mtx);
596     if (ret != 0)
597         tloge("check task count unlock drv mtx failed\n");
598 }
599 
open_param_check(const struct tee_drv_param * params,const struct tee_driver_module * drv_func)600 static int32_t open_param_check(const struct tee_drv_param *params, const struct tee_driver_module *drv_func)
601 {
602     if (params == NULL || params->args == 0) {
603         tloge("open invalid param\n");
604         return -1;
605     }
606 
607     if (drv_func == NULL) {
608         tloge("invalid drv func\n");
609         return -1;
610     }
611 
612     if (drv_func->open == NULL) {
613         tloge("no open func\n");
614         return -1;
615     }
616 
617     if (drv_func->close == NULL) { /* called in exception branch */
618         tloge("no close func\n");
619         return -1;
620     }
621 
622     return 0;
623 }
624 
get_drv_param(const struct tee_drv_param * params,uint64_t ** args_base,uint32_t * args_len)625 static int32_t get_drv_param(const struct tee_drv_param *params, uint64_t **args_base, uint32_t *args_len)
626 {
627     uint64_t *args = (uint64_t *)(uintptr_t)(params->args);
628     char *indata = (char *)(uintptr_t)params->data;
629     uint64_t param_len = args[DRV_PARAM_LEN_INDEX];
630     uint64_t param_offset = args[DRV_PARAM_INDEX];
631 
632     /* it may have no param */
633     if (param_len == 0) {
634         tlogd("input NULL param\n");
635         *args_base = NULL;
636         *args_len = 0;
637         return 0;
638     }
639 
640     if (param_len > (SYSCAL_MSG_BUFFER_SIZE - sizeof(struct drv_req_msg_t))) {
641         tloge("param_len:0x%llx is invalid\n", param_len);
642         return -1;
643     }
644 
645     if (param_offset != 0) {
646         tloge("invalid param_offset:0x%llx\n", param_offset);
647         return -1;
648     }
649 
650     if (indata == NULL) {
651         tloge("invalid param_indata\n");
652         return -1;
653     }
654 
655     uint64_t *param_buffer = malloc(param_len);
656     if (param_buffer == 0) {
657         tloge("malloc for param_buffer:0x%llx failed\n", param_len);
658         return -1;
659     }
660 
661     if (memcpy_s(param_buffer, param_len, indata, param_len) != EOK) {
662         tloge("copy param_buffer failed\n");
663         free(param_buffer);
664         return -1;
665     }
666 
667     *args_base = param_buffer;
668     *args_len = param_len;
669     return 0;
670 }
671 
free_drv_args(uint64_t * args)672 static void free_drv_args(uint64_t *args)
673 {
674     if (args != NULL)
675         free(args);
676 }
677 
get_open_param(const struct tee_drv_param * params,const struct tee_driver_module * drv_func,uint64_t ** arg,uint32_t * arg_len)678 static int32_t get_open_param(const struct tee_drv_param *params, const struct tee_driver_module *drv_func,
679     uint64_t **arg, uint32_t *arg_len)
680 {
681     if (open_param_check(params, drv_func) != 0)
682         return -1;
683 
684     if (get_drv_param(params, arg, arg_len) != 0) {
685         tloge("open get param failed\n");
686         return -1;
687     }
688 
689     return 0;
690 }
691 
get_drv_open_task(uint32_t pid,struct drv_task ** open_task)692 static int32_t get_drv_open_task(uint32_t pid, struct drv_task **open_task)
693 {
694     struct drv_task *task = find_and_get_drv_task_locked(pid, true);
695     if (task == NULL) {
696         tloge("pid:%u cannot open this driver\n", pid);
697         return -1;
698     }
699 
700     int32_t ret = get_task_count(task);
701     if (ret != 0) {
702         tloge("task open fd is overflow, cannot open");
703         put_drv_task_locked(task, DRV_TASK_OPEN_REF_CNT_STEP);
704         return -1;
705     }
706 
707     *open_task = task;
708 
709     return 0;
710 }
711 
driver_open(const struct tee_drv_param * params,const struct tee_driver_module * drv_func)712 int64_t driver_open(const struct tee_drv_param *params, const struct tee_driver_module *drv_func)
713 {
714     uint64_t *input_args = NULL;
715     uint32_t input_args_len = 0;
716 
717     if (get_open_param(params, drv_func, &input_args, &input_args_len) != 0)
718         return -1;
719 
720     uint64_t *args = (uint64_t *)(uintptr_t)params->args;
721     uint32_t pid = taskid_to_pid(args[CALLER_TASKID_INDEX]);
722     struct drv_task *task = NULL;
723     if (get_drv_open_task(pid, &task) != 0) {
724         free_drv_args(input_args);
725         return -1;
726     }
727 
728     int32_t fd = -1;
729     struct fd_data *data = alloc_fd_data(args[CALLER_TASKID_INDEX], params, &fd);
730     if (data == NULL)
731         goto alloc_fd_failed;
732 
733     int64_t ret = drv_func->open(&data->drv, (unsigned long)(uintptr_t)input_args, input_args_len);
734     if (ret != 0) {
735         tloge("open fd ret:0x%llx\n", ret);
736         goto open_fd_failed;
737     }
738 
739     /*
740      * add to list after open can limit ioctl/close cannot get fd_data
741      * before call open in concurrent scene
742      */
743     ret = add_fd_data_locked(data, task);
744     if (ret != 0)
745         goto add_fd_failed;
746 
747     put_drv_task_locked(task, 1);
748 
749     tlogd("caller taskid:0x%x alloc new fd:%d\n", pid, fd);
750     free_drv_args(input_args);
751 
752     /*
753      * cannot return fd from data->drv.fd in case of use after free of data.
754      * cpux call driver_open_fd, cpuy receive task exit signal from gtask,
755      * when cpux alloc fd and add to drv_task, cpuy will free all fd data in this drv_task
756      * and in this case, cpux may return fd after cpuy free all fd data,
757      * since it not atomic between add fd data to drv_task and return fd to caller.
758      * use local variable fd as return value after cpuy free all fd data,
759      * cpux will ipc_msg_reply fail to ta since this ta has been killed by gtask
760      */
761     return (int64_t)fd;
762 
763 add_fd_failed:
764     ret = drv_func->close(&data->drv);
765     if (ret != 0)
766         tloge("caller pid:0x%x close fd:%d failed ret:0x%llx\n", pid, data->drv.fd, ret);
767 
768 open_fd_failed:
769     free_fd_data(data);
770 
771 alloc_fd_failed:
772     /*
773      * pair with get_task_count after get drv_task
774      * should call before put_drv_task_locked
775      */
776     put_task_count(task);
777     put_drv_task_locked(task, DRV_TASK_OPEN_REF_CNT_STEP);
778     free_drv_args(input_args);
779 
780     return -1;
781 }
782 
check_fd_invalid(uint64_t fd)783 static bool check_fd_invalid(uint64_t fd)
784 {
785     uint32_t drv_index = (uint32_t)((fd >> DRV_INDEX_OFFSET) & DRV_INDEX_MASK);
786     uint32_t orig_index = get_drv_index();
787     if (drv_index != orig_index) {
788         tloge("invalid fd drv_index:0x%x orig_index:0x%x\n", drv_index, orig_index);
789         return true;
790     }
791 
792     fd = fd & DRV_FD_MASK;
793     if (fd == 0 || fd > FD_COUNT_MAX) {
794         tloge("invalid fd:0x%llx\n", fd);
795         return true;
796     }
797 
798     return false;
799 }
800 
ioctl_param_check(uint64_t fd,const struct tee_drv_param * params,const int64_t * fn_ret)801 static int32_t ioctl_param_check(uint64_t fd, const struct tee_drv_param *params, const int64_t *fn_ret)
802 {
803     if (params == NULL || params->args == 0 || fn_ret == NULL) {
804         tloge("ioctl invalid params\n");
805         return -1;
806     }
807 
808     if (check_fd_invalid(fd))
809         return -1;
810 
811     return 0;
812 }
813 
get_ioctl_param(uint64_t fd,struct tee_drv_param * params,const int64_t * fn_ret,uint64_t ** arg,uint32_t * arg_len)814 static int32_t get_ioctl_param(uint64_t fd, struct tee_drv_param *params,
815     const int64_t *fn_ret, uint64_t **arg, uint32_t *arg_len)
816 {
817     if (ioctl_param_check(fd, params, fn_ret) != 0)
818         return -1;
819 
820     spawn_uuid_t uuid;
821     uint32_t pid = taskid_to_pid(params->caller_pid);
822     int32_t ret = getuuid(pid, &uuid);
823     if (ret != 0) {
824         tloge("get pid:%u uuid failed\n", pid);
825         return -1;
826     }
827 
828     ret = memcpy_s(&(params->uuid), sizeof(params->uuid), &uuid.uuid, sizeof(uuid.uuid));
829     if (ret != 0) {
830         tloge("copy pid:%u uuid to params failed\n", pid);
831         return -1;
832     }
833 
834     if (get_drv_param(params, arg, arg_len) != 0) {
835         tloge("ioctl get param failed\n");
836         return -1;
837     }
838 
839     return 0;
840 }
841 
ioctl_auth_check(uint32_t cmd,const struct fd_data * data)842 static bool ioctl_auth_check(uint32_t cmd, const struct fd_data *data)
843 {
844     uint32_t i;
845     uint64_t cmd_perm = 0;
846 
847     for (i = 0; i < g_cmd_perm.cmd_num; i++) {
848         struct drv_cmd_perm_info_t item = g_cmd_perm.base_vaddr[i];
849         if (item.cmd == cmd) {
850             cmd_perm = item.perm;
851             break;
852         }
853     }
854 
855     if (i == g_cmd_perm.cmd_num) {
856         tlogd("cmd has no perm\n");
857         return true;
858     }
859 
860     tlogd("cmd:0x%x need perm:0x%llx, fd cmd 0x%llx\n", cmd, cmd_perm, data->cmd_perm);
861 
862     if ((cmd_perm & data->cmd_perm) != 0)
863         return true;
864 
865     tloge("cmd:0x%x need perm:0x%llx not 0x%llx\n", cmd, cmd_perm, data->cmd_perm);
866     return false;
867 }
868 
driver_ioctl(uint64_t fd,struct tee_drv_param * params,const struct tee_driver_module * drv_func,int64_t * fn_ret)869 int64_t driver_ioctl(uint64_t fd, struct tee_drv_param *params,
870     const struct tee_driver_module *drv_func, int64_t *fn_ret)
871 {
872     if (drv_func == NULL || drv_func->ioctl == NULL) {
873         tloge("invalid ioctl func\n");
874         return -1;
875     }
876 
877     uint64_t *input_args = NULL;
878     uint32_t input_args_len = 0;
879     int64_t ret;
880 
881     if (get_ioctl_param(fd, params, fn_ret, &input_args, &input_args_len) != 0)
882         return -1;
883 
884     uint64_t *args = (uint64_t *)(uintptr_t)params->args;
885     uint32_t pid = taskid_to_pid(params->caller_pid);
886     struct drv_task *task = find_and_get_drv_task_locked(pid, false);
887     if (task == NULL) {
888         tloge("task:%u has not open this driver, cannot ioctl\n", pid);
889         free_drv_args(input_args);
890         return -1;
891     }
892 
893     struct fd_data *data = find_and_get_fd_data_locked((int32_t)(fd & DRV_FD_MASK), &(params->uuid), task);
894     if (data == NULL) {
895         put_drv_task_locked(task, 1);
896         tloge("task:%u has not open fd:%d, cannot ioctl\n", pid, (int32_t)(fd & DRV_FD_MASK));
897         free_drv_args(input_args);
898         return -1;
899     }
900 
901     tlogd("task:%u taskid:0x%x ioctl fd:%d\n", pid, params->caller_pid, data->drv.fd);
902 
903     if (!ioctl_auth_check((uint32_t)args[DRV_CMD_ID_INDEX], data)) {
904         ret = -1;
905         goto err_put;
906     }
907 
908     ret = drv_func->ioctl(&data->drv,
909         (uint32_t)args[DRV_CMD_ID_INDEX], (unsigned long)(uintptr_t)input_args, input_args_len);
910 
911     *fn_ret = ret;
912     ret = 0;
913 
914 err_put:
915     dec_fd_ref_locked(data);
916     put_drv_task_locked(task, 1);
917     free_drv_args(input_args);
918 
919     return ret;
920 }
921 
close_param_check(uint64_t fd,const struct tee_drv_param * params)922 static int32_t close_param_check(uint64_t fd, const struct tee_drv_param *params)
923 {
924     if (params == NULL || params->args == 0) {
925         tloge("invalid params\n");
926         return -1;
927     }
928 
929     if (check_fd_invalid(fd))
930         return -1;
931 
932     return 0;
933 }
934 
driver_close(uint64_t fd,const struct tee_drv_param * params)935 int64_t driver_close(uint64_t fd, const struct tee_drv_param *params)
936 {
937     if (close_param_check(fd, params) != 0)
938         return -1;
939 
940     struct tee_uuid uuid;
941     if (get_caller_uuid(params, &uuid) != 0)
942         return -1;
943 
944     uint64_t *args = (uint64_t *)(uintptr_t)params->args;
945     uint32_t pid = taskid_to_pid(args[CALLER_TASKID_INDEX]);
946     struct drv_task *task = find_and_get_drv_task_locked(pid, false);
947     if (task == NULL) {
948         tloge("task:%u has not open this driver, cannot close\n", pid);
949         return -1;
950     }
951 
952     /*
953      * In order to discard whether the driver ioctl function is stucked,
954      * the close function registerd by driver must be called during the close execution flow.
955      * So in close entry, the flow is below:
956      * 1. find and delete the fd_data from task node
957      * 2. wait fd_data's ref_cnt to 0 (if ioctl flow has not be exited, the ref_cnt cannot be 0)
958      * 3. call close func registerd by driver and release fd resource
959      * And in ioctl entry, the flow is below:
960      * 1. find and get the fd_data
961      * 2. call ioctl func registerd by driver
962      * 3. put fd_data, and signal to other thread if the fd_data's ref_cnt is 0
963      */
964     struct fd_data *data = find_and_del_fd_data_locked((int32_t)(fd & DRV_FD_MASK), &uuid, task);
965     if (data == NULL) {
966         put_drv_task_locked(task, 1);
967         tloge("task:%u has not open fd:%d, cannot close\n", pid, (int32_t)(fd & DRV_FD_MASK));
968         return -1;
969     }
970 
971     tlogd("task:%u close fd:%d\n", pid, data->drv.fd);
972 
973     close_fd_data_locked(data);
974     put_drv_task_locked(task, DRV_TASK_OPEN_REF_CNT_STEP); /* pair with alloc_drv_task ref_cnt init with 1 */
975 
976     return 0;
977 }
978 
task_dump_fd(const struct drv_task * task)979 static void task_dump_fd(const struct drv_task *task)
980 {
981     struct dlist_node *pos = NULL;
982     struct dlist_node *next = NULL;
983     struct fd_data *temp = NULL;
984 
985     dlist_for_each_safe(pos, next, &task->data_head) {
986         temp = dlist_entry(pos, struct fd_data, data_list);
987         tloge("\t fd:%d ref_cnt:%u", temp->drv.fd, temp->ref_cnt);
988     }
989 }
990 
task_dump_fd_locked(struct drv_task * task)991 static void task_dump_fd_locked(struct drv_task *task)
992 {
993     int32_t ret = drv_mutex_lock(&task->task_mtx);
994     if (ret != 0) {
995         tloge("lock task mtx failed\n");
996         return;
997     }
998 
999     task_dump_fd(task);
1000 
1001     ret = pthread_mutex_unlock(&task->task_mtx);
1002     if (ret != 0)
1003         tloge("unlock task mtx failed\n");
1004 }
1005 
driver_dump(void)1006 void driver_dump(void)
1007 {
1008     struct dlist_node *pos = NULL;
1009     struct dlist_node *next = NULL;
1010     struct drv_task *temp = NULL;
1011 
1012     tloge("***** driver dump fd begin *****\n");
1013     int32_t ret = drv_mutex_lock(&g_drv_mtx);
1014     if (ret != 0) {
1015         tloge("lock drv mtx failed\n");
1016         return;
1017     }
1018 
1019     dlist_for_each_safe(pos, next, &g_drv_node) {
1020         temp = dlist_entry(pos, struct drv_task, task_list);
1021         tloge("task_pid:%u task_count:%u ref_cnt:%u\n", temp->task_pid, temp->task_count, temp->ref_cnt);
1022         task_dump_fd_locked(temp);
1023     }
1024 
1025     ret = pthread_mutex_unlock(&g_drv_mtx);
1026     if (ret != 0)
1027         tloge("unlock drv mtx failed\n");
1028 
1029     tloge("***** driver dump fd end *****\n");
1030 }
1031 
1032 #ifdef TEE_SUPPORT_CMD_DUMP
dump_cmd_perm(void)1033 static void dump_cmd_perm(void)
1034 {
1035     tloge("====== dump cmd perm begin ======\n");
1036 
1037     uint32_t i;
1038     for (i = 0; i < g_cmd_perm.cmd_num; i++)
1039         tloge("cmd, perm [%u, 0x%llx]\n", g_cmd_perm.base_vaddr[i].cmd,
1040             (unsigned long long)g_cmd_perm.base_vaddr[i].perm);
1041 
1042     tloge("====== dump cmd perm end ======\n");
1043 }
1044 #endif
1045 
driver_register_cmd_perm(const struct tee_drv_param * params,int64_t * ret_val)1046 int32_t driver_register_cmd_perm(const struct tee_drv_param *params, int64_t *ret_val)
1047 {
1048     if (params == NULL || params->args == 0 || ret_val == NULL)
1049         return -1;
1050 
1051     uint64_t *args = (uint64_t *)(uintptr_t)params->args;
1052     uint64_t vaddr = args[DRV_REGISTER_CMD_ADDR_INDEX];
1053     uint64_t size = args[DRV_REGISTER_CMD_SIZE_INDEX];
1054     if (size >= UINT32_MAX || size == 0 || size % sizeof(struct drv_cmd_perm_info_t) != 0 || vaddr == 0) {
1055         tloge("invalid size:0x%llx or vaddr\n", size);
1056         return -1;
1057     }
1058 
1059     taskid_t drv_mgr_pid = get_drv_mgr_pid();
1060     if (taskid_to_pid(drv_mgr_pid) != (taskid_to_pid(params->caller_pid))) {
1061         tloge("caller pid:0x%x cannot register drv cmd perm\n", params->caller_pid);
1062         return -1;
1063     }
1064 
1065     if (g_cmd_perm.base_vaddr != NULL) {
1066         tloge("something wrong, cmd perm has registered\n");
1067         return -1;
1068     }
1069 
1070     void *cmd_perm = malloc(size);
1071     if (cmd_perm == NULL) {
1072         tloge("alloc for cmd perm fail\n");
1073         return -1;
1074     }
1075 
1076     if (copy_from_client(vaddr, size, (uintptr_t)cmd_perm, size) != 0) {
1077         tloge("copy cmd perm fail\n");
1078         free(cmd_perm);
1079         return -1;
1080     }
1081 
1082     g_cmd_perm.base_vaddr = cmd_perm;
1083     g_cmd_perm.cmd_num = size / sizeof(struct drv_cmd_perm_info_t);
1084 
1085 #ifdef TEE_SUPPORT_CMD_DUMP
1086     dump_cmd_perm();
1087 #endif
1088 
1089     *ret_val = 0;
1090 
1091     return 0;
1092 }
1093