• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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