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 #define _GNU_SOURCE
13 #include "drv_dispatch.h"
14 #include <stdint.h>
15 #include <inttypes.h>
16 #include <pthread.h>
17 #include <securec.h>
18 #include <ipclib.h>
19 #include <tee_log.h>
20 #include <ta_framework.h>
21 #include <drv.h>
22 #include <tee_drv_internal.h>
23 #include <tee_drv_errno.h>
24 #include <target_type.h>
25 #include <ta_lib_img_unpack.h>
26 #include "tee_driver_module.h"
27 #include "drv_thread.h"
28 #include "drv_fd_ops.h"
29 #include "drv_ipc_mgr.h"
30 #include "drv_auth.h"
31 #include "drv_dyn_conf_mgr.h"
32 #include "drvcall_dyn_conf_mgr.h"
33 #include "drv_process_mgr.h"
34 #include "task_mgr.h"
35 #include "base_drv_node.h"
36 #include <ipclib_hal.h>
37 #include <spawn_ext.h>
38 #include <unistd.h>
39
get_drv_params(struct tee_drv_param * params,const struct drv_req_msg_t * msg,const struct src_msginfo * info)40 static int32_t get_drv_params(struct tee_drv_param *params, const struct drv_req_msg_t *msg,
41 const struct src_msginfo *info)
42 {
43 spawn_uuid_t uuid;
44 int32_t ret;
45 if (msg == NULL || info == NULL) {
46 tloge("invalid parameters\n");
47 return -1;
48 }
49
50 ret = getuuid(info->src_pid, &uuid);
51 if (ret != 0) {
52 tloge("get pid:%u uuid failed\n", info->src_pid);
53 return -1;
54 }
55
56 ret = memcpy_s(&(params->uuid), sizeof(params->uuid), &uuid.uuid, sizeof(uuid.uuid));
57 if (ret != 0) {
58 tloge("copy pid:%u uuid:0x%x to params failed\n", info->src_pid, uuid.uuid.timeLow);
59 return -1;
60 }
61
62 params->args = (uintptr_t)msg->args;
63 params->data = (uintptr_t)msg->data;
64 params->caller_pid = pid_to_taskid(info->src_tid, info->src_pid);
65
66 return 0;
67 }
68
get_drv_name(const struct tee_drv_param * params,char * drv_name,uint32_t len)69 static int32_t get_drv_name(const struct tee_drv_param *params, char *drv_name, uint32_t len)
70 {
71 char *indata = (char *)(uintptr_t)params->data;
72 uint64_t *args = (uint64_t *)(uintptr_t)params->args;
73 uint64_t name_len = args[DRV_NAME_LEN_INDEX];
74 uint64_t drv_name_offset = args[DRV_NAME_INDEX];
75
76 if (indata == NULL) {
77 tloge("invalid input buffer\n");
78 return -1;
79 }
80
81 if (name_len == 0 || name_len >= len) {
82 tloge("drv name len %"PRIx64" is invalid\n", name_len);
83 return -1;
84 }
85
86 if (drv_name_offset != args[DRV_PARAM_LEN_INDEX] ||
87 (drv_name_offset > (SYSCAL_MSG_BUFFER_SIZE - sizeof(struct drv_req_msg_t))) ||
88 (drv_name_offset + name_len > (SYSCAL_MSG_BUFFER_SIZE - sizeof(struct drv_req_msg_t)))) {
89 tloge("drv name offset %"PRIx64" is invalid\n", args[DRV_NAME_INDEX]);
90 return -1;
91 }
92
93 if (memcpy_s(drv_name, len, (indata + drv_name_offset), name_len) != EOK) {
94 tloge("copy drv name failed\n");
95 return -1;
96 }
97
98 drv_name[name_len] = '\0';
99
100 return 0;
101 }
102
is_drv_call_invalid(const struct task_node * call_node,const char * drv_name,uint32_t len)103 static bool is_drv_call_invalid(const struct task_node *call_node, const char *drv_name, uint32_t len)
104 {
105 if (call_node->target_type != DRV_TARGET_TYPE)
106 return false;
107
108 if (call_node->tlv.drv_conf == NULL) {
109 tloge("something wrong, drv conf is null\n");
110 return true;
111 }
112
113 tlogd("this is drv:%s call other drv:%s\n", call_node->tlv.drv_conf->mani.service_name, drv_name);
114 if ((len == call_node->tlv.drv_conf->mani.service_name_size) &&
115 (strncmp(call_node->tlv.drv_conf->mani.service_name, drv_name, len + 1) == 0)) {
116 tloge("drv:%s call yourself not support\n", drv_name);
117 return true;
118 }
119
120 return false;
121 }
122
alloc_drvcall_node_internal_drv(const struct tee_uuid * uuid,uint32_t taskid)123 static struct task_node *alloc_drvcall_node_internal_drv(const struct tee_uuid *uuid, uint32_t taskid)
124 {
125 struct drvcall_conf_t *tlv = malloc(sizeof(struct drvcall_conf_t));
126 if (tlv == NULL) {
127 tloge("malloc tlv node failed\n");
128 return NULL;
129 }
130 (void)memset_s(tlv, sizeof(*tlv), 0, sizeof(*tlv));
131 (void)memcpy_s(&(tlv->uuid), sizeof(tlv->uuid), uuid, sizeof(*uuid));
132
133 tlv->drvcall_perm_apply.base_perm = true;
134 struct task_node *node = alloc_and_init_ta_node(tlv);
135 if (node == NULL) {
136 free(tlv);
137 tloge("create drvcall node fail\n ");
138 return NULL;
139 }
140
141 node->pid = taskid_to_pid(taskid);
142 if (receive_task_conf(node) != 0) {
143 tloge("receive task conf fail\n");
144 free(tlv);
145 free_task_node(node);
146 return NULL;
147 }
148 free(tlv);
149
150 return node;
151 }
152
get_valid_drvcall_node(const struct tee_uuid * uuid,uint32_t taskid,const char * drv_name,uint32_t len)153 static struct task_node *get_valid_drvcall_node(const struct tee_uuid *uuid,
154 uint32_t taskid, const char *drv_name, uint32_t len)
155 {
156 bool base_drv_flag = get_base_drv_flag(drv_name, len);
157
158 struct task_node *call_node = get_node_by_uuid_with_lock(uuid, taskid);
159 if (call_node == NULL) {
160 if (base_drv_flag) {
161 call_node = alloc_drvcall_node_internal_drv(uuid, taskid);
162 } else {
163 tloge("cannot get caller node:0x%x taskid is 0x%x\n", uuid->timeLow, taskid);
164 return NULL;
165 }
166 }
167
168 if (is_drv_call_invalid(call_node, drv_name, len))
169 goto put_drvcall;
170 /* first check whether caller has the right to access this drv */
171 if (!base_drv_flag) {
172 if (!caller_open_auth_check(call_node, drv_name, len)) {
173 tloge("caller:0x%x cannot access %s\n", uuid->timeLow, drv_name);
174 goto put_drvcall;
175 }
176 }
177
178 int32_t ret = get_fd_count(call_node);
179 if (ret != 0) {
180 tloge("caller:0x%x get fd count fail\n", uuid->timeLow);
181 goto put_drvcall;
182 }
183
184 return call_node;
185
186 put_drvcall:
187 put_node_with_lock(call_node, 1);
188 return NULL;
189 }
190
191 #define ELF_APPEND_LEN 4 /* ".elf" */
unlink_drv_elf(const char * drv_name)192 static void unlink_drv_elf(const char *drv_name)
193 {
194 char drv_elf[DRV_NAME_MAX_LEN + ELF_APPEND_LEN] = { 0 };
195
196 int32_t ret = snprintf_s(drv_elf, sizeof(drv_elf), (sizeof(drv_elf) - 1), "%s%s",
197 drv_name, ".elf");
198 if (ret < 0) {
199 tloge("set unlink drv:%s elf fail\n", drv_name);
200 return;
201 }
202
203 uint32_t ipc_ret = ipc_msg_snd(TEE_UNLINK_DYNAMIC_DRV, GLOBAL_HANDLE, drv_elf, sizeof(drv_elf));
204 if (ipc_ret != 0)
205 tloge("send unlink drv:%s msg fail:0x%x", drv_name, ipc_ret);
206
207 tlogd("unlink drv:%s succ\n", drv_elf);
208 }
209
get_valid_drv_node(const struct tee_uuid * caller_uuid,const char * drv_name,uint32_t len)210 static struct task_node *get_valid_drv_node(const struct tee_uuid *caller_uuid, const char *drv_name, uint32_t len)
211 {
212 struct task_node *dnode = get_drv_node_by_name_with_lock(drv_name, len);
213 if (dnode == NULL) {
214 tloge("cannot find drv:%s\n", drv_name);
215 return NULL;
216 }
217
218 if (!drv_mac_open_auth_check(dnode->tlv.drv_conf, caller_uuid)) {
219 tloge("drv:%s mac check fail 0x%x", drv_name, caller_uuid->timeLow);
220 goto put_drv;
221 }
222
223 int32_t ret = check_drv_node_state(dnode);
224 if (ret == DRV_NEED_SPAWN) {
225 /* spawn process */
226 tlogd("SPAWN drv:%s begin\n", drv_name);
227 ret = spawn_driver_handle(dnode);
228 if (ret != 0) {
229 tloge("spawn drv:%s fail\n", drv_name);
230 broadcast_drv_state(dnode, false);
231 } else {
232 tlogd("spawn drv:%s succ and broadcast\n", drv_name);
233 broadcast_drv_state(dnode, true);
234 unlink_drv_elf(drv_name);
235 return dnode;
236 }
237 } else if (ret == DRV_SUCC) {
238 tlogd("drv:%s has spawn succ\n", drv_name);
239 return dnode;
240 }
241
242 tloge("cannot find drv:%s spawn node\n", drv_name);
243
244 put_drv:
245 put_node_with_lock(dnode, 1);
246 return NULL;
247 }
248
driver_open_func(const struct tee_drv_param * params)249 static int64_t driver_open_func(const struct tee_drv_param *params)
250 {
251 char drv_name[DRV_NAME_MAX_LEN] = { 0 };
252 if (get_drv_name(params, drv_name, sizeof(drv_name)) != 0)
253 return -1;
254
255 struct task_node *call_node = get_valid_drvcall_node(¶ms->uuid, params->caller_pid, drv_name, strlen(drv_name));
256 if (call_node == NULL)
257 return -1;
258
259 struct fd_node *data = alloc_and_init_fd_node();
260 if (data == NULL)
261 goto put_drvcall;
262
263 struct task_node *dnode = get_valid_drv_node(¶ms->uuid, drv_name, strlen(drv_name));
264 if (dnode == NULL)
265 goto free_fd;
266
267 /*
268 * get drvcall cmd permission, and send to driver process
269 * it will be used in ioctl function to check whether drvcaller has special cmd permission
270 */
271 uint64_t caller_perm;
272 bool base_drv_flag = get_base_drv_flag(drv_name, strlen(drv_name));
273 if (base_drv_flag) {
274 caller_perm = 0;
275 } else {
276 int32_t ret = get_drvcaller_cmd_perm(call_node, dnode, &caller_perm);
277 if (ret != 0) {
278 tloge("get caller:0x%x drv:%s cmd perm fail\n", params->uuid.timeLow, drv_name);
279 goto put_drv;
280 }
281 }
282 int64_t fd = drv_open_handle(params, dnode, caller_perm);
283 if (fd <= 0) {
284 tloge("drv:%s open fd fail:0x%llx\n", drv_name, fd);
285 goto put_drv;
286 }
287
288 data->fd = fd;
289 data->drv = dnode;
290
291 if (add_fd_to_drvcall_node(data, call_node) != 0) {
292 tloge("add fd fail\n");
293 goto close_fd;
294 }
295
296 tlogd("caller:0x%x open drv:%s fd:0x%llx end\n", params->uuid.timeLow, drv_name, fd);
297
298 return fd;
299
300 close_fd:
301 if (call_drv_close(call_node->pid, ¶ms->uuid, fd, dnode->drv_task.channel) != 0)
302 tloge("call drv:%s close fd:0x%llx fail\n", drv_name, fd);
303
304 put_drv:
305 put_node_with_lock(dnode, 1);
306
307 free_fd:
308 free(data);
309
310 put_drvcall:
311 put_fd_count(call_node);
312 put_node_with_lock(call_node, 1);
313 return -1;
314 }
315
driver_close_func_ops(struct task_node * call_node,int64_t fd,struct fd_node ** data)316 static int64_t driver_close_func_ops(struct task_node *call_node, int64_t fd, struct fd_node **data)
317 {
318 struct task_node *dnode = (*data)->drv;
319 if (dnode == NULL) {
320 tloge("something wrong, task:0x%x uuid:0x%x fd:0x%llx data has no drv\n",
321 call_node->pid, call_node->tlv.uuid.timeLow, fd);
322 del_fd_to_drvcall_node(data, call_node);
323 return -1;
324 }
325
326 /*
327 * must del fd in drvcall node before call drv_close
328 * otherwise will cause fd data cannot close in this case:
329 * two session of the same TA call the same drv,
330 * session 0 in cpux close the fd1 and session 1 in cpuy open new fd
331 * when drv free fd1 first, it may alloc fd1 to session 1 (session 0 close fd1, and session 1 open fd1 again)
332 * if not del fd data of this task in drvmgr, it may cannot find valid fd1 (close_flag = false)
333 * when session 1 close fd1 opened before since this task in drvmgr has two fd1,
334 * one opened by session 0 has set close_flag, another opened by session 1 has not set close_flag,
335 * session 1 close fd1 may find the session 0 opened since it just compare the fd1 value
336 */
337 del_fd_to_drvcall_node(data, call_node);
338
339 int64_t ret = call_drv_close(call_node->pid, &call_node->tlv.uuid, fd, dnode->drv_task.channel);
340 if (ret != 0)
341 tloge("call drv close fd:0x%llx for task:0x%x fail ret:0x%x\n", fd, call_node->pid, ret);
342
343 /* pair with dnode ref_cnt add one in open */
344 put_node_with_lock(dnode, 1);
345
346 return ret;
347 }
348
driver_close_func(int64_t fd,const struct tee_drv_param * params)349 static int64_t driver_close_func(int64_t fd, const struct tee_drv_param *params)
350 {
351 int64_t ret = DRV_GENERAL_ERR;
352
353 tlogd("call drv fd:0x%llx close begin\n", fd);
354
355 struct task_node *call_node = get_node_by_uuid_with_lock(¶ms->uuid, params->caller_pid);
356 if (call_node == NULL) {
357 tloge("cannot get call node pid:0x%x uuid:0x%x for fd:0x%llx\n",
358 params->caller_pid, params->uuid.timeLow, fd);
359 return ret;
360 }
361
362 struct fd_node *data = close_get_fd_node_with_lock(call_node, fd);
363 if (data == NULL) {
364 /*
365 * two case:
366 * 1. the caller has not open this fd
367 * 2. this fd has been closed in exception handle
368 */
369 tloge("task:0x%x uuid:0x%x cannot find fd:0x%llx\n",
370 params->caller_pid, params->uuid.timeLow, fd);
371 put_node_with_lock(call_node, 1);
372 return DRV_GENERAL_ERR;
373 }
374
375 ret = driver_close_func_ops(call_node, fd, &data);
376
377 /*
378 * one for get_drvcall_by_uuid_with_lock
379 * one for pair with open
380 */
381 put_node_with_lock(call_node, DRVCALL_DEC_CNT_INCLUDE_REGISTER_ONE);
382
383 tlogd("drv fd:0x%llx close ret:0x%llx\n", fd, ret);
384
385 /*
386 * In this case must dec channel ref_cnt in lib
387 * because this fd can be find in drvmgr
388 */
389 if (ret != DRV_SUCCESS) {
390 tloge("find fd:0x%llx but close fail\n", fd);
391 return DRV_CLOSE_FD_FAIL;
392 }
393
394 return ret;
395 }
396
driver_general_handle(const struct tee_drv_param * params,int64_t * ret_val)397 static int32_t driver_general_handle(const struct tee_drv_param *params, int64_t *ret_val)
398 {
399 uint64_t *args = (uint64_t *)(uintptr_t)params->args;
400 if (args == NULL) {
401 tloge("args is invalid\n");
402 return -1;
403 }
404
405 uint64_t drv_cmd = args[DRV_FRAM_CMD_INDEX];
406 int64_t ret;
407
408 if (drv_cmd == CALL_DRV_OPEN) {
409 ret = driver_open_func(params);
410 } else if (drv_cmd == CALL_DRV_CLOSE) {
411 ret = driver_close_func(args[DRV_CLOSE_FD_INDEX], params);
412 } else {
413 tloge("drv cmd:%" PRIx64 " not support\n", drv_cmd);
414 return -1;
415 }
416
417 *ret_val = ret;
418
419 return 0;
420 }
421
422 #define EXIT_PID_INDEX 0
driver_exception_handle(const struct tee_drv_param * params,int64_t * ret_val)423 static int32_t driver_exception_handle(const struct tee_drv_param *params, int64_t *ret_val)
424 {
425 uint32_t pid = taskid_to_pid(params->caller_pid);
426 if (pid != GLOBAL_HANDLE) {
427 tloge("task:0x%x not gtask, cannot call exception handle\n", pid);
428 return -1;
429 }
430
431 uint64_t *args = (uint64_t *)(uintptr_t)params->args;
432 if (args == NULL) {
433 tloge("args is invalid\n");
434 return -1;
435 }
436
437 uint64_t exit_pid = args[EXIT_PID_INDEX];
438 if (exit_pid > UINT32_MAX) {
439 tloge("invalid exit_pid\n");
440 return -1;
441 }
442
443 tloge("receive drv crash taskid:0x%x\n", (uint32_t)exit_pid);
444 if (find_drv_node_by_taskid(exit_pid) != NULL)
445 tee_abort("drv taskid:0x%x abort\n", (uint32_t)exit_pid);
446
447 *ret_val = 0;
448 return 0;
449 }
450
451 /*
452 * register or unregister maybe called by permission service
453 * if the permission service is supported
454 */
check_caller_from_legal_service(const struct tee_drv_param * params)455 static bool check_caller_from_legal_service(const struct tee_drv_param *params)
456 {
457 uint32_t pid = taskid_to_pid(params->caller_pid);
458 if (pid == GLOBAL_HANDLE)
459 return true;
460
461 #if defined(TEE_SUPPORT_PERM_64BIT) || defined(TEE_SUPPORT_PERM_32BIT)
462 struct tee_uuid perm_srv = TEE_SERVICE_PERM;
463 if (memcmp(¶ms->uuid, &perm_srv, sizeof(perm_srv)) == 0)
464 return true;
465 #endif
466
467 return false;
468 }
469
470 #define DRV_CONF_LEN_INDEX 1
471 #define DRV_CONF_OFF_INDEX 0
472
drv_conf_register_handle(const struct tee_drv_param * params,int64_t * ret_val)473 static int32_t drv_conf_register_handle(const struct tee_drv_param *params, int64_t *ret_val)
474 {
475 uint64_t *args = (uint64_t *)(uintptr_t)(params->args);
476 char *indata = (char *)(uintptr_t)params->data;
477 if (args == NULL || indata == NULL) {
478 tloge("drv conf register handle invalied args and indata params\n");
479 return -1;
480 }
481
482 uint64_t len = args[DRV_CONF_LEN_INDEX];
483
484 if (len != sizeof(struct drv_tlv) || args[DRV_CONF_OFF_INDEX] != 0) {
485 tloge("invalied params\n");
486 return -1;
487 }
488
489 if (!check_caller_from_legal_service(params)) {
490 tloge("drv conf can only register from legal service\n");
491 return -1;
492 }
493
494 struct drv_tlv tlv;
495 if (memcpy_s(&tlv, sizeof(tlv), indata, len) != 0) {
496 tloge("memcpy for tlv failed\n");
497 return -1;
498 }
499
500 struct task_node *node = alloc_and_init_drv_node(&tlv);
501 if (node == NULL) {
502 tloge("alloc drv node fail\n");
503 return -1;
504 }
505
506 if (receive_task_conf(node) != 0) {
507 tloge("receive drv task fail\n");
508 free_task_node(node);
509 return -1;
510 }
511
512 if (check_hardware_type(node, HARDWARE_ENGINE_CRYPTO))
513 free_task_node(node);
514
515 *ret_val = 0;
516 return 0;
517 }
518
drv_conf_unregister_handle(const struct tee_drv_param * params,int64_t * ret_val)519 static int32_t drv_conf_unregister_handle(const struct tee_drv_param *params, int64_t *ret_val)
520 {
521 uint64_t *args = (uint64_t *)(uintptr_t)(params->args);
522 char *indata = (char *)(uintptr_t)params->data;
523 if (args == NULL || indata == NULL) {
524 tloge("drv conf unregister handle invalied args and indata params\n");
525 return -1;
526 }
527
528 uint64_t len = args[DRV_CONF_LEN_INDEX];
529 char service_name[DRV_NAME_MAX_LEN + 1] = { 0 };
530
531 if (len == 0 || len >= DRV_NAME_MAX_LEN || args[DRV_CONF_OFF_INDEX] != 0) {
532 tloge("invalied params\n");
533 return -1;
534 }
535
536 if (!check_caller_from_legal_service(params)) {
537 tloge("drv conf can only unregist from legal service\n");
538 return -1;
539 }
540
541 if (memcpy_s(service_name, DRV_NAME_MAX_LEN, indata, (size_t)len) != 0) {
542 tloge("memcpy service_name failed\n");
543 return -1;
544 }
545
546 if (free_drv_conf_by_service_name(service_name, len) != 0) {
547 tloge("free drv conf failed\n");
548 return -1;
549 }
550
551 *ret_val = 0;
552 return 0;
553 }
554
555 #define DRVCALL_CONF_LEN_INDEX 1
556 #define DRVCALL_CONF_OFF_INDEX 0
557 #define DRVCALL_TASKID_INDEX 2
558
drvcall_conf_register_handle(const struct tee_drv_param * params,int64_t * ret_val)559 static int32_t drvcall_conf_register_handle(const struct tee_drv_param *params, int64_t *ret_val)
560 {
561 uint64_t *args = (uint64_t *)(uintptr_t)(params->args);
562 char *indata = (char *)(uintptr_t)params->data;
563 if (args == NULL || indata == NULL) {
564 tloge("drvcall conf register handle invalied args and indata params\n");
565 return -1;
566 }
567
568 uint64_t len = args[DRVCALL_CONF_LEN_INDEX];
569 if (len != sizeof(struct drvcall_conf_t) || args[DRVCALL_CONF_OFF_INDEX] != 0) {
570 tloge("drvcall conf register handle invalied params\n");
571 return -1;
572 }
573
574 if (!check_caller_from_legal_service(params)) {
575 tloge("drvcall conf can only register from legal service\n");
576 return -1;
577 }
578
579 struct drvcall_conf_t drvcall;
580 if (memcpy_s(&drvcall, sizeof(drvcall), indata, len) != 0) {
581 tloge("memcpy for drvcall failed\n");
582 return -1;
583 }
584
585 drvcall.drvcall_perm_apply.base_perm = false;
586
587 struct task_node *node = alloc_and_init_ta_node(&drvcall);
588 if (node == NULL) {
589 tloge("create drvcall node fail\n ");
590 return -1;
591 }
592
593 if (receive_task_conf(node) != 0) {
594 tloge("receive task conf fail\n");
595 free_task_node(node);
596 return -1;
597 }
598
599 *ret_val = 0;
600 return 0;
601 }
602
drvcall_conf_unregister_handle(const struct tee_drv_param * params,cref_t reply_hdl,struct drv_reply_msg_t * reply,int64_t * ret_val)603 static int32_t drvcall_conf_unregister_handle(const struct tee_drv_param *params,
604 cref_t reply_hdl, struct drv_reply_msg_t *reply, int64_t *ret_val)
605 {
606 uint64_t *args = (uint64_t *)(uintptr_t)(params->args);
607 char *indata = (char *)(uintptr_t)params->data;
608 if (args == NULL || indata == NULL) {
609 tloge("drvcall conf unregister handle invalied args and indata params\n");
610 return -1;
611 }
612
613 uint64_t len = args[DRVCALL_CONF_LEN_INDEX];
614 struct tee_uuid uuid;
615
616 if (len != sizeof(uuid) || args[DRVCALL_CONF_OFF_INDEX] != 0) {
617 tloge("invalied params\n");
618 return -1;
619 }
620
621 if (!check_caller_from_legal_service(params)) {
622 tloge("drvcall conf can only unregist from legal service\n");
623 return -1;
624 }
625
626 if (memcpy_s(&uuid, sizeof(uuid), indata, (size_t)len) != 0) {
627 tloge("memcpy uuid failed\n");
628 return -1;
629 }
630
631 struct task_node *node = get_ta_node_and_set_exit(&uuid);
632
633 reply->header.reply.ret_val = 0;
634 int32_t ret = ipc_msg_reply(reply_hdl, reply, sizeof(*reply));
635 if (ret != 0)
636 tloge("exception reply fail:0x%x\n", ret);
637
638 if (node != NULL) {
639 uint32_t close_fd = exception_close_handle(node);
640
641 /*
642 * close_fd for those fd that not close normally
643 * 2: one for get_drvcall_and_set_exit, another one for register drvcall
644 */
645 put_node_with_lock(node, (close_fd + DRVCALL_DEC_CNT_INCLUDE_REGISTER_ONE));
646 } else {
647 /* maybe the exit process has not register */
648 tlogd("cannot find taskid:0x%x drvcall\n", taskid);
649 }
650
651 *ret_val = 0;
652 return 0;
653 }
654
655 #ifdef TEE_SUPPORT_DYN_CONF_DEBUG
drvcall_conf_dump_handle(const struct tee_drv_param * params,int64_t * ret_val)656 static int32_t drvcall_conf_dump_handle(const struct tee_drv_param *params, int64_t *ret_val)
657 {
658 (void)params;
659 *ret_val = 0;
660
661 dump_task_node();
662
663 return 0;
664 }
665 #endif
666
driver_syscall_dispatch(int32_t swi_id,const struct tee_drv_param * params,cref_t reply_hdl,struct drv_reply_msg_t * reply,int64_t * ret_val)667 static int32_t driver_syscall_dispatch(int32_t swi_id, const struct tee_drv_param *params,
668 cref_t reply_hdl, struct drv_reply_msg_t *reply, int64_t *ret_val)
669 {
670 int32_t ret = -1;
671
672 switch (swi_id) {
673 case DRV_GENERAL_CMD_ID:
674 ret = driver_general_handle(params, ret_val);
675 break;
676 case DRV_EXCEPTION_CMD_ID:
677 ret = driver_exception_handle(params, ret_val);
678 break;
679 case REGISTER_DRV_CONF:
680 ret = drv_conf_register_handle(params, ret_val);
681 break;
682 case UNREGISTER_DRV_CONF:
683 ret = drv_conf_unregister_handle(params, ret_val);
684 break;
685 case REGISTER_DRVCALL_CONF:
686 ret = drvcall_conf_register_handle(params, ret_val);
687 break;
688 case UNREGISTER_DRVCALL_CONF:
689 ret = drvcall_conf_unregister_handle(params, reply_hdl, reply, ret_val);
690 break;
691 #ifdef TEE_SUPPORT_DYN_CONF_DEBUG
692 case DUMP_DRVCALL_CONF:
693 ret = drvcall_conf_dump_handle(params, ret_val);
694 break;
695 #endif
696 default:
697 tloge("swi_id:0x%x cannot handle\n", swi_id);
698 }
699
700 return ret;
701 }
702
driver_open_reply_error_callback(int64_t fd,const struct tee_drv_param * params)703 static void driver_open_reply_error_callback(int64_t fd, const struct tee_drv_param *params)
704 {
705 struct task_node *call_node = NULL;
706 struct fd_node *data = NULL;
707
708 int32_t ret = get_drvcall_and_fd_node(fd, params, &call_node, &data);
709 if (ret != 0)
710 return;
711
712 tloge("open callback find fd:0x%llx for taskid:0x%x uuid:0x%x\n",
713 fd, params->caller_pid, params->uuid.timeLow);
714
715 /* no care whether succ or fail */
716 (void)driver_close_func_ops(call_node, fd, &data);
717
718 /*
719 * one for get_drvcall_and_fd_node
720 * one pair with register drvcall
721 */
722 put_node_with_lock(call_node, DRVCALL_DEC_CNT_INCLUDE_REGISTER_ONE);
723 }
724
driver_reply_error_handle(int32_t swi_id,const struct tee_drv_param * params,int64_t ret_val)725 static void driver_reply_error_handle(int32_t swi_id, const struct tee_drv_param *params, int64_t ret_val)
726 {
727 uint64_t *args = (uint64_t *)(uintptr_t)params->args;
728 if (args == NULL) {
729 tloge("args is invalid\n");
730 return;
731 }
732
733 if (!((swi_id == DRV_GENERAL_CMD_ID) && (args[DRV_FRAM_CMD_INDEX] == CALL_DRV_OPEN)))
734 return;
735
736 if (ret_val <= 0)
737 return;
738
739 tloge("drv open reply failed, call drv close fd:%"PRIx64"\n", ret_val);
740 driver_open_reply_error_callback(ret_val, params);
741 }
742
driver_handle_message(const struct drv_req_msg_t * msg,const struct src_msginfo * info,struct drv_reply_msg_t * rmsg,const cref_t * msg_hdl)743 static int32_t driver_handle_message(const struct drv_req_msg_t *msg, const struct src_msginfo *info,
744 struct drv_reply_msg_t *rmsg, const cref_t *msg_hdl)
745 {
746 int64_t ret_val = -1;
747 int32_t ret;
748 struct tee_drv_param params = { 0 };
749 int32_t swi_id = msg->header.send.msg_id;
750
751 ret = get_drv_params(¶ms, msg, info);
752 if (ret != 0) {
753 tloge("get driver parameters failed\n");
754 return -1;
755 }
756
757 tid_t tid = gettid();
758 if (tid < 0) {
759 tloge("failed to get tid\n");
760 return -1;
761 }
762
763 update_callerpid_by_tid(tid, params.caller_pid);
764 ret = driver_syscall_dispatch(swi_id, ¶ms, *msg_hdl, rmsg, &ret_val);
765 update_callerpid_by_tid(tid, INVALID_CALLER_PID);
766 if (ret != 0)
767 tloge("handle swi 0x%x failed\n", swi_id);
768
769 /*
770 * in exception_close_handle, will send reply msg when handle succ,
771 * but not send reply msg when handle fail
772 */
773 if ((swi_id != UNREGISTER_DRVCALL_CONF) || (swi_id == UNREGISTER_DRVCALL_CONF && ret != 0)) {
774 rmsg->header.reply.ret_val = (ret == 0) ? ret_val : (int64_t)ret;
775 ret = ipc_msg_reply(*msg_hdl, rmsg, sizeof(struct drv_reply_msg_t));
776 if (ret != 0) {
777 tloge("msg reply for 0x%x failed\n", swi_id);
778 /*
779 * should clear system resource information alloced by this cmd when reply failed,
780 * otherwise it will cause memory leak
781 */
782 driver_reply_error_handle(swi_id, ¶ms, ret_val);
783 }
784 }
785
786 return ret;
787 }
788
driver_dispatch(void * msg,cref_t * p_msg_hdl,struct src_msginfo * info)789 intptr_t driver_dispatch(void *msg, cref_t *p_msg_hdl, struct src_msginfo *info)
790 {
791 int32_t ret;
792 struct drv_reply_msg_t reply_raw_buf;
793
794 if ((p_msg_hdl == NULL) || (info == NULL) || (msg == NULL)) {
795 tloge("invalid dispatch param\n");
796 return -1;
797 }
798
799 (void)memset_s(&reply_raw_buf, sizeof(reply_raw_buf), 0, sizeof(reply_raw_buf));
800
801 ret = driver_handle_message((struct drv_req_msg_t *)msg, info,
802 &reply_raw_buf, p_msg_hdl);
803 if (ret != 0)
804 tloge("driver handle message failed\n");
805
806 return ret;
807 }
808