• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 
13 #define _GNU_SOURCE
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <fcntl.h>
18 #include <dlfcn.h>
19 #include <sys/mman.h>
20 #include <priorities.h>
21 #include <fileio.h>
22 #include <unistd.h>
23 #include <ipclib.h>
24 #include <securec.h>
25 #include <tee_log.h>
26 #include <ta_framework.h>
27 #include <tee_task.h>
28 #include <tee_drv_internal.h>
29 #include <spawn_init.h>
30 #include <target_type.h>
31 #include <tee_drv_entry.h>
32 #include "get_spawn_env.h"
33 #include "load_init.h"
34 #include "ta_mt.h"
35 #include <ipclib_hal.h>
36 #include <mem_ops.h>
37 #include <unistd.h>
38 
39 #define RTLD_TA 0x100000
40 #define IPC_CHANNEL_NUM 2
41 
42 #ifdef __aarch64__
43 static const char *g_tarunner_path = "/tarunner.elf";
44 static const char *g_drv_so_path = "libdrv_shared.so";
45 #else
46 static const char *g_tarunner_path = "/tarunner_a32.elf";
47 static const char *g_drv_so_path = "libdrv_shared_a32.so";
48 #endif
49 
param_check(int32_t argc,const char * const * argv)50 static int32_t param_check(int32_t argc, const char * const * argv)
51 {
52     size_t length;
53 
54     if (argc < (ARGV_TERMINATE_INDEX - 1)) {
55         tloge("invalid argc %d\n", argc);
56         return -1;
57     }
58 
59     length = strnlen(argv[ARGV_TASK_NAME_INDEX], ARGV0_SIZE);
60     if (length == 0 || length >= ARGV0_SIZE) {
61         tloge("invalid service name\n");
62         return -1;
63     }
64 
65     if (strncmp(argv[ARGV_TASK_NAME_INDEX], g_tarunner_path, (strlen(g_tarunner_path) + 1)) == 0) {
66         tloge("load TA in buffer not implemented\n");
67         return -1;
68     }
69 
70     length = strnlen(argv[ARGV_TASK_PATH_INDEX], ARGV_SIZE);
71     if (length == 0 || length >= ARGV_SIZE) {
72         tloge("invalid path name\n");
73         return -1;
74     }
75 
76     return 0;
77 }
78 
79 /*
80  * they work for many TAs
81  * which helps TA to extend utilities
82  */
is_agent(const char * task_name)83 static bool is_agent(const char *task_name)
84 {
85     if (strncmp(task_name, "task_ssa", strlen("task_ssa") + 1) == 0)
86         return true;
87     return false;
88 }
89 
extend_one_more_utable(const char * task_name)90 static bool extend_one_more_utable(const char *task_name)
91 {
92     return is_agent(task_name);
93 }
94 
get_target_type_name(const struct env_param * param)95 static const char *get_target_type_name(const struct env_param *param)
96 {
97     const char *name = NULL;
98 
99     if (param->target_type == DRV_TARGET_TYPE)
100         name = "DRV";
101     else
102         name = "TA";
103 
104     return name;
105 }
106 
load_info_print(const char * task_name,const struct env_param * param)107 static void load_info_print(const char *task_name, const struct env_param *param)
108 {
109     const char *type = get_target_type_name(param);
110 
111     /* Always print, but not an error */
112 #ifdef __aarch64__
113     tlogi("Start dynlink 64bit %s %s: pid=%d\n", type, task_name, getpid());
114 #else
115     tlogi("Start dynlink %s %s: pid=%d\n", type, task_name, getpid());
116 #endif
117 }
118 
create_task_channel(const char * task_name,const struct env_param * param,cref_t * drv_channel)119 static int32_t create_task_channel(const char *task_name, const struct env_param *param, cref_t *drv_channel)
120 {
121     int32_t ret;
122     struct reg_items_st reg_items = { true, false, false };
123 
124     if (param->target_type == DRV_TARGET_TYPE) {
125         /* used for cs_server_loop */
126         ret = ipc_create_channel_native(task_name, drv_channel);
127         if (ret != 0) {
128             tloge("create drv:%s channel failed\n", task_name);
129             return -1;
130         }
131 
132         tlogd("create drv:%s channel:0x%llx\n", task_name, (unsigned long long)(*drv_channel));
133     } else {
134         /* Create 2 IPC channels */
135         ret = ipc_create_channel(task_name, IPC_CHANNEL_NUM, NULL, reg_items);
136         if (ret != 0) {
137             tloge("create multi ipc channel failed: %d\n", ret);
138             return -1;
139         }
140     }
141 
142     return 0;
143 }
144 
init(const char * task_name,const struct env_param * param,cref_t * drv_channel)145 static int32_t init(const char *task_name, const struct env_param *param, cref_t *drv_channel)
146 {
147     int32_t ret;
148 
149     load_info_print(task_name, param);
150 
151     /* modify g_debug_prefix */
152     g_debug_prefix = task_name;
153 
154     /* Extend utable for drv or agent, such as SSA */
155     if ((param->target_type == DRV_TARGET_TYPE) || extend_one_more_utable(task_name)) {
156         ret = extend_utables();
157         if (ret != 0) {
158             tloge("extend utable for \"%s\" failed: %d\n", task_name, ret);
159             return -1;
160         }
161     }
162 
163     ret = create_task_channel(task_name, param, drv_channel);
164     if (ret != 0)
165         return -1;
166 
167     ret = fileio_init();
168     if (ret != 0) {
169         tloge("file io init failed: %d\n", ret);
170         return -1;
171     }
172 
173     return 0;
174 }
175 
send_fail_msg_to_drvmgr(void)176 static void send_fail_msg_to_drvmgr(void)
177 {
178     cref_t ch = 0;
179     int32_t ret = ipc_get_ch_from_path(DRV_SPAWN_SYNC_NAME, &ch);
180     if (ret != 0) {
181         tloge("something wrong, spawn fail get drvmgr sync channel fail\n");
182         return;
183     }
184 
185     struct spawn_sync_msg msg = { 0 };
186     msg.msg_id = PROCESS_INIT_FAIL;
187 
188     ret = ipc_msg_notification(ch, &msg, sizeof(msg));
189     if (ret != 0) {
190         tloge("spawn fail notify to drvmgr fail\n");
191         return;
192     }
193 
194     if (ipc_release_from_path(DRV_SPAWN_SYNC_NAME, ch) != 0)
195         tloge("release drvmgr sync channel fail\n");
196 }
197 
send_load_fail_msg(uint32_t target_type)198 static void send_load_fail_msg(uint32_t target_type)
199 {
200     if (target_type == DRV_TARGET_TYPE) {
201         send_fail_msg_to_drvmgr();
202     } else {
203         /*
204          * TA load failed, send error to global task
205          * uwMsgHandle is 0 mean we don't need handle msg in msg function
206          * uwMsgID is 0 means we don't care about the context
207          * ucDstID is 1 means the recevier's channel ID is 1
208          */
209         if (ipc_msg_qsend(CREATE_THREAD_FAIL, GLOBAL_HANDLE, SECOND_CHANNEL) != 0)
210             tloge("failed to reply GTASK for MT ta\n");
211     }
212 }
213 
load_fail(uint32_t target_type)214 static void load_fail(uint32_t target_type)
215 {
216     clear_libtee();
217 
218     send_load_fail_msg(target_type);
219 }
220 
get_routine_info(void * handle,uint32_t size,struct ta_routine_info * routine)221 static int32_t get_routine_info(void *handle, uint32_t size, struct ta_routine_info *routine)
222 {
223     /* no need to check function entry since TA may not define it */
224     routine->info[CREATE_ENTRY_INDEX] = dlsym(handle, "TA_CreateEntryPoint");
225     routine->info[OPEN_SESSION_INDEX] = dlsym(handle, "TA_OpenSessionEntryPoint");
226     routine->info[INVOKE_COMMAND_INDEX] = dlsym(handle, "TA_InvokeCommandEntryPoint");
227     routine->info[CLOSE_SESSION_INDEX] = dlsym(handle, "TA_CloseSessionEntryPoint");
228     routine->info[DESTROY_ENTRY_INDEX] = dlsym(handle, "TA_DestroyEntryPoint");
229 
230     /* should check caller info when open session */
231     routine->addcaller_flag = true;
232 
233     if (mprotect(routine, size, PROT_READ) != 0) {
234         tloge("change routine attribute failed\n");
235         return -1;
236     }
237 
238     return 0;
239 }
240 
lib_tee_task_entry(void * handle,int32_t priority,const char * task_name,void * libtee)241 static void lib_tee_task_entry(void *handle, int32_t priority, const char *task_name, void *libtee)
242 {
243     struct ta_routine_info *routine = NULL;
244     ta_entry_type ta_entry = { 0 };
245     uint32_t size;
246 
247     ta_entry.ta_entry = dlsym(libtee, "tee_task_entry");
248     if (ta_entry.ta_entry == NULL) {
249         tloge("get task entry failed: %s\n", dlerror());
250         return;
251     }
252 
253     /* cannot be overflow */
254     size = PAGE_ALIGN_UP(sizeof(*routine));
255     /* first param set as 0 means no specific address, set fd as -1 means no specific fd */
256     routine = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
257     if (routine == MAP_FAILED) {
258         tloge("map for routine failed\n");
259         return;
260     }
261 
262     if (memset_s(routine, size, 0, size) != EOK) {
263         tloge("clear routine failed\n");
264         goto err_out;
265     }
266 
267     if (get_routine_info(handle, size, routine) != 0)
268         goto err_out;
269 
270     tee_task_entry_mt(ta_entry, priority, task_name, routine);
271 
272     /* tee_task_entry should never return */
273     tee_abort("tee task entry returns\n");
274 
275 err_out:
276     if (munmap(routine, size) != 0)
277         tloge("free routine failed\n");
278 }
279 
ta_tee_task_entry(ta_entry_type ta_entry,int32_t priority,const char * task_name)280 static void ta_tee_task_entry(ta_entry_type ta_entry, int32_t priority, const char *task_name)
281 {
282     tlogi("ta link elf_main_entry\n");
283 
284     tee_task_entry_mt(ta_entry, priority, task_name, NULL);
285 
286     /* tee_task_entry should never return */
287     tee_abort("tee task entry returns\n");
288 }
289 
load_dyn_client(char * client)290 static void load_dyn_client(char *client)
291 {
292     uint32_t size = CLIENT_NAME_SIZE * MAX_DYN_CLIENT_NUM;
293     if (strnlen(client, size - 1) != size - 1)
294         return;
295 
296     for (uint32_t i = 0; i < size; i++) {
297         if (client[i] == '#')
298             client[i] = 0;
299     }
300 
301     char per_client_name[CLIENT_NAME_SIZE + 1] = {0};
302     for (uint32_t i = 0; i < MAX_DYN_CLIENT_NUM; i++) {
303         if (memcpy_s(per_client_name, sizeof(per_client_name),
304             client + i * CLIENT_NAME_SIZE, CLIENT_NAME_SIZE) != 0)
305             continue;
306 
307         if (strlen(per_client_name) == 0)
308             continue;
309 
310         tlogi("load_dyn_client client_name:%s\n", per_client_name);
311         (void)dlopen(per_client_name, RTLD_NOW | RTLD_GLOBAL | RTLD_TA);
312         (void)memset_s(per_client_name, sizeof(per_client_name), 0, sizeof(per_client_name));
313     }
314 }
315 
tee_task_handle(const char * const * argv,const struct env_param * param,void * libtee)316 static void tee_task_handle(const char * const *argv, const struct env_param *param, void *libtee)
317 {
318     ta_entry_type ta_entry = { 0 };
319 
320     load_dyn_client((char *)argv[ARGV_CLIENT_NAME_INDEX]);
321 
322     /* Load TA in dlopen, will call init_array func */
323     void *handle = dlopen(argv[ARGV_TASK_PATH_INDEX], RTLD_NOW | RTLD_GLOBAL | RTLD_TA);
324     if (handle == NULL) {
325         tloge("dlopen %s failed: %s\n", argv[ARGV_TASK_PATH_INDEX], dlerror());
326         return;
327     }
328 
329     /* elf symbol reloc */
330     ta_entry.ta_entry_orig = dlsym(handle, "tee_task_entry");
331     /* TA has tee_task_entry */
332     if (ta_entry.ta_entry_orig != NULL)
333         ta_tee_task_entry(ta_entry, param->priority, argv[ARGV_TASK_NAME_INDEX]);
334     else
335         lib_tee_task_entry(handle, param->priority, argv[ARGV_TASK_NAME_INDEX], libtee);
336 
337     dlclose(handle);
338 }
339 
340 #define DRV_FUNC_SYMBOL_APPEND 9U /* reserved mem for "g_driver_" string */
dlsym_drv_func(void * drv_handle,const char * drv_name)341 static struct tee_driver_module *dlsym_drv_func(void *drv_handle, const char *drv_name)
342 {
343     char symbol_name[DRV_NAME_MAX_LEN + DRV_FUNC_SYMBOL_APPEND] = {0};
344     if (snprintf_s(symbol_name, sizeof(symbol_name), sizeof(symbol_name) - 1, "%s%s", "g_driver_", drv_name) <= 0) {
345         tloge("get symbol_name failed\n");
346         return NULL;
347     }
348 
349     struct tee_driver_module *drv_func = dlsym(drv_handle, symbol_name);
350     if (drv_func == NULL) {
351         tloge("cannot get drv func:%s\n", symbol_name);
352         return NULL;
353     }
354 
355     return drv_func;
356 }
357 
drv_task_handle(const char * const * argv,const struct env_param * param,void * libtee,cref_t drv_channel)358 static void drv_task_handle(const char * const * argv, const struct env_param *param, void *libtee, cref_t drv_channel)
359 {
360     void *drv_so_handle = NULL;
361     void *drv_handle = NULL;
362     void (*use_tid_flag)(void) = NULL;
363 
364     use_tid_flag = dlsym(libtee, "set_log_use_tid_flag");
365     if (use_tid_flag != NULL) {
366         use_tid_flag();
367     } else {
368         tloge("cannot set use tid log flag\n");
369         goto drv_err;
370     }
371 
372     tlogd("target_type is %u elf_path:%s task_name:%s\n", param->target_type, argv[ARGV_TASK_PATH_INDEX],
373         argv[ARGV_TASK_NAME_INDEX]);
374 
375     drv_so_handle = dlopen(g_drv_so_path, RTLD_NOW | RTLD_GLOBAL);
376     if (drv_so_handle == NULL) {
377         tloge("load %s failed %s\n", g_drv_so_path, dlerror());
378         goto drv_err;
379     }
380 
381     drv_entry_func drv_entry = dlsym(drv_so_handle, "tee_drv_entry");
382     if (drv_entry == NULL) {
383         tloge("cannot get tee drv entry\n");
384         goto drv_err;
385     }
386 
387     drv_handle = dlopen(argv[ARGV_TASK_PATH_INDEX], RTLD_NOW | RTLD_GLOBAL | RTLD_TA);
388     if (drv_handle == NULL) {
389         tloge("dlopen drv:%s failed %s\n", argv[ARGV_TASK_PATH_INDEX], dlerror());
390         goto drv_err;
391     }
392 
393     /* check in drv_entry */
394     struct tee_driver_module *drv_func = dlsym_drv_func(drv_handle, argv[ARGV_TASK_NAME_INDEX]);
395     if (drv_func == NULL)
396         goto drv_err;
397 
398     drv_entry(drv_func, argv[ARGV_TASK_NAME_INDEX], drv_channel, param);
399 
400     tee_abort("drv entry return, something wrong\n");
401 
402 drv_err:
403     if (drv_so_handle != NULL)
404         dlclose(drv_so_handle);
405 
406     if (drv_handle != NULL)
407         dlclose(drv_handle);
408 }
409 
main(int32_t argc,const char * const * argv)410 __attribute__((visibility("default"))) int32_t main(int32_t argc, const char * const * argv)
411 {
412     struct env_param param = { 0 };
413     void *libtee = NULL;
414     cref_t drv_channel = 0;
415 
416     mem_ops_init();
417 
418     if (param_check(argc, argv) != 0) {
419         tloge("param check failed\n");
420         goto err_out;
421     }
422 
423     if (get_env_param(&param) != 0)
424         goto err_out;
425 
426     /* task context initialization */
427     if (init(argv[ARGV_TASK_NAME_INDEX], &param, &drv_channel) != 0)
428         goto err_out;
429 
430     if (param.target_type == DRV_TARGET_TYPE) {
431         drv_task_handle(argv, &param, libtee, drv_channel);
432     } else {
433         /* A parameter is added for transferring the client name during dynamic service loading */
434         if (argc < ARGV_MAX - 1) {
435             tloge("invalid argc %d", argc);
436             goto err_out;
437         }
438 
439         tee_task_handle(argv, &param, libtee);
440     }
441 
442 err_out:
443     load_fail(param.target_type);
444     return -1;
445 }
446