• 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 "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