• 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 "tee_load_lib.h"
13 #include <stdlib.h>
14 #include <fileio.h>
15 #include "securec.h"
16 #include "tee_inner_uuid.h"
17 #include "gtask_core.h" /* for find_service */
18 #include "tee_time_api.h"
19 #include "service_manager.h"
20 #include "session_manager.h"
21 #include "init.h"
22 
23 #define PREFIX_LEN           6 /* prefix: /tafs/ */
24 #define LIB_AGED_TIME_LIMIT  10000U /* unit: millis */
25 #define LIB_LIMIT_COUNT      5U
26 
get_lib_count(const struct service_struct * service)27 static uint32_t get_lib_count(const struct service_struct *service)
28 {
29     uint32_t count = 0;
30     struct lib_info *cur = NULL;
31 
32     cur = service->lib_list_head.next;
33 
34     while ((cur != NULL) && (cur->type != IMG_TYPE_DYNAMIC_DRV) &&
35            (cur->type != IMG_TYPE_CRYPTO_DRV)) {
36         count++;
37         cur = cur->next;
38     }
39 
40     return count;
41 }
42 
is_aged_lib(const struct lib_info * libinfo)43 static bool is_aged_lib(const struct lib_info *libinfo)
44 {
45     TEE_Time current = { 0, 0 };
46     uint64_t interval;
47 
48     if (libinfo == NULL) {
49         tloge("invalid param\n");
50         return false;
51     }
52 
53     /* for dynamic_drv, donnot need aged */
54     if (libinfo->type == IMG_TYPE_DYNAMIC_DRV || libinfo->type == IMG_TYPE_CRYPTO_DRV ||
55         libinfo->type == IMG_TYPE_DYNAMIC_CLIENT)
56         return false;
57 
58     TEE_GetSystemTime(&current);
59 
60     get_interval(&current, &libinfo->load_elf_time, &interval);
61 
62     if (interval > LIB_AGED_TIME_LIMIT) {
63         tlogi("aged lib: name is %s, and seconds interval =%llu, max interval = %u\n",
64               libinfo->name, (unsigned long long)interval, LIB_AGED_TIME_LIMIT);
65         return true;
66     }
67     return false;
68 }
69 
do_age_timeout_lib(struct service_struct * service)70 void do_age_timeout_lib(struct service_struct *service)
71 {
72     struct lib_info *cur = NULL;
73     struct lib_info *pre = NULL;
74     struct lib_info *tmp = NULL;
75 
76     if (service == NULL)
77         return;
78 
79     pre = &service->lib_list_head;
80     cur = pre->next;
81     while (cur != NULL) {
82         if (is_aged_lib(cur)) {
83             tmp = cur->next;
84             if (unlink(cur->name) != 0)
85                 tloge("unlink %s failed\n", cur->name);
86             free(cur);
87             pre->next = tmp;
88             cur = pre->next;
89         } else {
90             pre = cur;
91             cur = cur->next;
92         }
93     }
94 }
95 
is_lib_loaded(const struct service_struct * service,const char * name,size_t name_size)96 int is_lib_loaded(const struct service_struct *service, const char *name, size_t name_size)
97 {
98     int ret = LIB_NOT_LOADED;
99     struct lib_info *cur = NULL;
100 
101     if (service == NULL || name == NULL || name_size > LIB_NAME_MAX) {
102         tloge("input param is null\n");
103         return CHECK_ERROR;
104     }
105 
106     cur = service->lib_list_head.next;
107     while (cur != NULL) {
108         /* compare length add 1 in order to include "\0" */
109         if (strncmp(name, cur->name, (strlen(cur->name) + 1)) == 0) {
110             tlogi("already in the list, file_name = %s\n", name);
111             ret = LIB_LOADED;
112             break;
113         } else {
114             cur = cur->next;
115         }
116     }
117 
118     return ret;
119 }
120 
tee_add_libinfo(struct service_struct * service,const char * name,size_t name_size,tee_img_type_t type)121 TEE_Result tee_add_libinfo(struct service_struct *service, const char *name, size_t name_size,
122                            tee_img_type_t type)
123 {
124     struct lib_info *libinfo = NULL;
125     bool check_value = (service == NULL || name == NULL);
126     if (check_value == true) {
127         tloge("params error\n");
128         return TEE_ERROR_GENERIC;
129     }
130     if (is_lib_loaded(service, name, name_size) != LIB_NOT_LOADED) {
131         tloge("already in the list or param is invalid!\n");
132         return TEE_ERROR_GENERIC;
133     }
134 
135     /* dynamic_drv lib should not be limited by IMG_TYPE_DYNAMIC_DRV and CRYPTO_DRV */
136     if ((type != IMG_TYPE_DYNAMIC_DRV) && (get_lib_count(service) > LIB_LIMIT_COUNT) &&
137         (type != IMG_TYPE_CRYPTO_DRV)) {
138         tlogi("already load %u lib, caution!\n", LIB_LIMIT_COUNT);
139         return TEE_ERROR_GENERIC;
140     }
141 
142     libinfo = (struct lib_info *)malloc(sizeof(*libinfo));
143     if (libinfo == NULL) {
144         tloge("libinfo malloc failed\n");
145         return TEE_ERROR_GENERIC;
146     }
147 
148     if (strcpy_s(libinfo->name, sizeof(libinfo->name), name) != EOK) { /* with /tafs/ prefix */
149         free(libinfo);
150         return TEE_ERROR_GENERIC;
151     }
152 
153     TEE_GetSystemTime(&libinfo->load_elf_time);
154     libinfo->type = type;
155     tlogd("libinfo add node: %s at sec: %u is drv: %d\n",
156           libinfo->name, libinfo->load_elf_time.seconds, (int32_t)libinfo->type);
157     libinfo->next = service->lib_list_head.next;
158     service->lib_list_head.next = libinfo;
159 
160     return TEE_SUCCESS;
161 }
162 
tee_delete_all_libinfo(struct service_struct * service)163 void tee_delete_all_libinfo(struct service_struct *service)
164 {
165     struct lib_info *libinfo = NULL;
166     struct lib_info *next    = NULL;
167 
168     if (service == NULL) {
169         tloge("params error\n");
170         return;
171     }
172     libinfo = service->lib_list_head.next;
173     while (libinfo != NULL) {
174         next = libinfo->next;
175         if (unlink(libinfo->name) != 0)
176             tloge("unlink %s failed\n", libinfo->name);
177         free(libinfo);
178         libinfo = next;
179     }
180     service->lib_list_head.next = NULL;
181     return;
182 }
183 
tee_delete_single_libinfo(struct service_struct * service,const char * lib_name)184 static void tee_delete_single_libinfo(struct service_struct *service, const char *lib_name)
185 {
186     struct lib_info *pre = NULL;
187     struct lib_info *cur = NULL;
188 
189     if (service->lib_list_head.next == NULL) {
190         tloge("no node in lib_list and %s won't be deleted!\n", lib_name);
191         return;
192     }
193     if (strnlen(lib_name, LIB_NAME_MAX) == LIB_NAME_MAX) {
194         tloge("lib name is too long\n");
195         return;
196     }
197 
198     pre = &service->lib_list_head;
199     cur = service->lib_list_head.next;
200 
201     while (cur != NULL) {
202         /*
203          * compare length add 1 in order to include "\0"
204          * otherwise it may delete wrong lib, for example:
205          * lib1: test.so
206          * lib2: testa.so
207          * when input name is test, it may unlink test.so or testa.so
208          */
209         if (strncmp(lib_name, cur->name + PREFIX_LEN, (size_t)(strlen(lib_name) + 1)) == 0) {
210             if (unlink(cur->name) != 0)
211                 tloge("unlink %s failed\n", cur->name);
212             /*
213              * for dynamic_drv, only unlink from tafs, donnot delete it from
214              * lib_list, to avoid teecd was killed
215              */
216             if (cur->type == IMG_TYPE_DYNAMIC_DRV || cur->type == IMG_TYPE_CRYPTO_DRV)
217                 return;
218             pre->next = cur->next;
219             free(cur);
220             return;
221         } else {
222             pre = cur;
223             cur = cur->next;
224         }
225     }
226     tloge("%s not exist in lib list!\n", lib_name);
227     return;
228 }
229 
process_unlink(const struct ta_unlink_lib_msg * ret_msg,uint32_t task_id)230 static void process_unlink(const struct ta_unlink_lib_msg *ret_msg, uint32_t task_id)
231 {
232     struct service_struct *cur_service = NULL;
233     struct session_struct *cur_session = NULL;
234 
235     if (ret_msg == NULL) {
236         tloge("ret_msg is NULL!\n");
237         return;
238     }
239 
240     if (!ret_msg->is_drvlib) {
241         if (find_task(task_id, &cur_service, &cur_session) == false) {
242             tloge("fail to find service or session!\n");
243             return;
244         }
245     } else {
246         TEE_UUID uuid = TEE_SERVICE_GLOBAL;
247         if (find_service(&uuid, 0, &cur_service) == INVALID_SERVICE_INDEX)
248             return;
249     }
250     tee_delete_single_libinfo(cur_service, ret_msg->lib_name);
251     return;
252 }
253 
handle_unlink_dynamic_drv(uint32_t cmd_id,uint32_t task_id,const uint8_t * msg_buf,uint32_t msg_size)254 int32_t handle_unlink_dynamic_drv(uint32_t cmd_id, uint32_t task_id, const uint8_t *msg_buf, uint32_t msg_size)
255 {
256     struct ta_unlink_lib_msg msg;
257 
258     (void)cmd_id;
259     if (msg_size <= sizeof(msg.lib_name)) {
260         tloge("msg_size:0x%x error\n", msg_size);
261         return GT_ERR_END_CMD;
262     }
263 
264     uint32_t drv_id;
265     if (get_drvmgr_pid(&drv_id) != 0) {
266         tloge("get drvmgr taskid failed\n");
267         return GT_ERR_END_CMD;
268     }
269 
270     if (taskid_to_pid(task_id) != drv_id) {
271         tloge("task:0x%x not support unlink dynamic drv lib\n", task_id);
272         return GT_ERR_END_CMD;
273     }
274 
275     /*
276      * for dynamic_drv, only unlink it from tafs, donot delete it's libinfo
277      * from lib_list, to denied teecd was killed.
278      */
279     (void)memset_s(&msg, sizeof(msg), 0, sizeof(msg));
280     errno_t rc = memcpy_s(msg.lib_name, sizeof(msg.lib_name) - 1, msg_buf, sizeof(msg.lib_name) - 1);
281     if (rc != EOK) {
282         tloge("[error]memcpy_s failed, rc=%d, line:%d.\n", rc, __LINE__);
283         return GT_ERR_END_CMD;
284     }
285     msg.lib_name[LIB_NAME_MAX - 1] = '\0';
286     msg.is_drvlib = true;
287 
288     process_unlink(&msg, 0); /* taskid not used when is_drvlib is true */
289 
290     return GT_ERR_OK;
291 }
292