1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <dirent.h>
17 #include <dlfcn.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <linux/limits.h>
22
23 #include "beget_ext.h"
24 #include "config_policy_utils.h"
25 #include "init_utils.h"
26 #include "list.h"
27 #include "securec.h"
28 #include "modulemgr.h"
29
30 #define MODULE_SUFFIX_D ".z.so"
31 #ifdef SUPPORT_64BIT
32 #define MODULE_LIB_NAME "lib64"
33 #else
34 #define MODULE_LIB_NAME "lib"
35 #endif
36 #define LIB_NAME_LEN 3
37
38 struct tagMODULE_MGR {
39 ListNode modules;
40 const char *name;
41 MODULE_INSTALL_ARGS installArgs;
42 };
43
ModuleMgrCreate(const char * name)44 MODULE_MGR *ModuleMgrCreate(const char *name)
45 {
46 MODULE_MGR *moduleMgr;
47
48 BEGET_CHECK(name != NULL, return NULL);
49
50 moduleMgr = (MODULE_MGR *)malloc(sizeof(MODULE_MGR));
51 BEGET_CHECK(moduleMgr != NULL, return NULL);
52 OH_ListInit(&(moduleMgr->modules));
53 moduleMgr->name = strdup(name);
54 if (moduleMgr->name == NULL) {
55 free((void *)moduleMgr);
56 return NULL;
57 }
58 moduleMgr->installArgs.argc = 0;
59 moduleMgr->installArgs.argv = NULL;
60
61 return moduleMgr;
62 }
63
ModuleMgrDestroy(MODULE_MGR * moduleMgr)64 void ModuleMgrDestroy(MODULE_MGR *moduleMgr)
65 {
66 BEGET_CHECK(moduleMgr != NULL, return);
67
68 ModuleMgrUninstall(moduleMgr, NULL);
69 BEGET_CHECK(moduleMgr->name == NULL, free((void *)moduleMgr->name));
70 free((void *)moduleMgr);
71 }
72
73 /*
74 * Module Item related api
75 */
76
77
78 typedef struct tagMODULE_ITEM {
79 ListNode node;
80 MODULE_MGR *moduleMgr;
81 const char *name;
82 void *handle;
83 } MODULE_ITEM;
84
ModuleDestroy(ListNode * node)85 static void ModuleDestroy(ListNode *node)
86 {
87 MODULE_ITEM *module;
88
89 BEGET_CHECK(node != NULL, return);
90
91 module = (MODULE_ITEM *)node;
92 BEGET_CHECK(module->name == NULL, free((void *)module->name));
93 BEGET_CHECK(module->handle == NULL, dlclose(module->handle));
94 free((void *)module);
95 }
96
97 static MODULE_INSTALL_ARGS *currentInstallArgs = NULL;
98
ModuleInstall(MODULE_ITEM * module,int argc,const char * argv[])99 static void *ModuleInstall(MODULE_ITEM *module, int argc, const char *argv[])
100 {
101 void *handle;
102 char path[PATH_MAX];
103 int rc;
104
105 module->moduleMgr->installArgs.argc = argc;
106 module->moduleMgr->installArgs.argv = argv;
107
108 BEGET_LOGV("Module install name %s", module->name);
109 if (module->name[0] == '/') {
110 rc = snprintf_s(path, sizeof(path), sizeof(path) - 1, STARTUP_INIT_UT_PATH"%s" MODULE_SUFFIX_D, module->name);
111 BEGET_CHECK(rc >= 0, return NULL);
112 } else {
113 const char *fmt = (InUpdaterMode() == 0) ? "/system/" MODULE_LIB_NAME : "/" MODULE_LIB_NAME;
114 rc = snprintf_s(path, sizeof(path), sizeof(path) - 1,
115 STARTUP_INIT_UT_PATH"%s/%s/lib%s" MODULE_SUFFIX_D, fmt, module->moduleMgr->name, module->name);
116 BEGET_CHECK(rc >= 0, return NULL);
117 }
118 BEGET_LOGV("Module install path %s", path);
119 char *realPath = GetRealPath(path);
120 BEGET_ERROR_CHECK(realPath != NULL, return NULL, "Failed to get real path");
121 currentInstallArgs = &(module->moduleMgr->installArgs);
122 handle = dlopen(realPath, RTLD_LAZY | RTLD_GLOBAL);
123 currentInstallArgs = NULL;
124 BEGET_CHECK_ONLY_ELOG(handle != NULL, "ModuleInstall path %s fail %d", realPath, errno);
125 free(realPath);
126 return handle;
127 }
128
ModuleCompare(ListNode * node,void * data)129 static int ModuleCompare(ListNode *node, void *data)
130 {
131 MODULE_ITEM *module = (MODULE_ITEM *)node;
132 const char *name = module->name;
133 if (module->name[0] == '/') {
134 name = strrchr((name), '/') + 1;
135 }
136 if (strncmp(name, "lib", LIB_NAME_LEN) == 0) {
137 name = name + LIB_NAME_LEN;
138 }
139 return strcmp(name, (char *)data);
140 }
141
142 /*
143 * 用于扫描安装指定目录下所有的插件。
144 */
ModuleMgrInstall(MODULE_MGR * moduleMgr,const char * moduleName,int argc,const char * argv[])145 int ModuleMgrInstall(MODULE_MGR *moduleMgr, const char *moduleName,
146 int argc, const char *argv[])
147 {
148 MODULE_ITEM *module;
149 BEGET_LOGV("ModuleMgrInstall moduleName %s", moduleName);
150 // Get module manager
151 BEGET_CHECK(!(moduleMgr == NULL || moduleName == NULL), return -1);
152
153 module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)moduleName, ModuleCompare);
154 BEGET_ERROR_CHECK(module == NULL, return 0, "%s module already exists", moduleName);
155
156 // Create module item
157 module = (MODULE_ITEM *)malloc(sizeof(MODULE_ITEM));
158 BEGET_CHECK(module != NULL, return -1);
159
160 module->handle = NULL;
161 module->moduleMgr = moduleMgr;
162
163 module->name = strdup(moduleName);
164 BEGET_CHECK(module->name != NULL, free(module);
165 return -1);
166
167 // Install
168 module->handle = ModuleInstall(module, argc, argv);
169 #ifndef STARTUP_INIT_TEST
170 if (module->handle == NULL) {
171 BEGET_LOGE("Failed to install module %s", module->name);
172 ModuleDestroy((ListNode *)module);
173 return -1;
174 }
175 #endif
176 // Add to list
177 OH_ListAddTail(&(moduleMgr->modules), (ListNode *)module);
178
179 return 0;
180 }
181
ModuleMgrGetArgs(void)182 const MODULE_INSTALL_ARGS *ModuleMgrGetArgs(void)
183 {
184 return currentInstallArgs;
185 }
186
StringEndsWith(const char * srcStr,const char * endStr)187 static int StringEndsWith(const char *srcStr, const char *endStr)
188 {
189 int srcStrLen = strlen(srcStr);
190 int endStrLen = strlen(endStr);
191
192 BEGET_CHECK(!(srcStrLen < endStrLen), return -1);
193
194 srcStr += (srcStrLen - endStrLen);
195 BEGET_CHECK(strcmp(srcStr, endStr) != 0, return (srcStrLen - endStrLen));
196 return -1;
197 }
198
ScanModules(MODULE_MGR * moduleMgr,const char * path)199 static void ScanModules(MODULE_MGR *moduleMgr, const char *path)
200 {
201 BEGET_LOGV("Scan module with name '%s'", path);
202 DIR *dir = opendir(path);
203 BEGET_CHECK(dir != NULL, return);
204 char *moduleName = calloc(PATH_MAX, sizeof(char));
205 while (moduleName != NULL) {
206 struct dirent *file = readdir(dir);
207 if (file == NULL) {
208 break;
209 }
210 if ((file->d_type != DT_REG) && (file->d_type != DT_LNK)) {
211 continue;
212 }
213
214 // Must be ended with MODULE_SUFFIX_D
215 int end = StringEndsWith(file->d_name, MODULE_SUFFIX_D);
216 if (end <= 0) {
217 continue;
218 }
219
220 file->d_name[end] = '\0';
221 int len = sprintf_s(moduleName, PATH_MAX - 1, "%s/%s", path, file->d_name);
222 if (len > 0) {
223 moduleName[len] = '\0';
224 BEGET_LOGI("Scan module with name '%s'", moduleName);
225 ModuleMgrInstall(moduleMgr, moduleName, 0, NULL);
226 }
227 }
228 if (moduleName != NULL) {
229 free(moduleName);
230 }
231 closedir(dir);
232 }
233
234 /*
235 * 用于扫描安装指定目录下所有的插件。
236 */
ModuleMgrScan(const char * modulePath)237 MODULE_MGR *ModuleMgrScan(const char *modulePath)
238 {
239 MODULE_MGR *moduleMgr;
240 char path[PATH_MAX];
241 BEGET_LOGV("ModuleMgrScan moduleName %s", modulePath);
242 moduleMgr = ModuleMgrCreate(modulePath);
243 BEGET_CHECK(moduleMgr != NULL, return NULL);
244
245 if (modulePath[0] == '/') {
246 ScanModules(moduleMgr, modulePath);
247 } else if (InUpdaterMode() == 1) {
248 BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1,
249 "/%s/%s", MODULE_LIB_NAME, modulePath) > 0, free((void *)moduleMgr); return NULL);
250 ScanModules(moduleMgr, path);
251 } else {
252 BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1,
253 "%s/%s", MODULE_LIB_NAME, modulePath) > 0, free((void *)moduleMgr); return NULL);
254 CfgFiles *files = GetCfgFiles(path);
255 for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) {
256 if (files->paths[i]) {
257 ScanModules(moduleMgr, files->paths[i]);
258 }
259 }
260 FreeCfgFiles(files);
261 }
262 return moduleMgr;
263 }
264
265 /*
266 * 卸载指定插件。
267 */
ModuleMgrUninstall(MODULE_MGR * moduleMgr,const char * name)268 void ModuleMgrUninstall(MODULE_MGR *moduleMgr, const char *name)
269 {
270 MODULE_ITEM *module;
271 BEGET_CHECK(moduleMgr != NULL, return);
272 // Uninstall all modules if no name specified
273 if (name == NULL) {
274 OH_ListRemoveAll(&(moduleMgr->modules), ModuleDestroy);
275 return;
276 }
277 BEGET_LOGV("ModuleMgrUninstall moduleName %s", name);
278 // Find module by name
279 module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)name, ModuleCompare);
280 BEGET_ERROR_CHECK(module != NULL, return, "Can not find module %s", name);
281
282 // Remove from the list
283 OH_ListRemove((ListNode *)module);
284 // Destroy the module
285 ModuleDestroy((ListNode *)module);
286 }
287
ModuleMgrGetCnt(const MODULE_MGR * moduleMgr)288 int ModuleMgrGetCnt(const MODULE_MGR *moduleMgr)
289 {
290 BEGET_CHECK(moduleMgr != NULL, return 0);
291 return OH_ListGetCnt(&(moduleMgr->modules));
292 }
293
294 typedef struct tagMODULE_TRAVERSAL_ARGS {
295 void *cookie;
296 OhosModuleTraversal traversal;
297 } MODULE_TRAVERSAL_ARGS;
298
ModuleTraversalProc(ListNode * node,void * cookie)299 static int ModuleTraversalProc(ListNode *node, void *cookie)
300 {
301 MODULE_ITEM *module;
302 MODULE_TRAVERSAL_ARGS *args;
303 MODULE_INFO info;
304
305 module = (MODULE_ITEM *)node;
306 args = (MODULE_TRAVERSAL_ARGS *)cookie;
307
308 info.cookie = args->cookie;
309 info.handle = module->handle;
310 info.name = module->name;
311 args->traversal(&info);
312
313 return 0;
314 }
315
316 /**
317 * @brief Traversing all hooks in the HookManager
318 *
319 * @param moduleMgr HookManager handle.
320 * If hookMgr is NULL, it will use default HookManager
321 * @param cookie traversal cookie.
322 * @param traversal traversal function.
323 * @return None.
324 */
ModuleMgrTraversal(const MODULE_MGR * moduleMgr,void * cookie,OhosModuleTraversal traversal)325 void ModuleMgrTraversal(const MODULE_MGR *moduleMgr, void *cookie, OhosModuleTraversal traversal)
326 {
327 MODULE_TRAVERSAL_ARGS args;
328 if (moduleMgr == NULL) {
329 return;
330 }
331
332 args.cookie = cookie;
333 args.traversal = traversal;
334 OH_ListTraversal((ListNode *)(&(moduleMgr->modules)), (void *)(&args), ModuleTraversalProc, 0);
335 }
336