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