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 "dynload.h"
13 #include <inttypes.h>
14 #include <string.h>
15 #include <securec.h>
16 #include <fileio.h>
17 #include <ta_framework.h>
18 #include <tee_common.h>
19 #include <tee_log.h>
20 #include <tee_config.h>
21 #include <tee_config.h>
22 #include "uuid2path.h"
23 #include "tee_load_lib.h"
24 #include "gtask_core.h" /* for find_service */
25 #include "gtask_inner.h"
26 #include "service_manager.h"
27 #include "session_manager.h"
28 #include "tee_app_load_srv.h"
29 #include "spawn_init.h"
30 #include <spawn_ext.h>
31
32 #define ELFCLASS32 1
33 #define ELFCLASS64 2
34 #define NAME_LEN 64
35 #define RWRIGHT 0600
36 #define MAX_DRV_LIB_SIZE 0x80000 /* 512K */
37
sre_dynamic_load_elf(const TEE_UUID * uuid)38 static uint32_t sre_dynamic_load_elf(const TEE_UUID *uuid)
39 {
40 int ret;
41 char name[MAX_TAFS_NAME_LEN] = { 0 };
42
43 ret = uuid_to_fname(uuid, name, sizeof(name));
44 if (ret < 0) {
45 tloge("from uuid to fname error!\n");
46 return 1;
47 }
48
49 if (rename_tmp_file(name, sizeof(name)) != TEE_SUCCESS)
50 return 1;
51
52 return 0;
53 }
54
sre_dynamic_del_elf(const TEE_UUID * uuid)55 static uint32_t sre_dynamic_del_elf(const TEE_UUID *uuid)
56 {
57 int ret;
58 char name[NAME_LEN] = { 0 };
59
60 ret = uuid_to_fname(uuid, name, NAME_LEN);
61 if (ret < 0) {
62 tloge("uuid_to_fname error!\n");
63 return TEE_ERROR_GENERIC;
64 }
65
66 if (unlink(name) == -1) {
67 tloge("unlink fail!!!\n");
68 return TEE_ERROR_GENERIC;
69 }
70 return TEE_SUCCESS;
71 }
72
sre_release_dynamic_region(const TEE_UUID * uuid,uint32_t release)73 uint32_t sre_release_dynamic_region(const TEE_UUID *uuid, uint32_t release)
74 {
75 if (release == TA_REGION_FOR_REUSE)
76 return TEE_SUCCESS;
77
78 struct service_struct *service = NULL;
79
80 if (find_service(uuid, 0, &service) == -1) {
81 tloge("release dynamic: can't find service!!!\n");
82 return TEE_ERROR_GENERIC;
83 }
84 service->elf_state = ELF_NOT_EXIST;
85 return sre_dynamic_del_elf(uuid);
86 }
87
88 #define ELF_TYPE_OFFSET 4
varify_elf_arch(const char * elf,int file_size,bool * ta_64bit)89 TEE_Result varify_elf_arch(const char *elf, int file_size, bool *ta_64bit)
90 {
91 if (elf == NULL || ta_64bit == NULL) {
92 tloge("Parameters is null\n");
93 return TEE_ERROR_GENERIC;
94 }
95 if (file_size < (int)(ELF_TYPE_OFFSET * sizeof(uint8_t) + sizeof(uint8_t))) {
96 tloge("file size is invalid\n");
97 return TEE_ERROR_GENERIC;
98 }
99
100 uint8_t *elf_type = (uint8_t *)elf + ELF_TYPE_OFFSET;
101
102 if (*elf_type == ELFCLASS32) {
103 *ta_64bit = false;
104 } else if (*elf_type == ELFCLASS64) {
105 *ta_64bit = true;
106 } else {
107 tloge("Unknown elf architecture %d\n", (int)(*elf_type));
108 return TEE_ERROR_GENERIC;
109 }
110
111 return TEE_SUCCESS;
112 }
113
elf_param_check(uint32_t stack_size,uint32_t heap_size,uint32_t mani_ext_size)114 int elf_param_check(uint32_t stack_size, uint32_t heap_size, uint32_t mani_ext_size)
115 {
116 stack_size = PAGE_ALIGN_UP(stack_size);
117 if ((stack_size == 0) || (stack_size > MAX_STACK_SIZE) || (heap_size == 0) || mani_ext_size > NOTIFY_MAX_LEN) {
118 tloge("Parameters check failed. stack size = %u, heap size = %u, manifest extend size = %u\n",
119 stack_size, heap_size, mani_ext_size);
120 return -1;
121 }
122 return 0;
123 }
124
load_elf_to_tee(const TEE_UUID * uuid,const char * task_name,bool buildin,bool dyn_conf_registed,struct service_attr * service_attr)125 TEE_Result load_elf_to_tee(const TEE_UUID *uuid, const char *task_name, bool buildin,
126 bool dyn_conf_registed, struct service_attr *service_attr)
127 {
128 TEE_Result ret;
129 uint32_t uw_ret;
130 if (uuid == NULL || task_name == NULL || service_attr == NULL) {
131 tloge("check Parameters failed\n");
132 /* cmd no need to check. */
133 return TEE_ERROR_GENERIC;
134 }
135
136 /* check if dynamic service already exist */
137 if (dynamic_service_exist(uuid, buildin))
138 return TEE_ERROR_GENERIC;
139
140 tlogd("task name is %s, ta_64bit:%d\n", task_name, ta_64bit);
141
142 uw_ret = sre_dynamic_load_elf(uuid);
143 if (uw_ret != 0)
144 return TEE_ERROR_GENERIC;
145
146 ret = register_service(task_name, uuid, dyn_conf_registed, service_attr);
147 if (ret != 0)
148 tloge("register service \"%s\" fail: 0x%x\n", task_name, ret);
149
150 return ret;
151 }
152
is_param_valid(const load_elf_func_params * param,bool is_talib,tee_img_type_t type)153 static int is_param_valid(const load_elf_func_params *param, bool is_talib, tee_img_type_t type)
154 {
155 bool check_value = (param->fname == NULL || param->lib_name == NULL || param->fname_size > LIB_NAME_MAX ||
156 strlen(param->lib_name) > MAX_NAME_LEN || param->file_buffer == NULL);
157 if (check_value == true)
158 return false;
159 if (strchr(param->lib_name, '/') != NULL) // in case of redirect
160 return false;
161
162 if ((type != IMG_TYPE_DYNAMIC_DRV) && (!is_talib) && (param->file_size > MAX_DRV_LIB_SIZE) &&
163 (type != IMG_TYPE_CRYPTO_DRV)) {
164 tloge("drv-lib %s size is too big: %d\n", param->lib_name, param->file_size);
165 return false;
166 }
167
168 return true;
169 }
170
do_err_work(int fp,const char * name)171 static void do_err_work(int fp, const char *name)
172 {
173 if (close(fp) != 0)
174 tloge("fclose failed\n");
175
176 if (unlink(name) != 0)
177 tloge("unlink %s failed\n", name);
178
179 return;
180 }
181
proc_load_lib_elf(const char * file_buffer,int file_size,uint64_t memid,const char * name)182 static int proc_load_lib_elf(const char *file_buffer, int file_size, uint64_t memid, const char *name)
183 {
184 int ret;
185
186 int fp = open(name, O_CREAT | O_RDWR, RWRIGHT, memid);
187 if (fp < 0) {
188 tloge("fopen failed: %d\n", fp);
189 return 1;
190 }
191
192 ret = ftruncate(fp, file_size);
193 if (ret < 0) {
194 tloge("ftruncate failed\n");
195 do_err_work(fp, name);
196 return 1;
197 }
198
199 if (write(fp, file_buffer, (size_t)file_size) != file_size) {
200 tloge("fwrite failed\n");
201 do_err_work(fp, name);
202 return 1;
203 }
204
205 if (close(fp) != 0) {
206 tloge("fclose failed\n");
207 if (unlink(name) != 0)
208 tloge("unlink %s failed\n", name);
209 return 1;
210 }
211
212 return 0;
213 }
214
is_ta_lib(const TEE_UUID * uuid)215 static bool is_ta_lib(const TEE_UUID *uuid)
216 {
217 TEE_UUID global_uuid = TEE_SERVICE_GLOBAL;
218
219 if (!TEE_MemCompare(&global_uuid, uuid, sizeof(*uuid)))
220 return false;
221
222 return true;
223 }
224
225 #define MAX_RECORD_LIST_NUM 10
226 static struct dlist_node g_client_list;
227 static uint32_t g_client_num = 0;
228 static bool g_init = false;
229 static pthread_mutex_t g_client_list_mutex = PTHREAD_MUTEX_INITIALIZER;
230 struct dyn_client_t {
231 struct dlist_node list_head;
232 bool is_64bit;
233 char client_name[CLIENT_NAME_SIZE];
234 };
235
find_record(const char * client_name,uint16_t name_size,bool is_64bit)236 static bool find_record(const char *client_name, uint16_t name_size, bool is_64bit)
237 {
238 struct dyn_client_t *node = NULL;
239 struct dyn_client_t *temp = NULL;
240 dlist_for_each_entry_safe(node, temp, &g_client_list, struct dyn_client_t, list_head) {
241 if (strnlen(node->client_name, CLIENT_NAME_SIZE) != name_size)
242 continue;
243
244 if (TEE_MemCompare(node->client_name, client_name, strnlen(client_name, name_size) == 0) &&
245 node->is_64bit == is_64bit)
246 return true;
247 }
248
249 return false;
250 }
251
add_dyn_client_to_list(const char * client_name,uint16_t name_size,bool ta_64bit)252 static bool add_dyn_client_to_list(const char *client_name, uint16_t name_size, bool ta_64bit)
253 {
254 tlogi("add_dyn_client_to_list, client_name:%s name_size:%d ta_64bit:%u\n",
255 client_name, name_size, ta_64bit);
256
257 if (pthread_mutex_lock(&g_client_list_mutex) != 0) {
258 tloge("pthread lock failed\n");
259 return false;
260 }
261
262 if (!g_init) {
263 dlist_init(&g_client_list);
264 g_init = true;
265 }
266
267 if (find_record(client_name, name_size, ta_64bit)) {
268 tlogi("record already exist\n");
269 (void)pthread_mutex_unlock(&g_client_list_mutex);
270 return true;
271 }
272
273 if (g_client_num >= MAX_RECORD_LIST_NUM) {
274 tloge("the number of list node is overstepped\n");
275 (void)pthread_mutex_unlock(&g_client_list_mutex);
276 return false;
277 }
278
279 struct dyn_client_t *node = NULL;
280 node = TEE_Malloc(sizeof(struct dyn_client_t), 0);
281 if (node == NULL) {
282 tloge("malloc failed\n");
283 (void)pthread_mutex_unlock(&g_client_list_mutex);
284 return false;
285 }
286
287 node->is_64bit = ta_64bit;
288 errno_t rc = memcpy_s(&(node->client_name), sizeof(node->client_name),
289 client_name, name_size);
290 if (rc != EOK) {
291 tlogw("mem copy fail!");
292 TEE_Free(node);
293 (void)pthread_mutex_unlock(&g_client_list_mutex);
294 return false;
295 }
296
297 dlist_insert_tail(&node->list_head, &g_client_list);
298 g_client_num++;
299 (void)pthread_mutex_unlock(&g_client_list_mutex);
300 return true;
301 }
302
get_dyn_client_name(bool is_64bit,char * client,uint32_t size)303 bool get_dyn_client_name(bool is_64bit, char *client, uint32_t size)
304 {
305 if (client == NULL)
306 return false;
307
308 if (pthread_mutex_lock(&g_client_list_mutex) != 0) {
309 tloge("pthread lock failed\n");
310 return false;
311 }
312
313 if (!g_init) {
314 dlist_init(&g_client_list);
315 g_init = true;
316 }
317
318 struct dyn_client_t *node = NULL;
319 struct dyn_client_t *temp = NULL;
320 uint32_t count = 0;
321
322 dlist_for_each_entry_safe(node, temp, &g_client_list, struct dyn_client_t, list_head) {
323 if (node->is_64bit == is_64bit) {
324 if (count * CLIENT_NAME_SIZE >= size)
325 break;
326
327 if (memcpy_s(client + count * CLIENT_NAME_SIZE, size - count * CLIENT_NAME_SIZE,
328 node->client_name, strlen(node->client_name)) != 0) {
329 tloge("copy client fail!");
330 continue;
331 }
332 count++;
333 }
334 }
335
336 (void)pthread_mutex_unlock(&g_client_list_mutex);
337 return true;
338 }
339
record_client_name(const char * file_buffer,uint32_t file_size,const char * fname,uint32_t fname_size)340 static int record_client_name(const char *file_buffer, uint32_t file_size,
341 const char *fname, uint32_t fname_size)
342 {
343 bool ta_64bit = false;
344
345 if (file_buffer == NULL || fname == NULL)
346 return LOAD_FAIL;
347
348 if (varify_elf_arch(file_buffer, file_size, &ta_64bit) != TEE_SUCCESS) {
349 tloge("varify elf architecture failed\n");
350 return LOAD_FAIL;
351 }
352
353 if (!add_dyn_client_to_list(fname, fname_size, ta_64bit))
354 return LOAD_FAIL;
355
356 return LOAD_SUCC;
357 }
358
dynamic_load_lib_elf(const load_elf_func_params * param,const struct service_struct * service,const TEE_UUID * uuid,uint64_t memid,tee_img_type_t type)359 int dynamic_load_lib_elf(const load_elf_func_params *param, const struct service_struct *service,
360 const TEE_UUID *uuid, uint64_t memid, tee_img_type_t type)
361 {
362 const TEE_UUID crypto_uuid = CRYPTOMGR;
363 bool is_talib = is_ta_lib(uuid);
364 bool check_value = (param == NULL || uuid == NULL || service == NULL);
365 if (check_value == true)
366 return LOAD_FAIL;
367
368 if (!is_param_valid(param, is_talib, type)) {
369 tloge("load lib elf: param invalid!\n");
370 return LOAD_FAIL;
371 }
372
373 if (uuid_to_libname(uuid, param->fname, param->fname_size, param->lib_name, type) < 0) {
374 tloge("%s uuid_to_fname error!\n", param->fname);
375 return LOAD_FAIL;
376 }
377
378 int ret = is_lib_loaded(service, param->fname, param->fname_size);
379 if (ret == LIB_LOADED)
380 return LIB_EXIST;
381 else if (ret == CHECK_ERROR)
382 return LOAD_FAIL;
383
384 if (proc_load_lib_elf(param->file_buffer, param->file_size, memid, param->fname) != 0)
385 return LOAD_FAIL;
386
387 if (type == IMG_TYPE_DYNAMIC_CLIENT) {
388 ret = record_client_name(param->file_buffer, param->file_size,
389 param->fname, param->fname_size);
390 if (ret != LOAD_SUCC)
391 (void)unlink(param->fname);
392 return ret;
393 }
394 /*
395 * new driver binary is set with ".elf" because it will be dlopend by drvloader
396 * so no need to set uid since the file whose name not end with ".so" can only be dlopend by loader
397 */
398 if (type == IMG_TYPE_DYNAMIC_DRV)
399 return LOAD_SUCC;
400
401 if (type == IMG_TYPE_CRYPTO_DRV)
402 (void)memcpy_s((void *)uuid, sizeof(*uuid), &crypto_uuid, sizeof(*uuid));
403
404 return LOAD_SUCC;
405 }
406