From deddf477e11a93c4062fc89b81f2cb58677f8e0a Mon Sep 17 00:00:00 2001 From: Mupceet Date: Mon, 8 Aug 2022 20:15:04 +0800 Subject: [PATCH] init: add system plugin adapter Signed-off-by: Mupceet --- interfaces/innerkits/BUILD.gn | 1 + interfaces/innerkits/hookmgr/hookmgr.c | 6 +- .../init_module_engine/include/bootstage.h | 84 ++++++++++- .../include/init_module_engine.h | 1 + .../init_module_engine/stub/libinit.stub.json | 4 +- services/begetctl/param_cmd.c | 1 - services/init/include/init_service.h | 3 + services/init/include/init_service_manager.h | 2 - services/init/init_common_service.c | 57 ++++++++ services/init/init_service_manager.c | 19 +++ services/init/lite/BUILD.gn | 1 + services/init/standard/init.c | 19 --- services/modules/BUILD.gn | 46 +----- services/modules/bootchart/BUILD.gn | 52 +++++++ services/modules/bootevent/BUILD.gn | 1 + services/modules/bootevent/bootevent.c | 53 ++++--- services/modules/init_hook/BUILD.gn | 56 ++++++++ services/modules/init_hook/init_hook.c | 135 ++++++++++++++++++ services/modules/init_hook/init_hook.h | 56 ++++++++ services/modules/init_hook/param_hook.c | 65 +++++++++ services/modules/plugin_adapter.h | 12 ++ services/param/base/param_trie.c | 5 +- services/param/include/param_manager.h | 17 ++- services/param/include/param_osadp.h | 1 + services/param/linux/BUILD.gn | 1 + services/param/linux/param_request.c | 7 +- services/param/linux/param_service.c | 58 +------- services/param/liteos/BUILD.gn | 1 + services/param/manager/param_manager.c | 121 ++++++++-------- services/param/trigger/trigger_processor.c | 97 ++++++------- test/unittest/BUILD.gn | 7 + test/unittest/lite/BUILD.gn | 5 + test/unittest/param/param_unittest.cpp | 26 +++- test/unittest/param/paramservice_unittest.cpp | 45 ++---- 34 files changed, 758 insertions(+), 307 deletions(-) create mode 100755 services/modules/bootchart/BUILD.gn create mode 100755 services/modules/init_hook/BUILD.gn create mode 100755 services/modules/init_hook/init_hook.c create mode 100755 services/modules/init_hook/init_hook.h create mode 100755 services/modules/init_hook/param_hook.c diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn index ce89bb6c..376e7d96 100755 --- a/interfaces/innerkits/BUILD.gn +++ b/interfaces/innerkits/BUILD.gn @@ -63,6 +63,7 @@ if (defined(ohos_lite)) { public_configs = [ ":exported_header_files" ] deps = [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//base/startup/init/services/modules/init_hook:inithook", "//third_party/bounds_checking_function:libsec_shared", "//third_party/mbedtls:mbedtls_shared", ] diff --git a/interfaces/innerkits/hookmgr/hookmgr.c b/interfaces/innerkits/hookmgr/hookmgr.c index 42a89768..fb941d19 100644 --- a/interfaces/innerkits/hookmgr/hookmgr.c +++ b/interfaces/innerkits/hookmgr/hookmgr.c @@ -121,6 +121,7 @@ static int hookItemCompare(ListNode *node, ListNode *newNode) struct HOOKITEM_COMPARE_VAL { int prio; OhosHook hook; + void *hookCookie; }; static int hookItemCompareValue(ListNode *node, void *data) @@ -130,7 +131,9 @@ static int hookItemCompareValue(ListNode *node, void *data) hookItem = (const HOOK_ITEM *)node; BEGET_CHECK(hookItem->info.prio == compareVal->prio, return (hookItem->info.prio - compareVal->prio)); - BEGET_CHECK(hookItem->info.hook != compareVal->hook, return 0); + if (hookItem->info.hook == compareVal->hook && hookItem->info.hookCookie == compareVal->hookCookie) { + return 0; + } return -1; } @@ -143,6 +146,7 @@ static int addHookToStage(HOOK_STAGE *hookStage, int prio, OhosHook hook, void * // Check if exists compareVal.prio = prio; compareVal.hook = hook; + compareVal.hookCookie = hookCookie; hookItem = (HOOK_ITEM *)OH_ListFind(&(hookStage->hooks), (void *)(&compareVal), hookItemCompareValue); BEGET_CHECK(hookItem == NULL, return 0); diff --git a/interfaces/innerkits/init_module_engine/include/bootstage.h b/interfaces/innerkits/init_module_engine/include/bootstage.h index c92a13bd..9d15b97d 100755 --- a/interfaces/innerkits/init_module_engine/include/bootstage.h +++ b/interfaces/innerkits/init_module_engine/include/bootstage.h @@ -32,7 +32,13 @@ enum INIT_BOOTSTAGE { INIT_PRE_CFG_LOAD = 30, INIT_SERVICE_PARSE = 35, INIT_POST_PERSIST_PARAM_LOAD = 40, - INIT_POST_CFG_LOAD = 50 + INIT_POST_CFG_LOAD = 50, + INIT_REBOOT = 55, + INIT_SERVICE_CLEAR = 56, + INIT_SERVICE_DUMP = 57, + INIT_SERVICE_FORK_BEFORE = 58, + INIT_SERVICE_SET_PERMS = 59, + INIT_JOB_PARSE = 70, }; HOOK_MGR *GetBootStageHookMgr(); @@ -75,6 +81,22 @@ typedef struct tagSERVICE_PARSE_CTX { const cJSON *serviceNode; /* Service JSON node */ } SERVICE_PARSE_CTX; +/** + * @brief job config parsing context information + */ +typedef struct tagJOB_PARSE_CTX { + const char *jobName; /* job name */ + const cJSON *jobNode; /* job JSON node */ +} JOB_PARSE_CTX; + +/** + * @brief service info + */ +typedef struct tagSERVICE_INFO_CTX { + const char *serviceName; /* Service name */ + const char *reserved; /* reserved info */ +} SERVICE_INFO_CTX; + /** * @brief service config parse hook function prototype * @@ -83,6 +105,22 @@ typedef struct tagSERVICE_PARSE_CTX { */ typedef void (*ServiceParseHook)(SERVICE_PARSE_CTX *serviceParseCtx); +/** + * @brief job config parse hook function prototype + * + * @param JobParseHook job config parsing context information + * @return None + */ +typedef void (*JobParseHook)(JOB_PARSE_CTX *jobParseCtx); + +/** + * @brief service hook function prototype + * + * @param ServiceHook service info + * @return None + */ +typedef void (*ServiceHook)(SERVICE_INFO_CTX *serviceCtx); + /** * @brief Register a hook for service config parsing * @@ -92,6 +130,50 @@ typedef void (*ServiceParseHook)(SERVICE_PARSE_CTX *serviceParseCtx); */ int InitAddServiceParseHook(ServiceParseHook hook); +/** + * @brief service config parsing context information + */ +typedef struct tagReboot { + char *reason; +} RebootHookCtx; + +/** + * @brief service config parse hook function prototype + * + * @param serviceParseCtx service config parsing context information + * @return None + */ +typedef void (*InitRebootHook)(RebootHookCtx *ctx); +/** + * @brief Register a hook for reboot + * + * @param hook + * + * @return return 0 if succeed; other values if failed. + */ +int InitAddRebootHook(InitRebootHook hook); + +/** + * @brief Register a hook for job config parsing + * + * @param hook job config parsing hook + * in the hook, we can parse extra fields in the config file. + * @return return 0 if succeed; other values if failed. + */ +int InitAddJobParseHook(JobParseHook hook); + +/** + * @brief Register a hook for service + * + * @param hook service hook + * in the hook, we can get service. + * @param hookState init boot state + * @return return 0 if succeed; other values if failed. + */ +int InitAddServiceHook(ServiceHook hook, int hookState); + +int InitAddClearServiceHook(ServiceHook hook); + #ifdef __cplusplus #if __cplusplus } diff --git a/interfaces/innerkits/init_module_engine/include/init_module_engine.h b/interfaces/innerkits/init_module_engine/include/init_module_engine.h index 252beff6..005a1a29 100755 --- a/interfaces/innerkits/init_module_engine/include/init_module_engine.h +++ b/interfaces/innerkits/init_module_engine/include/init_module_engine.h @@ -42,6 +42,7 @@ int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd); void RemoveCmdExecutor(const char *cmdName, int id); +int DoJobNow(const char *jobName); #ifdef __cplusplus #if __cplusplus } diff --git a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json index 624200b8..40df4039 100755 --- a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json +++ b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json @@ -13,5 +13,7 @@ { "name": "InitAddPostCfgLoadHook" }, { "name": "InitModuleMgrInstall" }, { "name": "InitModuleMgrUnInstall" }, - { "name": "StartupLog" } + { "name": "StartupLog" }, + { "name": "DoJobNow" }, + { "name": "GetServiceExtData" } ] diff --git a/services/begetctl/param_cmd.c b/services/begetctl/param_cmd.c index df64a621..a6bc4027 100644 --- a/services/begetctl/param_cmd.c +++ b/services/begetctl/param_cmd.c @@ -359,7 +359,6 @@ static int32_t BShellParamCmdDump(BShellHandle shell, int32_t argc, char *argv[] { BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); if (argc >= 2 && strcmp(argv[1], "verbose") == 0) { // 2 min arg - SystemSetParameter("ohos.servicectrl.display", "system"); SystemDumpParameters(1); } else { SystemDumpParameters(0); diff --git a/services/init/include/init_service.h b/services/init/include/init_service.h index a0653708..d75bc7b1 100644 --- a/services/init/include/init_service.h +++ b/services/init/include/init_service.h @@ -155,8 +155,11 @@ typedef struct Service_ { TimerHandle timer; ServiceJobs serviceJobs; cpu_set_t cpuSet; + struct ListNode extDataNode; } Service; +Service *GetServiceByPid(pid_t pid); +Service *GetServiceByName(const char *servName); int ServiceStart(Service *service); int ServiceStop(Service *service); void ServiceReap(Service *service); diff --git a/services/init/include/init_service_manager.h b/services/init/include/init_service_manager.h index c5131c75..376405bf 100644 --- a/services/init/include/init_service_manager.h +++ b/services/init/include/init_service_manager.h @@ -49,8 +49,6 @@ typedef struct { int serviceCount; } ServiceSpace; -Service *GetServiceByPid(pid_t pid); -Service *GetServiceByName(const char *servName); cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName); int ParseOneService(const cJSON *curItem, Service *service); diff --git a/services/init/init_common_service.c b/services/init/init_common_service.c index d1109c47..0806cf11 100644 --- a/services/init/init_common_service.c +++ b/services/init/init_common_service.c @@ -43,6 +43,11 @@ #include "securec.h" #include "service_control.h" +#ifndef OHOS_LITE +#include "hookmgr.h" +#include "bootstage.h" +#endif + #ifdef WITH_SELINUX #include "init_selinux_param.h" #include @@ -82,6 +87,45 @@ static int SetSystemSeccompPolicy(const Service *service) } #endif +#ifndef OHOS_LITE +/** + * service Hooking + */ +static int ServiceHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) +{ + SERVICE_INFO_CTX *serviceContext = (SERVICE_INFO_CTX *)executionContext; + ServiceHook realHook = (ServiceHook)hookInfo->hookCookie; + + realHook(serviceContext); + return 0; +}; + +int InitAddServiceHook(ServiceHook hook, int hookState) +{ + HOOK_INFO info; + + info.stage = hookState; + info.prio = 0; + info.hook = ServiceHookWrapper; + info.hookCookie = (void *)hook; + + return HookMgrAddEx(GetBootStageHookMgr(), &info); +} + +/** + * service hooking execute + */ +static void ServiceHookExecute(const char *serviceName, const char *info, int stage) +{ + SERVICE_INFO_CTX context; + + context.serviceName = serviceName; + context.reserved = info; + + (void)HookMgrExecute(GetBootStageHookMgr(), stage, (void *)(&context), NULL); +} +#endif + static int SetPerms(const Service *service) { INIT_CHECK_RETURN_VALUE(KeepCapability() == 0, SERVICE_FAILURE); @@ -134,6 +178,12 @@ static int SetPerms(const Service *service) INIT_ERROR_CHECK(SetAmbientCapability(service->servPerm.caps[i]) == 0, return SERVICE_FAILURE, "SetAmbientCapability failed for service: %s", service->name); } +#ifndef OHOS_LITE + /* + * service set Perms hooks + */ + ServiceHookExecute(service->name, NULL, INIT_SERVICE_SET_PERMS); +#endif return SERVICE_SUCCESS; } @@ -344,6 +394,12 @@ int ServiceStart(Service *service) INIT_LOGE("start service %s invalid, please check %s.", service->name, service->pathArgs.argv[0]); return SERVICE_FAILURE; } +#ifndef OHOS_LITE + /* + * before service fork hooks + */ + ServiceHookExecute(service->name, NULL, INIT_SERVICE_FORK_BEFORE); +#endif int pid = fork(); if (pid == 0) { // fail must exit sub process @@ -388,6 +444,7 @@ int ServiceStop(Service *service) NotifyServiceChange(service, SERVICE_STOPPING); INIT_LOGI("stop service %s, pid %d.", service->name, service->pid); service->pid = -1; + NotifyServiceChange(service, SERVICE_STOPPED); return SERVICE_SUCCESS; } diff --git a/services/init/init_service_manager.c b/services/init/init_service_manager.c index ebb1f82c..a315af2f 100755 --- a/services/init/init_service_manager.c +++ b/services/init/init_service_manager.c @@ -91,6 +91,18 @@ static void DumpServiceSocket(const Service *service) } } +#ifndef OHOS_LITE +static void DumpServiceHookExecute(const char *name, const char *info) +{ + SERVICE_INFO_CTX context; + + context.serviceName = name; + context.reserved = info; + + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&context), NULL); +} +#endif + void DumpOneService(const Service *service) { const InitArgInfo startModeMap[] = { @@ -130,6 +142,12 @@ void DumpOneService(const Service *service) for (int i = 0; i < (int)service->servPerm.capsCnt; i++) { printf("\t\tservice perms capability %u \n", service->servPerm.caps[i]); } +#ifndef OHOS_LITE + /* + * dump service hooks + */ + DumpServiceHookExecute(service->name, NULL); +#endif } void DumpAllServices(void) @@ -197,6 +215,7 @@ Service *AddService(const char *name) service->name = node->name; service->status = SERVICE_IDLE; CPU_ZERO(&service->cpuSet); + OH_ListInit(&service->extDataNode); g_serviceSpace.serviceCount++; INIT_LOGV("AddService %s", node->name); return service; diff --git a/services/init/lite/BUILD.gn b/services/init/lite/BUILD.gn index 7b5a7159..9f0d0216 100644 --- a/services/init/lite/BUILD.gn +++ b/services/init/lite/BUILD.gn @@ -60,6 +60,7 @@ executable("init") { "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", "//base/startup/init/services/log:init_log", "//base/startup/init/services/loopevent:loopevent", + "//base/startup/init/services/modules/init_hook:inithook", "//base/startup/init/services/param/base:parameterbase", "//base/startup/init/services/utils:libinit_utils", "//build/lite/config/component/cJSON:cjson_static", diff --git a/services/init/standard/init.c b/services/init/standard/init.c index 53beec87..20e34c47 100755 --- a/services/init/standard/init.c +++ b/services/init/standard/init.c @@ -274,24 +274,10 @@ static void BootStateChange(const char *content) } if (strcmp("post-init", content) == 0) { StartAllServices(START_MODE_NORMAL); - // Destroy all hooks - HookMgrDestroy(bootStageHookMgr); - bootStageHookMgr = NULL; return; } } -#if defined(OHOS_SERVICE_DUMP) -static int SystemDump(int id, const char *name, int argc, const char **argv) -{ - INIT_ERROR_CHECK(argv != NULL && argc >= 1, return 0, "Invalid install parameter"); - INIT_LOGI("Dump system info %s", argv[0]); - SystemDumpParameters(1); - SystemDumpTriggers(1); - return 0; -} -#endif - static void IsEnableSandbox(void) { const char *name = "const.sandbox"; @@ -390,11 +376,6 @@ void SystemConfig(void) INIT_LOGI("Parse init config file done."); HookMgrExecute(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, (void *)&timingStat, (void *)&options); - // dump config -#if defined(OHOS_SERVICE_DUMP) - AddCmdExecutor("display", SystemDump); - (void)AddCompleteJob("param:ohos.servicectrl.display", "ohos.servicectrl.display=*", "display system"); -#endif IsEnableSandbox(); // execute init PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init")); diff --git a/services/modules/BUILD.gn b/services/modules/BUILD.gn index 485a287b..d2772834 100755 --- a/services/modules/BUILD.gn +++ b/services/modules/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020-2021 Huawei Device Co., Ltd. +# Copyright (c) 2020-2022 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -11,56 +11,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -if (!defined(ohos_lite)) { - import("//base/startup/init/begetd.gni") - import("//build/ohos.gni") - - ohos_shared_library("bootchart") { - sources = [ "bootchart/bootchart.c" ] - - include_dirs = [ - ".", - "//base/startup/init/services/include/param", - ] - - deps = [ - "//base/startup/init/interfaces/innerkits:libbegetutil", - "//third_party/bounds_checking_function:libsec_shared", - "//third_party/cJSON:cjson_static", - ] - - external_deps = [ "init:libinit_module_engine" ] - - part_name = "init" - if (target_cpu == "arm64") { - module_install_dir = "lib64/init" - } else { - module_install_dir = "lib/init" - } - } - - config("libbootchart_static_config") { - include_dirs = [ "." ] - } - - ohos_source_set("libbootchart_static") { - sources = [ "bootchart/bootchart_static.c" ] - public_configs = [ ":libbootchart_static_config" ] - public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] - } -} - group("static_modules") { if (!defined(ohos_lite)) { deps = [ - ":libbootchart_static", + "bootchart:libbootchart_static", "bootevent:libbootevent_static", + "init_hook:inithook", ] } } group("modulesgroup") { if (!defined(ohos_lite)) { - deps = [ ":bootchart" ] + deps = [ "bootchart:bootchart" ] } } diff --git a/services/modules/bootchart/BUILD.gn b/services/modules/bootchart/BUILD.gn new file mode 100755 index 00000000..5abae303 --- /dev/null +++ b/services/modules/bootchart/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//base/startup/init/begetd.gni") +import("//build/ohos.gni") + +ohos_shared_library("bootchart") { + sources = [ "bootchart.c" ] + + include_dirs = [ + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/bootchart", + "//base/startup/init/services/include/param", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//third_party/bounds_checking_function:libsec_shared", + "//third_party/cJSON:cjson_static", + ] + + external_deps = [ "init:libinit_module_engine" ] + + part_name = "init" + if (target_cpu == "arm64") { + module_install_dir = "lib64/init" + } else { + module_install_dir = "lib/init" + } +} + +config("libbootchart_static_config") { + include_dirs = [ + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/bootchart", + ] +} + +ohos_source_set("libbootchart_static") { + sources = [ "bootchart_static.c" ] + public_configs = [ ":libbootchart_static_config" ] + public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] +} diff --git a/services/modules/bootevent/BUILD.gn b/services/modules/bootevent/BUILD.gn index 631b0315..d7f4dd76 100755 --- a/services/modules/bootevent/BUILD.gn +++ b/services/modules/bootevent/BUILD.gn @@ -24,6 +24,7 @@ config("bootevent_static_config") { ohos_source_set("libbootevent_static") { sources = [ "bootevent.c" ] + include_dirs = [ ".." ] public_configs = [ ":bootevent_static_config" ] public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] } diff --git a/services/modules/bootevent/bootevent.c b/services/modules/bootevent/bootevent.c index f8f4627b..19bbd6a0 100755 --- a/services/modules/bootevent/bootevent.c +++ b/services/modules/bootevent/bootevent.c @@ -17,10 +17,11 @@ #include "init_module_engine.h" #include "trigger_manager.h" #include "init_log.h" +#include "plugin_adapter.h" #define BOOT_EVENT_PARA_PREFIX "bootevent." #define BOOT_EVENT_PARA_PREFIX_LEN 10 - +#ifdef BOOTEVENT typedef struct tagBOOT_EVENT_PARAM_ITEM { ListNode node; const char *paramName; @@ -132,44 +133,40 @@ static void BootEventParaFireByName(const char *paramName) #define BOOT_EVENT_FIELD_NAME "bootevents" +#endif + static void ServiceParseBootEventHook(SERVICE_PARSE_CTX *serviceParseCtx) { - int cnt; - cJSON *bootEvents = cJSON_GetObjectItem(serviceParseCtx->serviceNode, BOOT_EVENT_FIELD_NAME); - - // No bootevents in config file - if (bootEvents == NULL) { - return; - } + PLUGIN_LOGI("ServiceParseBootEventHook %s", serviceParseCtx->serviceName); +} - // Single bootevent in config file - if (!cJSON_IsArray(bootEvents)) { - BootEventParaAdd(cJSON_GetStringValue(bootEvents)); - return; - } +static int DoBootEventCmd(int id, const char *name, int argc, const char **argv) +{ + PLUGIN_LOGI("DoBootEventCmd argc %d %s", argc, name); + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + // argv[0] samgr.ready.true + PLUGIN_LOGI("DoBootEventCmd argv %s", argv[0]); + return 0; +} - // Multiple bootevents in config file - cnt = cJSON_GetArraySize(bootEvents); - for (int i = 0; i < cnt; i++) { - cJSON *item = cJSON_GetArrayItem(bootEvents, i); - BootEventParaAdd(cJSON_GetStringValue(item)); - } +void ClearServiceBootEventHook(SERVICE_INFO_CTX *serviceCtx) +{ + PLUGIN_LOGI("ClearServiceBootEventHook serviceName %s", serviceCtx->serviceName); } -static void ParamSetBootEventHook(PARAM_SET_CTX *paramSetCtx) +static int32_t g_executorId = -1; +static int ParamSetBootEventHook(const HOOK_INFO *hookInfo, void *cookie) { - // Check if the parameter is started with "bootevent." - if (strncmp(paramSetCtx->name, BOOT_EVENT_PARA_PREFIX, BOOT_EVENT_PARA_PREFIX_LEN) != 0) { - return; + if (g_executorId == -1) { + g_executorId = AddCmdExecutor("bootevent", DoBootEventCmd); + PLUGIN_LOGI("DoBootEventCmd executorId %d", g_executorId); } - - // Delete the bootevent param for list - BootEventParaFireByName(paramSetCtx->name); + return 0; } MODULE_CONSTRUCTOR(void) { InitAddServiceParseHook(ServiceParseBootEventHook); - - ParamSetHookAdd(ParamSetBootEventHook); + InitAddGlobalInitHook(0, ParamSetBootEventHook); + InitAddClearServiceHook(ClearServiceBootEventHook); } diff --git a/services/modules/init_hook/BUILD.gn b/services/modules/init_hook/BUILD.gn new file mode 100755 index 00000000..002c92c4 --- /dev/null +++ b/services/modules/init_hook/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +config("inithook_config") { + include_dirs = [ "//base/startup/init/services/modules/init_hook" ] +} +comm_include = [ + "//base/startup/init/services/include", + "//base/startup/init/services/include/param", + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/init/include", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", + "//third_party/cJSON", + "//third_party/bounds_checking_function/include", +] +if (defined(ohos_lite)) { + static_library("inithook") { + defines = [ "_GNU_SOURCE" ] + include_dirs = comm_include + sources = [ "param_hook.c" ] + public_configs = [ ":inithook_config" ] + } +} else { + ohos_source_set("inithook") { + defines = [ "_GNU_SOURCE" ] + include_dirs = comm_include + sources = [ + "init_hook.c", + "param_hook.c", + ] + if (build_selinux) { + include_dirs += [ + "//third_party/selinux/libselinux/include/", + "//base/security/selinux/interfaces/policycoreutils/include/", + ] + defines += [ "WITH_SELINUX" ] + } + public_configs = [ ":inithook_config" ] + public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] + } +} diff --git a/services/modules/init_hook/init_hook.c b/services/modules/init_hook/init_hook.c new file mode 100755 index 00000000..71d0069e --- /dev/null +++ b/services/modules/init_hook/init_hook.c @@ -0,0 +1,135 @@ + +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "init_hook.h" +#include "init_service.h" +#include "init_utils.h" +#include "plugin_adapter.h" +#include "securec.h" +#include "init_module_engine.h" +#include "init_group_manager.h" +#include "hookmgr.h" +#include "bootstage.h" + +static int ServiceExtDataCompareProc(ListNode *node, void *data) +{ + ServiceExtData *item = ListEntry(node, ServiceExtData, node); + if (item->dataId == *(uint32_t *)data) { + return 0; + } + return -1; +} + +static ServiceExtData *GetServiceExtData_(Service *service, uint32_t id) +{ + ListNode *node = OH_ListFind(&service->extDataNode, (void *)&id, ServiceExtDataCompareProc); + return (ServiceExtData *)node; +} + +ServiceExtData *AddServiceExtData(const char *serviceName, uint32_t id, void *data, uint32_t dataLen) +{ + Service *service = GetServiceByName(serviceName); + PLUGIN_CHECK(service != NULL, return NULL, "Can not find service for %s", serviceName); + ServiceExtData *extData = GetServiceExtData_(service, id); + if (extData != NULL) { + return NULL; + } + extData = calloc(1, sizeof(ServiceExtData) + dataLen); + PLUGIN_CHECK(extData != NULL, return NULL, "Can not alloc extData for %d", id); + OH_ListInit(&extData->node); + extData->dataId = id; + if (data != NULL) { + int ret = memcpy_s(extData->data, dataLen, data, dataLen); + if (ret == 0) { + OH_ListAddTail(&service->extDataNode, &extData->node); + return extData; + } + } else { + OH_ListAddTail(&service->extDataNode, &extData->node); + return extData; + } + free(extData); + return NULL; +} + +void DelServiceExtData(const char *serviceName, uint32_t id) +{ + Service *service = GetServiceByName(serviceName); + PLUGIN_CHECK(service != NULL, return, "Can not find service for %s", serviceName); + ServiceExtData *extData = GetServiceExtData_(service, id); + if (extData == NULL) { + return; + } + OH_ListRemove(&extData->node); + free(extData); +} + +ServiceExtData *GetServiceExtData(const char *serviceName, uint32_t id) +{ + Service *service = GetServiceByName(serviceName); + PLUGIN_CHECK (service != NULL, return NULL, "Can not find service for %s", serviceName); + return GetServiceExtData_(service, id); +} + +static int ServiceClearHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) +{ + SERVICE_INFO_CTX *ctx = (SERVICE_INFO_CTX *)executionContext; + ServiceHook realHook = (ServiceHook)hookInfo->hookCookie; + realHook(ctx); + INIT_LOGI("ServiceClearHookWrapper realHook %p", realHook); + return 0; +}; + +int InitAddClearServiceHook(ServiceHook hook) +{ + HOOK_INFO info; + info.stage = INIT_SERVICE_CLEAR; + info.prio = 0; + info.hook = ServiceClearHookWrapper; + info.hookCookie = (void *)hook; + PLUGIN_LOGI("InitAddClearServiceHook hook %p info.stage %d %p", hook, info.stage, GetBootStageHookMgr()); + return HookMgrAddEx(GetBootStageHookMgr(), &info); +} + +static int CmdClear_(int id, const char *name, int argc, const char **argv) +{ + SERVICE_INFO_CTX ctx = {0}; + ctx.reserved = argc >= 1 ? argv[0] : NULL; + PLUGIN_LOGI("CmdClear_ %s cmd: %s", name, ctx.reserved); + + InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL); + while (node != NULL) { + if (node->data.service == NULL) { + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + ctx.serviceName = node->name; + HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_CLEAR, (void *)&ctx, NULL); + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + } + return 0; +} + +static int ParamSetBootEventHook(const HOOK_INFO *hookInfo, void *cookie) +{ + AddCmdExecutor("clear", CmdClear_); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + InitAddGlobalInitHook(0, ParamSetBootEventHook); +} diff --git a/services/modules/init_hook/init_hook.h b/services/modules/init_hook/init_hook.h new file mode 100755 index 00000000..bc9a55c0 --- /dev/null +++ b/services/modules/init_hook/init_hook.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STARTUP_INIT_PARAM_HOOK_ +#define STARTUP_INIT_PARAM_HOOK_ +#include +#include + +#include "list.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define SERVICE_CTL_CMD_INDEX 2 +typedef struct { + const char *name; + const char *replace; + const char *cmd; +} ParamCmdInfo; + +const ParamCmdInfo *GetServiceStartCtrl(size_t *size); +const ParamCmdInfo *GetServiceCtl(size_t *size); +const ParamCmdInfo *GetStartupPowerCtl(size_t *size); +const ParamCmdInfo *GetOtherSpecial(size_t *size); + +typedef struct { + struct ListNode node; + uint32_t dataId; + uint8_t data[]; +} ServiceExtData; + +ServiceExtData *AddServiceExtData(const char *serviceName, uint32_t id, void *data, uint32_t dataLen); +void DelServiceExtData(const char *serviceName, uint32_t id); +ServiceExtData *GetServiceExtData(const char *serviceName, uint32_t id); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/services/modules/init_hook/param_hook.c b/services/modules/init_hook/param_hook.c new file mode 100755 index 00000000..25b900ff --- /dev/null +++ b/services/modules/init_hook/param_hook.c @@ -0,0 +1,65 @@ + +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "init_hook.h" +#include "init_service.h" +#include "init_utils.h" +#include "plugin_adapter.h" +#include "securec.h" + +const ParamCmdInfo *GetServiceStartCtrl(size_t *size) +{ + static const ParamCmdInfo ctrlParam[] = { + {"ohos.ctl.start", "start", "start "}, + {"ohos.ctl.stop", "stop", "stop "}, + }; + *size = ARRAY_LENGTH(ctrlParam); + return ctrlParam; +} + +const ParamCmdInfo *GetServiceCtl(size_t *size) +{ + static const ParamCmdInfo installParam[] = { + {"ohos.servicectrl.install", "install", "install" }, + {"ohos.servicectrl.uninstall", "uninstall", "uninstall" }, + {"ohos.servicectrl.clear", "clear", "clear" } + }; + *size = ARRAY_LENGTH(installParam); + return installParam; +} + +const ParamCmdInfo *GetStartupPowerCtl(size_t *size) +{ + static const ParamCmdInfo powerCtrlArg[] = { + {"reboot,shutdown", "reboot.shutdown", "reboot "}, + {"reboot,updater", "reboot.updater", "reboot "}, + {"reboot,flashd", "reboot.flashd", "reboot "}, + {"reboot,loader", "reboot.loader", "reboot "}, + {"reboot,charge", "reboot.charge", "reboot "}, + {"reboot", "reboot", "reboot "}, + }; + *size = ARRAY_LENGTH(powerCtrlArg); + return powerCtrlArg; +} + +const ParamCmdInfo *GetOtherSpecial(size_t *size) +{ + static const ParamCmdInfo other[] = { + {"bootevent.", "bootevent.", "bootevent"}, + }; + *size = ARRAY_LENGTH(other); + return other; +} diff --git a/services/modules/plugin_adapter.h b/services/modules/plugin_adapter.h index 73e87421..c00af691 100755 --- a/services/modules/plugin_adapter.h +++ b/services/modules/plugin_adapter.h @@ -21,6 +21,12 @@ #include "init_log.h" +#define PROCESS_EXIT_CODE 0x7f // 0x7f: user specified + +#ifndef UNUSED +#define UNUSED(x) (void)(x) +#endif + #ifndef PLUGIN_DOMAIN #define PLUGIN_DOMAIN (BASE_DOMAIN + 6) #endif @@ -39,4 +45,10 @@ if (!(ret)) { \ exper; \ } + +#define HOOKID(name) HOOK_ID_##name +enum HOOK_ID_ { + HOOKID(BOOTCHART), + HOOKID(SELINUX), +}; #endif diff --git a/services/param/base/param_trie.c b/services/param/base/param_trie.c index feca2b7f..390d9f0d 100644 --- a/services/param/base/param_trie.c +++ b/services/param/base/param_trie.c @@ -43,8 +43,7 @@ static int InitWorkSpace_(WorkSpace *workSpace, uint32_t spaceSize, int readOnly int ret = GetRealFileName(workSpace, buffer, sizeof(buffer)); PARAM_CHECK(ret == 0, return -1, "Failed to get file name %s", workSpace->fileName); void *areaAddr = GetSharedMem(buffer, &workSpace->memHandle, spaceSize, readOnly); - PARAM_CHECK(areaAddr != NULL, return PARAM_CODE_ERROR_MAP_FILE, - "Failed to map memory error %d spaceSize %d", errno, spaceSize); + PARAM_ONLY_CHECK(areaAddr != NULL, return PARAM_CODE_ERROR_MAP_FILE); if (!readOnly) { workSpace->area = (ParamTrieHeader *)areaAddr; ATOMIC_INIT(&workSpace->area->commitId, 0); @@ -108,7 +107,7 @@ INIT_LOCAL_API int InitWorkSpace(WorkSpace *workSpace, int onlyRead, uint32_t sp workSpace->allocTrieNode = AllocateParamTrieNode; workSpace->area = NULL; int ret = InitWorkSpace_(workSpace, spaceSize, onlyRead); - PARAM_CHECK(ret == 0, return ret, "Failed to init workspace %s", workSpace->fileName); + PARAM_ONLY_CHECK(ret == 0, return ret); PARAMSPACE_AREA_INIT_LOCK(workSpace); PARAM_SET_FLAG(workSpace->flags, WORKSPACE_FLAGS_INIT); PARAM_LOGV("InitWorkSpace %s for %s", workSpace->fileName, (onlyRead == 0) ? "init" : "other"); diff --git a/services/param/include/param_manager.h b/services/param/include/param_manager.h index 15310bfe..88083c42 100644 --- a/services/param/include/param_manager.h +++ b/services/param/include/param_manager.h @@ -34,8 +34,12 @@ extern "C" { #endif #define WORKSPACE_NAME_DAC "param_sec_dac" -#define WORKSPACE_NAME_NORMAL "param_storage" #define WORKSPACE_NAME_DEF_SELINUX "u:object_r:default_param:s0" +#ifndef PARAM_SUPPORT_SELINUX +#define WORKSPACE_NAME_NORMAL "param_storage" +#else +#define WORKSPACE_NAME_NORMAL WORKSPACE_NAME_DEF_SELINUX +#endif #define PARAM_NEED_CHECK_IN_SERVICE 0x2 #define PARAM_CTRL_SERVICE 0x1 @@ -71,6 +75,13 @@ typedef struct { PersistParamOps persistParamOps; } ParamPersistWorkSpace; +typedef struct { + char realKey[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 1]; + char cmdName[32]; + uint32_t valueOffset; + uint8_t ctrlParam; +} ServiceCtrlInfo; + typedef void (*TraversalParamPtr)(ParamHandle handle, void *context); typedef struct { TraversalParamPtr traversalParamPtr; @@ -99,7 +110,7 @@ INIT_LOCAL_API int InitPersistParamWorkSpace(void); INIT_LOCAL_API void ClosePersistParamWorkSpace(void); INIT_LOCAL_API int WritePersistParam(const char *name, const char *value); -INIT_INNER_API int CheckParameterSet(const char *name, const char *value, +INIT_LOCAL_API int CheckParameterSet(const char *name, const char *value, const ParamSecurityLabel *srcLabel, int *ctrlService); INIT_INNER_API ParamHandle GetParamHandle(const WorkSpace *workSpace, uint32_t index, const char *name); INIT_INNER_API int CheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode); @@ -110,6 +121,8 @@ INIT_INNER_API ParamWorkSpace *GetParamWorkSpace(void); INIT_INNER_API int GetParamSecurityAuditData(const char *name, int type, ParamAuditData *auditData); INIT_INNER_API int SysCheckParamExist(const char *name); +INIT_LOCAL_API int GetServiceCtrlInfo(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo); + #ifdef STARTUP_INIT_TEST ParamService *GetParamService(); #endif diff --git a/services/param/include/param_osadp.h b/services/param/include/param_osadp.h index 74fe175a..52943214 100755 --- a/services/param/include/param_osadp.h +++ b/services/param/include/param_osadp.h @@ -44,6 +44,7 @@ extern "C" { #endif #endif +#define PARAM_WORKSPACE_MIN (1024) #if (defined __LITEOS_A__ || defined __LITEOS_M__) #define DAC_DEFAULT_MODE 0777 #ifdef STARTUP_INIT_TEST diff --git a/services/param/linux/BUILD.gn b/services/param/linux/BUILD.gn index 17574368..ed62ba8c 100755 --- a/services/param/linux/BUILD.gn +++ b/services/param/linux/BUILD.gn @@ -31,6 +31,7 @@ param_include_dirs = [ "//base/startup/init/services/include", "//base/startup/init/services/init/include", "//base/startup/init/services/log", + "//base/startup/init/services/modules/init_hook", "//base/startup/init/interfaces/innerkits/init_module_engine/include", "//base/startup/init/services/loopevent/include", "//third_party/bounds_checking_function/include", diff --git a/services/param/linux/param_request.c b/services/param/linux/param_request.c index f97aca37..ad08dafe 100644 --- a/services/param/linux/param_request.c +++ b/services/param/linux/param_request.c @@ -135,9 +135,10 @@ static int StartRequest(int clientFd, ParamMessage *request, int timeout) int SystemSetParameter(const char *name, const char *value) { PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid name or value"); - int ctrlService = 0; - int ret = CheckParameterSet(name, value, GetParamSecurityLabel(), &ctrlService); - PARAM_CHECK(ret == 0, return ret, "Forbid to set parameter %s", name); + int ret = CheckParamName(name, 0); + PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name); + ret = CheckParamValue(NULL, name, value, GetParamValueType(name)); + PARAM_CHECK(ret == 0, return ret, "Illegal param value %s", value); size_t msgSize = sizeof(ParamMsgContent); msgSize = (msgSize < RECV_BUFFER_MAX) ? RECV_BUFFER_MAX : msgSize; diff --git a/services/param/linux/param_service.c b/services/param/linux/param_service.c index 5e99a909..57944071 100755 --- a/services/param/linux/param_service.c +++ b/services/param/linux/param_service.c @@ -25,10 +25,6 @@ #include "param_message.h" #include "trigger_manager.h" #include "securec.h" -#ifndef OHOS_LITE -#include "hookmgr.h" -#include "init_running_hooks.h" -#endif static ParamService g_paramService = {}; @@ -135,45 +131,6 @@ static int SendWatcherNotifyMessage(const TriggerExtInfo *extData, const char *c return 0; } -#ifndef OHOS_LITE -/** - * Parameter Set Hooking - */ -static int ParamSetHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) -{ - PARAM_SET_CTX *paramSetContext = (PARAM_SET_CTX *)executionContext; - ParamSetHook realHook = (ParamSetHook)hookInfo->hookCookie; - - realHook(paramSetContext); - return 0; -}; - -int ParamSetHookAdd(ParamSetHook hook) -{ - HOOK_INFO info; - - info.stage = INIT_PARAM_SET_HOOK_STAGE; - info.prio = 0; - info.hook = ParamSetHookWrapper; - info.hookCookie = (void *)hook; - - return HookMgrAddEx(NULL, &info); -} - -static int ParamSetHookExecute(const char *name, const char *value) -{ - PARAM_SET_CTX context; - - context.name = name; - context.value = value; - context.skipParamSet = 0; - - (void)HookMgrExecute(NULL, INIT_PARAM_SET_HOOK_STAGE, (void *)(&context), NULL); - - return context.skipParamSet; -} -#endif - static int SystemSetParam(const char *name, const char *value, const ParamSecurityLabel *srcLabel) { PARAM_LOGV("SystemWriteParam name %s value: %s", name, value); @@ -181,20 +138,7 @@ static int SystemSetParam(const char *name, const char *value, const ParamSecuri int ret = CheckParameterSet(name, value, srcLabel, &ctrlService); PARAM_CHECK(ret == 0, return ret, "Forbid to set parameter %s", name); -#ifndef OHOS_LITE - /* - * Execute param set hooks before setting parameter values - */ - if (ParamSetHookExecute(name, value)) { - // Hook has processed the parameter set request - PARAM_LOGI("param [%s] set in the hook.", name); - return 0; - } -#endif - - if (ctrlService & PARAM_CTRL_SERVICE) { // ctrl param - PostParamTrigger(EVENT_TRIGGER_PARAM, name, value); - } else { + if ((ctrlService & PARAM_CTRL_SERVICE) != PARAM_CTRL_SERVICE) { // ctrl param uint32_t dataIndex = 0; ret = WriteParam(name, value, &dataIndex, 0); PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value); diff --git a/services/param/liteos/BUILD.gn b/services/param/liteos/BUILD.gn index ccea8c34..f13825f3 100644 --- a/services/param/liteos/BUILD.gn +++ b/services/param/liteos/BUILD.gn @@ -14,6 +14,7 @@ import("//base/startup/init/begetd.gni") param_include_dirs = [ "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/services/modules/init_hook", "//base/startup/init/services/param/include", "//base/startup/init/services/param/adapter", "//base/startup/init/services/include/param", diff --git a/services/param/manager/param_manager.c b/services/param/manager/param_manager.c index f342863d..913ee775 100644 --- a/services/param/manager/param_manager.c +++ b/services/param/manager/param_manager.c @@ -18,9 +18,11 @@ #include #include +#include "init_cmds.h" +#include "init_hook.h" #include "param_trie.h" -#include "securec.h" #include "param_utils.h" +#include "securec.h" ParamNode *SystemCheckMatchParamWait(const char *name, const char *value) { @@ -238,66 +240,70 @@ INIT_INNER_API int GetParamSecurityAuditData(const char *name, int type, ParamAu return 0; } -static char *BuildKey(const char *format, ...) +static int CreateCtrlInfo(ServiceCtrlInfo **ctrlInfo, const char *cmd, uint32_t offset, + uint8_t ctrlParam, const char *format, ...) { - const size_t buffSize = 1024; // 1024 for format key - char *buffer = malloc(buffSize); - PARAM_CHECK(buffer != NULL, return NULL, "Failed to malloc for format"); + *ctrlInfo = calloc(1, sizeof(ServiceCtrlInfo)); + PARAM_CHECK(ctrlInfo != NULL, return -1, "Failed to alloc memory %s", cmd); va_list vargs; va_start(vargs, format); - int len = vsnprintf_s(buffer, buffSize, buffSize - 1, format, vargs); + int len = vsnprintf_s((*ctrlInfo)->realKey, + sizeof((*ctrlInfo)->realKey), sizeof((*ctrlInfo)->realKey) - 1, format, vargs); va_end(vargs); - if (len > 0 && (size_t)len < buffSize) { - buffer[len] = '\0'; - for (int i = 0; i < len; i++) { - if (buffer[i] == '|') { - buffer[i] = '\0'; - } - } - return buffer; + int ret = strcpy_s((*ctrlInfo)->cmdName, sizeof((*ctrlInfo)->cmdName), cmd); + (*ctrlInfo)->valueOffset = offset; + if (ret != 0 || len <= 0) { + free(*ctrlInfo); + return -1; } - return NULL; + (*ctrlInfo)->ctrlParam = ctrlParam; + return 0; } -PARAM_STATIC char *GetServiceCtrlName(const char *name, const char *value) +INIT_LOCAL_API int GetServiceCtrlInfo(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo) { - static char *ctrlParam[] = { - "ohos.ctl.start", - "ohos.ctl.stop" - }; - static char *installParam[] = { - "ohos.servicectrl." - }; - static char *powerCtrlArg[][2] = { - {"reboot,shutdown", "reboot.shutdown"}, - {"reboot,updater", "reboot.updater"}, - {"reboot,flashd", "reboot.flashd"}, - {"reboot", "reboot"}, - }; - char *key = NULL; + PARAM_CHECK(ctrlInfo != NULL, return -1, "Invalid ctrlInfo %s", name); + *ctrlInfo = NULL; + size_t size = 0; if (strcmp("ohos.startup.powerctrl", name) == 0) { - for (size_t i = 0; i < ARRAY_LENGTH(powerCtrlArg); i++) { - if (strncmp(value, powerCtrlArg[i][0], strlen(powerCtrlArg[i][0])) == 0) { - return BuildKey("%s%s", OHOS_SERVICE_CTRL_PREFIX, powerCtrlArg[i][1]); + const ParamCmdInfo *powerCtrlArg = GetStartupPowerCtl(&size); + for (size_t i = 0; i < size; i++) { + if (strncmp(value, powerCtrlArg[i].name, strlen(powerCtrlArg[i].name)) == 0) { + uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(powerCtrlArg[i].replace) + 1; + return CreateCtrlInfo(ctrlInfo, powerCtrlArg[i].cmd, valueOffset, 1, + "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, powerCtrlArg[i].replace, value); } } - return key; + return 0; } - for (size_t i = 0; i < ARRAY_LENGTH(ctrlParam); i++) { - if (strcmp(name, ctrlParam[i]) == 0) { - return BuildKey("%s%s", OHOS_SERVICE_CTRL_PREFIX, value); + if (strncmp("ohos.ctl.", name, strlen("ohos.ctl.")) == 0) { + const ParamCmdInfo *ctrlParam = GetServiceStartCtrl(&size); + for (size_t i = 0; i < size; i++) { + if (strcmp(name, ctrlParam[i].name) == 0) { + uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(ctrlParam[i].replace) + 1; + return CreateCtrlInfo(ctrlInfo, ctrlParam[i].cmd, valueOffset, 1, + "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, ctrlParam[i].replace, value); + } } } - - for (size_t i = 0; i < ARRAY_LENGTH(installParam); i++) { - if (strncmp(name, installParam[i], strlen(installParam[i])) == 0) { - return BuildKey("%s.%s", name, value); + if (strncmp("ohos.servicectrl.", name, strlen("ohos.servicectrl.")) == 0) { + const ParamCmdInfo *installParam = GetServiceCtl(&size); + for (size_t i = 0; i < size; i++) { + if (strncmp(name, installParam[i].name, strlen(installParam[i].name)) == 0) { + return CreateCtrlInfo(ctrlInfo, installParam[i].cmd, strlen(name) + 1, 1, "%s.%s", name, value); + } + } + } + const ParamCmdInfo *other = GetOtherSpecial(&size); + for (size_t i = 0; i < size; i++) { + if (strncmp(name, other[i].name, strlen(other[i].name)) == 0) { + return CreateCtrlInfo(ctrlInfo, other[i].cmd, strlen(other[i].name), 0, "%s.%s", name, value); } } - return key; + return 0; } -INIT_INNER_API int CheckParameterSet(const char *name, +INIT_LOCAL_API int CheckParameterSet(const char *name, const char *value, const ParamSecurityLabel *srcLabel, int *ctrlService) { ParamWorkSpace *paramSpace = GetParamWorkSpace(); @@ -311,24 +317,25 @@ INIT_INNER_API int CheckParameterSet(const char *name, PARAM_CHECK(ret == 0, return ret, "Illegal param value %s", value); *ctrlService = 0; -#ifndef __LITEOS_M__ - if (getpid() != 1) { // none init -#ifdef PARAM_SUPPORT_SELINUX - *ctrlService |= PARAM_NEED_CHECK_IN_SERVICE; - return 0; -#else - if ((srcLabel->flags[0] & LABEL_CHECK_IN_ALL_PROCESS) != LABEL_CHECK_IN_ALL_PROCESS) { - *ctrlService |= PARAM_NEED_CHECK_IN_SERVICE; + ServiceCtrlInfo *serviceInfo = NULL; + GetServiceCtrlInfo(name, value, &serviceInfo); + ret = CheckParamPermission(srcLabel, (serviceInfo == NULL) ? name : serviceInfo->realKey, DAC_WRITE); + if (ret == 0) { + if (serviceInfo == NULL) { return 0; } + if (serviceInfo->ctrlParam != 0) { // ctrl param + *ctrlService |= PARAM_CTRL_SERVICE; + } +#if !(defined __LITEOS_A__ || defined __LITEOS_M__) + // do hook cmd + PARAM_LOGI("CheckParameterSet realKey %s cmd: '%s' value: %s", + serviceInfo->realKey, serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset); + DoCmdByName(serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset); #endif } -#endif - char *key = GetServiceCtrlName(name, value); - ret = CheckParamPermission(srcLabel, (key == NULL) ? name : key, DAC_WRITE); - if (key != NULL) { // ctrl param - free(key); - *ctrlService |= PARAM_CTRL_SERVICE; + if (serviceInfo != NULL) { + free(serviceInfo); } return ret; } diff --git a/services/param/trigger/trigger_processor.c b/services/param/trigger/trigger_processor.c index 50d8be10..eca45b6e 100644 --- a/services/param/trigger/trigger_processor.c +++ b/services/param/trigger/trigger_processor.c @@ -14,7 +14,6 @@ */ #include -#include "init_cmds.h" #include "init_param.h" #include "init_service_manager.h" #include "init_utils.h" @@ -24,6 +23,8 @@ #include "trigger_checker.h" #include "trigger_manager.h" #include "securec.h" +#include "hookmgr.h" +#include "bootstage.h" #define MAX_TRIGGER_COUNT_RUN_ONCE 20 static TriggerWorkSpace g_triggerWorkSpace = {}; @@ -140,65 +141,11 @@ PARAM_STATIC void ProcessBeforeEvent(const ParamTaskPtr stream, } } -static const char *GetCmdInfo(const char *content, uint32_t contentSize) -{ - static char buffer[PARAM_NAME_LEN_MAX] = {0}; - uint32_t index = 0; - while (index < contentSize && index < PARAM_NAME_LEN_MAX) { - if (*(content + index) == '=' || *(content + index) == ',') { - break; - } - buffer[index] = *(content + index); - index++; - } - if (index >= (PARAM_NAME_LEN_MAX - 1)) { - return NULL; - } - buffer[index] = ' '; - buffer[index + 1] = '\0'; - int cmdIndex = 0; - return GetMatchCmd(buffer, &cmdIndex); -} - -static void DoServiceCtrlTrigger(const char *cmdStart, uint32_t len, int onlyValue) -{ - char *cmdParam = (char *)cmdStart; - const char *matchCmd = GetCmdInfo(cmdStart, len); - if (matchCmd != NULL) { - size_t cmdLen = strlen(matchCmd); - if (onlyValue != 0 && cmdParam != NULL && strlen(cmdParam) > cmdLen) { - cmdParam += cmdLen + 1; - } - PARAM_LOGV("DoServiceCtrlTrigger matchCmd %s cmdParam %s", matchCmd, cmdParam); -#ifndef STARTUP_INIT_TEST - DoCmdByName(matchCmd, cmdParam); -#endif - } else { - PARAM_LOGE("DoServiceCtrlTrigger cmd %s not found", cmdStart); - } -} - static void SendTriggerEvent(int type, const char *content, uint32_t contentLen) { PARAM_CHECK(content != NULL, return, "Invalid param"); PARAM_LOGV("SendTriggerEvent type %d content %s", type, content); - if (type == EVENT_TRIGGER_PARAM) { - int ctrlSize = strlen(SYS_POWER_CTRL); - int prefixSize = strlen(OHOS_SERVICE_CTRL_PREFIX); - if (strncmp(content, SYS_POWER_CTRL, ctrlSize) == 0) { - DoServiceCtrlTrigger(content + ctrlSize, contentLen - ctrlSize, 0); - } else if (strncmp(content, OHOS_SERVICE_CTRL_PREFIX, prefixSize) == 0) { - DoServiceCtrlTrigger(content + prefixSize, contentLen - prefixSize, 1); - } else if (strncmp(content, OHOS_CTRL_START, strlen(OHOS_CTRL_START)) == 0) { - StartServiceByName(content + strlen(OHOS_CTRL_START)); - } else if (strncmp(content, OHOS_CTRL_STOP, strlen(OHOS_CTRL_STOP)) == 0) { - StopServiceByName(content + strlen(OHOS_CTRL_STOP)); - } else { - ParamEventSend(g_triggerWorkSpace.eventHandle, (uint64_t)type, content, contentLen); - } - } else { - ParamEventSend(g_triggerWorkSpace.eventHandle, (uint64_t)type, content, contentLen); - } + ParamEventSend(g_triggerWorkSpace.eventHandle, (uint64_t)type, content, contentLen); } void PostParamTrigger(int type, const char *name, const char *value) @@ -254,6 +201,40 @@ static int GetCommandInfo(const char *cmdLine, int *cmdKeyIndex, char **content) return 0; } +/** + * job Config File Parse Hooking + */ +static int JobParseHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) +{ + JOB_PARSE_CTX *jobParseContext = (JOB_PARSE_CTX *)executionContext; + JobParseHook realHook = (JobParseHook)hookInfo->hookCookie; + + realHook(jobParseContext); + return 0; +}; + +int InitAddJobParseHook(JobParseHook hook) +{ + HOOK_INFO info; + + info.stage = INIT_JOB_PARSE; + info.prio = 0; + info.hook = JobParseHookWrapper; + info.hookCookie = (void *)hook; + + return HookMgrAddEx(GetBootStageHookMgr(), &info); +} + +static void ParseJobHookExecute(const char *name, const cJSON *jobNode) +{ + JOB_PARSE_CTX context; + + context.jobName = name; + context.jobNode = jobNode; + + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_JOB_PARSE, (void *)(&context), NULL); +} + static int ParseTrigger_(const TriggerWorkSpace *workSpace, const cJSON *triggerItem, int (*checkJobValid)(const char *jobName)) { @@ -310,6 +291,10 @@ int ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *j for (int i = 0; i < size && i < TRIGGER_MAX_CMD; ++i) { cJSON *item = cJSON_GetArrayItem(triggers, i); ParseTrigger_(&g_triggerWorkSpace, item, checkJobValid); + /* + * execute job parsing hooks + */ + ParseJobHookExecute(cJSON_GetStringValue(cJSON_GetObjectItem(item, "name")), item); } return 0; } diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 6e2ad6c6..1c919a4a 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -81,6 +81,8 @@ ohos_unittest("init_unittest") { "//base/startup/init/services/loopevent/task/le_watchtask.c", "//base/startup/init/services/loopevent/timer/le_timer.c", "//base/startup/init/services/loopevent/utils/le_utils.c", + "//base/startup/init/services/modules/init_hook/init_hook.c", + "//base/startup/init/services/modules/init_hook/param_hook.c", "//base/startup/init/services/param/adapter/param_dac.c", "//base/startup/init/services/param/adapter/param_persistadp.c", "//base/startup/init/services/param/base/param_base.c", @@ -157,6 +159,7 @@ ohos_unittest("init_unittest") { sources += [ "//base/startup/init/interfaces/innerkits/hookmgr/hookmgr.c", + "//base/startup/init/interfaces/innerkits/init_module_engine/init_modulemgr.c", "//base/startup/init/interfaces/innerkits/modulemgr/modulemgr.c", "innerkits/hookmgr_unittest.cpp", "innerkits/modulemgr_unittest.cpp", @@ -186,6 +189,10 @@ ohos_unittest("init_unittest") { "//base/startup/init/services/loopevent/task", "//base/startup/init/services/loopevent/timer", "//base/startup/init/services/loopevent/utils", + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/modules/selinux", + "//base/startup/init/services/loopevent/utils", "//base/startup/init/services/param/adapter", "//base/startup/init/services/param/base", "//base/startup/init/services/param/linux", diff --git a/test/unittest/lite/BUILD.gn b/test/unittest/lite/BUILD.gn index c00582b8..db734a00 100755 --- a/test/unittest/lite/BUILD.gn +++ b/test/unittest/lite/BUILD.gn @@ -36,6 +36,7 @@ if (defined(ohos_lite)) { ] } param_common_sources = [ + "//base/startup/init/services/modules/init_hook/param_hook.c", "//base/startup/init/services/param/manager/param_manager.c", "//base/startup/init/services/param/manager/param_persist.c", "//base/startup/init/services/param/manager/param_server.c", @@ -94,10 +95,14 @@ if (defined(ohos_lite)) { "//base/startup/init/services/param/watcher/agent", "//base/startup/init/services/param/watcher/include", "//base/startup/init/services/param/watcher/proxy", + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/modules/selinux", "//base/startup/init/test/unittest", "//base/startup/init/test/unittest/param", "//base/startup/init/interfaces/innerkits/include", "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", "//base/startup/init/interfaces/innerkits/syspara", "//third_party/cJSON", "//third_party/bounds_checking_function/include", diff --git a/test/unittest/param/param_unittest.cpp b/test/unittest/param/param_unittest.cpp index 52a57580..6d71363b 100644 --- a/test/unittest/param/param_unittest.cpp +++ b/test/unittest/param/param_unittest.cpp @@ -27,7 +27,11 @@ using namespace std; extern "C" { int WorkSpaceNodeCompare(const HashNode *node1, const HashNode *node2); -char *GetServiceCtrlName(const char *name, const char *value); +} + +static void OnClose(ParamTaskPtr client) +{ + UNUSED(client); } static int CheckServerParamValue(const char *name, const char *expectValue) @@ -412,10 +416,24 @@ HWTEST_F(ParamUnitTest, TestLinuxRWLock, TestSize.Level0) free(workspace1); free(workspace2); } + HWTEST_F(ParamUnitTest, TestGetServiceCtlName, TestSize.Level0) { - EXPECT_STREQ(GetServiceCtrlName("ohos.startup.powerctrl", "reboot,updater"), "ohos.servicectrl.reboot.updater"); - EXPECT_STREQ(GetServiceCtrlName("ohos.ctl.stop", "test"), "ohos.servicectrl.test"); - EXPECT_STREQ(GetServiceCtrlName("ohos.servicectrl.stop", "test"), "ohos.servicectrl.stop.test"); + ServiceCtrlInfo *serviceInfo = NULL; + GetServiceCtrlInfo("ohos.startup.powerctrl", "reboot,updater", &serviceInfo); + if (serviceInfo != NULL) { + EXPECT_STREQ(serviceInfo->realKey, "ohos.servicectrl.reboot.updater.reboot,updater"); + free(serviceInfo); + } + GetServiceCtrlInfo("ohos.ctl.stop", "test", &serviceInfo); + if (serviceInfo != NULL) { + EXPECT_STREQ(serviceInfo->realKey, "ohos.servicectrl.stop.test"); + free(serviceInfo); + } + GetServiceCtrlInfo("ohos.servicectrl.stop", "test", &serviceInfo); + if (serviceInfo != NULL) { + EXPECT_STREQ(serviceInfo->realKey, "ohos.servicectrl.stop.test"); + free(serviceInfo); + } } } diff --git a/test/unittest/param/paramservice_unittest.cpp b/test/unittest/param/paramservice_unittest.cpp index 509191a2..efc8362a 100644 --- a/test/unittest/param/paramservice_unittest.cpp +++ b/test/unittest/param/paramservice_unittest.cpp @@ -528,49 +528,34 @@ HWTEST_F(ParamServiceUnitTest, TestServiceCtrl, TestSize.Level0) { ParamServiceUnitTest test; int ret = test.TestServiceCtrl("server1", 0770); -#ifdef PARAM_SUPPORT_SELINUX - EXPECT_EQ(ret, 0); -#else - EXPECT_NE(ret, 0); -#endif + EXPECT_NE(ret, 0); + // selinux forbid ret = test.TestServiceCtrl("server2", 0772); - EXPECT_EQ(ret, 0); + EXPECT_NE(ret, 0); } HWTEST_F(ParamServiceUnitTest, TestPowerCtrl, TestSize.Level0) { ParamServiceUnitTest test; int ret = test.TestPowerCtrl("reboot,shutdown", 0770); -#ifdef PARAM_SUPPORT_SELINUX - EXPECT_EQ(ret, 0); -#else - EXPECT_NE(ret, 0); -#endif + EXPECT_NE(ret, 0); ret = test.TestPowerCtrl("reboot,shutdown", 0772); - EXPECT_EQ(ret, 0); + // selinux forbid + EXPECT_NE(ret, 0); ret = test.TestPowerCtrl("reboot,updater", 0770); -#ifdef PARAM_SUPPORT_SELINUX - EXPECT_EQ(ret, 0); -#else - EXPECT_NE(ret, 0); -#endif + EXPECT_NE(ret, 0); ret = test.TestPowerCtrl("reboot,updater", 0772); - EXPECT_EQ(ret, 0); + // selinux forbid + EXPECT_NE(ret, 0); ret = test.TestPowerCtrl("reboot,flash", 0770); -#ifdef PARAM_SUPPORT_SELINUX - EXPECT_EQ(ret, 0); -#else - EXPECT_NE(ret, 0); -#endif + EXPECT_NE(ret, 0); ret = test.TestPowerCtrl("reboot,flash", 0772); - EXPECT_EQ(ret, 0); + // selinux forbid + EXPECT_NE(ret, 0); ret = test.TestPowerCtrl("reboot", 0770); -#ifdef PARAM_SUPPORT_SELINUX - EXPECT_EQ(ret, 0); -#else - EXPECT_NE(ret, 0); -#endif + EXPECT_NE(ret, 0); ret = test.TestPowerCtrl("reboot", 0772); - EXPECT_EQ(ret, 0); + // selinux forbid + EXPECT_NE(ret, 0); } } // namespace init_ut -- GitLab