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