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
104 module->moduleMgr->installArgs.argc = argc;
105 module->moduleMgr->installArgs.argv = argv;
106
107 BEGET_LOGV("Module install name %s", module->name);
108 if (module->name[0] == '/') {
109 if (snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s" MODULE_SUFFIX_D, module->name) < 0) {
110 return NULL;
111 }
112 } else {
113 const char *fmt = (InUpdaterMode() == 0) ? "/system/" MODULE_LIB_NAME : "/" MODULE_LIB_NAME;
114 if (snprintf_s(path, sizeof(path), sizeof(path) - 1,
115 "%s/%s/lib%s" MODULE_SUFFIX_D, fmt, module->moduleMgr->name, module->name) < 0) {
116 return NULL;
117 }
118 }
119 BEGET_LOGV("Module install path %s", path);
120 char *realPath = GetRealPath(path);
121 BEGET_ERROR_CHECK(realPath != NULL, return NULL, "Failed to get real path");
122 currentInstallArgs = &(module->moduleMgr->installArgs);
123 handle = dlopen(realPath, RTLD_LAZY | RTLD_GLOBAL);
124 currentInstallArgs = NULL;
125 BEGET_CHECK_ONLY_ELOG(handle != NULL, "ModuleInstall path %s fail %d", realPath, errno);
126 free(realPath);
127 return handle;
128 }
129
ModuleCompare(ListNode * node,void * data)130 static int ModuleCompare(ListNode *node, void *data)
131 {
132 MODULE_ITEM *module = (MODULE_ITEM *)node;
133 const char *name = module->name;
134 if (module->name[0] == '/') {
135 name = strrchr((name), '/') + 1;
136 }
137 if (strncmp(name, "lib", LIB_NAME_LEN) == 0) {
138 name = name + LIB_NAME_LEN;
139 }
140 return strcmp(name, (char *)data);
141 }
142
143 /*
144 * 用于扫描安装指定目录下所有的插件。
145 */
ModuleMgrInstall(MODULE_MGR * moduleMgr,const char * moduleName,int argc,const char * argv[])146 int ModuleMgrInstall(MODULE_MGR *moduleMgr, const char *moduleName,
147 int argc, const char *argv[])
148 {
149 MODULE_ITEM *module;
150 BEGET_LOGV("ModuleMgrInstall moduleName %s", moduleName);
151 // Get module manager
152 BEGET_CHECK(!(moduleMgr == NULL || moduleName == NULL), return -1);
153
154 module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)moduleName, ModuleCompare);
155 BEGET_ERROR_CHECK(module == NULL, return 0, "%s module already exists", moduleName);
156
157 // Create module item
158 module = (MODULE_ITEM *)malloc(sizeof(MODULE_ITEM));
159 BEGET_CHECK(module != NULL, return -1);
160
161 module->handle = NULL;
162 module->moduleMgr = moduleMgr;
163
164 module->name = strdup(moduleName);
165 if (module->name == NULL) {
166 ModuleDestroy((ListNode *)module);
167 return -1;
168 }
169
170 // Install
171 module->handle = ModuleInstall(module, argc, argv);
172 if (module->handle == NULL) {
173 BEGET_LOGE("Failed to install module %s", module->name);
174 ModuleDestroy((ListNode *)module);
175 return -1;
176 }
177
178 // Add to list
179 OH_ListAddTail(&(moduleMgr->modules), (ListNode *)module);
180
181 return 0;
182 }
183
ModuleMgrGetArgs(void)184 const MODULE_INSTALL_ARGS *ModuleMgrGetArgs(void)
185 {
186 return currentInstallArgs;
187 }
188
StringEndsWith(const char * srcStr,const char * endStr)189 static int StringEndsWith(const char *srcStr, const char *endStr)
190 {
191 int srcStrLen = strlen(srcStr);
192 int endStrLen = strlen(endStr);
193
194 BEGET_CHECK(!(srcStrLen < endStrLen), return -1);
195
196 srcStr += (srcStrLen - endStrLen);
197 BEGET_CHECK(strcmp(srcStr, endStr) != 0, return (srcStrLen - endStrLen));
198 return -1;
199 }
200
ScanModules(MODULE_MGR * moduleMgr,const char * path)201 static void ScanModules(MODULE_MGR *moduleMgr, const char *path)
202 {
203 BEGET_LOGV("Scan module with name '%s'", path);
204 DIR *dir = opendir(path);
205 BEGET_CHECK(dir != NULL, return);
206 char *moduleName = malloc(PATH_MAX);
207 while (moduleName != NULL) {
208 struct dirent *file = readdir(dir);
209 if (file == NULL) {
210 break;
211 }
212 if ((file->d_type != DT_REG) && (file->d_type != DT_LNK)) {
213 continue;
214 }
215
216 // Must be ended with MODULE_SUFFIX_D
217 int end = StringEndsWith(file->d_name, MODULE_SUFFIX_D);
218 if (end <= 0) {
219 continue;
220 }
221
222 file->d_name[end] = '\0';
223 int len = sprintf_s(moduleName, PATH_MAX - 1, "%s/%s", path, file->d_name);
224 if (len > 0) {
225 moduleName[len] = '\0';
226 BEGET_LOGI("Scan module with name '%s'", moduleName);
227 ModuleMgrInstall(moduleMgr, moduleName, 0, NULL);
228 }
229 }
230 if (moduleName != NULL) {
231 free(moduleName);
232 }
233 closedir(dir);
234 }
235
236 /*
237 * 用于扫描安装指定目录下所有的插件。
238 */
ModuleMgrScan(const char * modulePath)239 MODULE_MGR *ModuleMgrScan(const char *modulePath)
240 {
241 MODULE_MGR *moduleMgr;
242 char path[PATH_MAX];
243
244 moduleMgr = ModuleMgrCreate(modulePath);
245 BEGET_CHECK(moduleMgr != NULL, return NULL);
246
247 if (modulePath[0] == '/') {
248 ScanModules(moduleMgr, modulePath);
249 } else if (InUpdaterMode() == 1) {
250 BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1,
251 "/%s/%s", MODULE_LIB_NAME, modulePath) > 0, return NULL);
252 ScanModules(moduleMgr, path);
253 } else {
254 BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1,
255 "%s/%s", MODULE_LIB_NAME, modulePath) > 0, return NULL);
256 CfgFiles *files = GetCfgFiles(path);
257 for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) {
258 if (files->paths[i]) {
259 ScanModules(moduleMgr, files->paths[i]);
260 }
261 }
262 FreeCfgFiles(files);
263 }
264 return moduleMgr;
265 }
266
267 /*
268 * 卸载指定插件。
269 */
ModuleMgrUninstall(MODULE_MGR * moduleMgr,const char * name)270 void ModuleMgrUninstall(MODULE_MGR *moduleMgr, const char *name)
271 {
272 MODULE_ITEM *module;
273 BEGET_CHECK(moduleMgr != NULL, return);
274 // Uninstall all modules if no name specified
275 if (name == NULL) {
276 OH_ListRemoveAll(&(moduleMgr->modules), ModuleDestroy);
277 return;
278 }
279 BEGET_LOGV("ModuleMgrUninstall moduleName %s", name);
280 // Find module by name
281 module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)name, ModuleCompare);
282 BEGET_ERROR_CHECK(module != NULL, return, "Can not find module %s", name);
283
284 // Remove from the list
285 OH_ListRemove((ListNode *)module);
286 // Destroy the module
287 ModuleDestroy((ListNode *)module);
288 }
289
ModuleMgrGetCnt(const MODULE_MGR * moduleMgr)290 int ModuleMgrGetCnt(const MODULE_MGR *moduleMgr)
291 {
292 BEGET_CHECK(moduleMgr != NULL, return 0);
293 return OH_ListGetCnt(&(moduleMgr->modules));
294 }
295
296 typedef struct tagMODULE_TRAVERSAL_ARGS {
297 void *cookie;
298 OhosModuleTraversal traversal;
299 } MODULE_TRAVERSAL_ARGS;
300
ModuleTraversalProc(ListNode * node,void * cookie)301 static int ModuleTraversalProc(ListNode *node, void *cookie)
302 {
303 MODULE_ITEM *module;
304 MODULE_TRAVERSAL_ARGS *args;
305 MODULE_INFO info;
306
307 module = (MODULE_ITEM *)node;
308 args = (MODULE_TRAVERSAL_ARGS *)cookie;
309
310 info.cookie = args->cookie;
311 info.handle = module->handle;
312 info.name = module->name;
313 args->traversal(&info);
314
315 return 0;
316 }
317
318 /**
319 * @brief Traversing all hooks in the HookManager
320 *
321 * @param moduleMgr HookManager handle.
322 * If hookMgr is NULL, it will use default HookManager
323 * @param cookie traversal cookie.
324 * @param traversal traversal function.
325 * @return None.
326 */
ModuleMgrTraversal(const MODULE_MGR * moduleMgr,void * cookie,OhosModuleTraversal traversal)327 void ModuleMgrTraversal(const MODULE_MGR *moduleMgr, void *cookie, OhosModuleTraversal traversal)
328 {
329 MODULE_TRAVERSAL_ARGS args;
330 if (moduleMgr == NULL) {
331 return;
332 }
333
334 args.cookie = cookie;
335 args.traversal = traversal;
336 OH_ListTraversal((ListNode *)(&(moduleMgr->modules)), (void *)(&args), ModuleTraversalProc, 0);
337 }
338