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 38struct tagMODULE_MGR { 39 ListNode modules; 40 const char *name; 41 MODULE_INSTALL_ARGS installArgs; 42}; 43 44MODULE_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 64void 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 78typedef struct tagMODULE_ITEM { 79 ListNode node; 80 MODULE_MGR *moduleMgr; 81 const char *name; 82 void *handle; 83} MODULE_ITEM; 84 85static 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 97static MODULE_INSTALL_ARGS *currentInstallArgs = NULL; 98 99static 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 129static 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 */ 145int 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 182const MODULE_INSTALL_ARGS *ModuleMgrGetArgs(void) 183{ 184 return currentInstallArgs; 185} 186 187static 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 199static 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 */ 237MODULE_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 */ 268void 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 288int ModuleMgrGetCnt(const MODULE_MGR *moduleMgr) 289{ 290 BEGET_CHECK(moduleMgr != NULL, return 0); 291 return OH_ListGetCnt(&(moduleMgr->modules)); 292} 293 294typedef struct tagMODULE_TRAVERSAL_ARGS { 295 void *cookie; 296 OhosModuleTraversal traversal; 297} MODULE_TRAVERSAL_ARGS; 298 299static 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 */ 325void 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