1 /*
2 * Copyright (C) 2023 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 #include "tee_load_dynamic.h"
14 #include <sys/stat.h> /* for stat */
15 #include <dirent.h>
16 #include <limits.h>
17
18 #include "securec.h"
19 #include "tc_ns_client.h"
20 #include "tee_log.h"
21 #include "secfile_load_agent.h"
22
23 #ifdef LOG_TAG
24 #undef LOG_TAG
25 #endif
26 #define LOG_TAG "teecd_load_dynamic"
27
28 #if defined(DYNAMIC_DRV_DIR) || defined(DYNAMIC_CRYPTO_DRV_DIR) || defined(DYNAMIC_SRV_DIR)
29 #define MAX_FILE_NAME_LEN 128
30
OpenDynamicDir(const char * dynDir)31 static DIR *OpenDynamicDir(const char *dynDir)
32 {
33 DIR *dir = opendir(dynDir);
34 if (dir == NULL) {
35 tlogw("open drv dir: %" PUBLIC "s failed\n", dynDir);
36 }
37
38 return dir;
39 }
40
endsWith(const char * str,const char * suffix)41 static int32_t endsWith(const char *str, const char *suffix)
42 {
43 size_t strLen = strnlen(str, MAX_FILE_NAME_LEN);
44 size_t suffixLen = strnlen(suffix, MAX_FILE_NAME_LEN);
45 if (suffixLen > strLen || strLen == 0 || strLen >= MAX_FILE_NAME_LEN || suffixLen == 0) {
46 return -1;
47 }
48
49 const char *ptr = str + (strLen - suffixLen);
50 if (strcmp(ptr, suffix) == 0) {
51 return 0;
52 }
53
54 return -1;
55 }
56
LoadOneFile(const char * dynDir,const struct dirent * dirFile,int32_t fd,uint32_t loadType)57 static int32_t LoadOneFile(const char *dynDir, const struct dirent *dirFile, int32_t fd, uint32_t loadType)
58 {
59 char name[MAX_FILE_NAME_LEN];
60 FILE *fp = NULL;
61 int32_t ret = -1;
62
63 if (endsWith(dirFile->d_name, ".sec") != 0) {
64 tloge("file name does not end with .sec\n");
65 goto END;
66 }
67
68 if (memset_s(name, sizeof(name), 0, sizeof(name)) != 0) {
69 tloge("mem set failed, name: %" PUBLIC "s, size: %" PUBLIC "u\n", name, (uint32_t)sizeof(name));
70 goto END;
71 }
72 if (strcat_s(name, MAX_FILE_NAME_LEN, dynDir) != 0) {
73 tloge("dir name too long: %" PUBLIC "s\n", dynDir);
74 goto END;
75 }
76 if (strcat_s(name, MAX_FILE_NAME_LEN, dirFile->d_name) != 0) {
77 tloge("drv name too long: %" PUBLIC "s\n", dirFile->d_name);
78 goto END;
79 }
80
81 fp = fopen(name, "r");
82 if (fp == NULL) {
83 tloge("open drv failed: %" PUBLIC "s\n", name);
84 goto END;
85 }
86
87 ret = LoadSecFile(fd, fp, loadType, NULL);
88 if (ret != 0) {
89 tloge("load dynamic failed: %" PUBLIC "s\n", name);
90 }
91
92 END:
93 if (fp != NULL) {
94 (void)fclose(fp);
95 }
96
97 return ret;
98 }
99
LoadOneDynamicDir(int32_t fd,const char * dynDir,uint32_t loadType)100 static int32_t LoadOneDynamicDir(int32_t fd, const char *dynDir, uint32_t loadType)
101 {
102 int32_t ret = -1;
103 struct dirent *dirFile = NULL;
104
105 DIR *dir = OpenDynamicDir(dynDir);
106 if (dir == NULL) {
107 tlogi("dynamic dir not exist dyndir=%" PUBLIC"s\n", dynDir);
108 return ret;
109 }
110 while ((dirFile = readdir(dir)) != NULL) {
111 if (dirFile->d_type != DT_REG) {
112 tlogd("no need to load\n");
113 continue;
114 }
115 ret = LoadOneFile(dynDir, dirFile, fd, loadType);
116 if (ret != 0) {
117 tlogd("load dynamic failed\n");
118 continue;
119 }
120 }
121
122 (void)closedir(dir);
123 return ret;
124 }
125
LoadDynamicCryptoDir(void)126 void LoadDynamicCryptoDir(void)
127 {
128 #ifdef DYNAMIC_CRYPTO_DRV_DIR
129 int32_t fd = GetSecLoadAgentFd();
130 (void)LoadOneDynamicDir(fd, DYNAMIC_CRYPTO_DRV_DIR, LOAD_DYNAMIC_DRV);
131 #endif
132 }
133
CheckPath(const char * drvPath,uint32_t drvPathLen,char * trustDrvPath)134 static int32_t CheckPath(const char *drvPath, uint32_t drvPathLen, char *trustDrvPath)
135 {
136 char trustDrvRootPath[PATH_MAX] = {0};
137 size_t optLen = strnlen(drvPath, MAX_FILE_NAME_LEN);
138 if (optLen == 0 || optLen >= MAX_FILE_NAME_LEN || drvPathLen != optLen) {
139 tloge("drv path is invalid\n");
140 return -1;
141 }
142
143 size_t rootLen = strnlen(DYNAMIC_DRV_DIR, MAX_FILE_NAME_LEN);
144 if (rootLen == 0 || rootLen >= MAX_FILE_NAME_LEN) {
145 tloge("drv root path is invalid\n");
146 return -1;
147 }
148
149 if (realpath(drvPath, trustDrvPath) == NULL) {
150 tloge("check realpath failed\n");
151 return -1;
152 }
153
154 if (realpath(DYNAMIC_DRV_DIR, trustDrvRootPath) == NULL) {
155 tloge("check realpath failed\n");
156 return -1;
157 }
158
159 rootLen = strnlen(trustDrvRootPath, MAX_FILE_NAME_LEN);
160 if (rootLen == 0 || rootLen >= MAX_FILE_NAME_LEN) {
161 tloge("drv root path is invalid\n");
162 return -1;
163 }
164
165 optLen = strnlen(trustDrvPath, MAX_FILE_NAME_LEN);
166 if (optLen <= rootLen || optLen >= MAX_FILE_NAME_LEN) {
167 tloge("drv path is invalid\n");
168 return -1;
169 }
170
171 if (strncmp(trustDrvPath, trustDrvRootPath, rootLen) != 0) {
172 tloge("drv path is invalid, %" PUBLIC "s, %" PUBLIC "s\n", trustDrvPath, trustDrvRootPath);
173 return -1;
174 }
175
176 return 0;
177 }
178
LoadDynamicDrvDir(const char * drvPath,uint32_t drvPathLen)179 void LoadDynamicDrvDir(const char *drvPath, uint32_t drvPathLen)
180 {
181 #ifdef DYNAMIC_DRV_DIR
182 int32_t fd = GetSecLoadAgentFd();
183 if (drvPathLen == 0 || drvPath == NULL) {
184 #ifdef DYNAMIC_DRV_FEIMA_DIR
185 if (LoadOneDynamicDir(fd, DYNAMIC_DRV_FEIMA_DIR, LOAD_DYNAMIC_DRV)) {
186 #endif
187 LoadOneDynamicDir(fd, DYNAMIC_DRV_DIR, LOAD_DYNAMIC_DRV);
188 #ifdef DYNAMIC_DRV_FEIMA_DIR
189 }
190 #endif
191 } else {
192 char trustDrvPath[PATH_MAX] = {0};
193 if (CheckPath(drvPath, drvPathLen, trustDrvPath) != 0) {
194 tloge("check path failed\n");
195 return;
196 }
197 if (strcat_s(trustDrvPath, PATH_MAX, "/") != 0) {
198 tloge("add / to trust drv path failed\n");
199 return;
200 }
201
202 (void)LoadOneDynamicDir(fd, drvPath, LOAD_DYNAMIC_DRV);
203 }
204 #endif
205 }
206
LoadDynamicSrvDir(void)207 void LoadDynamicSrvDir(void)
208 {
209 #ifdef DYNAMIC_SRV_DIR
210 int32_t fd = GetSecLoadAgentFd();
211 #ifdef DYNAMIC_SRV_FEIMA_DIR
212 if (LoadOneDynamicDir(fd, DYNAMIC_SRV_FEIMA_DIR, LOAD_SERVICE)) {
213 #endif
214 (void)LoadOneDynamicDir(fd, DYNAMIC_SRV_DIR, LOAD_SERVICE);
215 #ifdef DYNAMIC_SRV_FEIMA_DIR
216 }
217 #endif
218 #endif
219 }
220 #endif
221