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