/* * Copyright (c) 2024 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 #include #include #include #include #include #include #ifdef __MUSL__ #include #include #include #endif #include "appspawn_hook.h" #include "appspawn_manager.h" #ifdef WITH_SECCOMP #include "seccomp_policy.h" #endif namespace { #if defined(webview_arm64) const std::string ARK_WEB_CORE_HAP_LIB_PATH = "/data/storage/el1/bundle/arkwebcore/libs/arm64"; #elif defined(webview_x86_64) const std::string ARK_WEB_CORE_HAP_LIB_PATH = "/data/storage/el1/bundle/arkwebcore/libs/x86_64"; #else const std::string ARK_WEB_CORE_HAP_LIB_PATH = "/data/storage/el1/bundle/arkwebcore/libs/arm"; #endif const std::string ARK_WEB_ENGINE_LIB_NAME = "libarkweb_engine.so"; const std::string ARK_WEB_RENDER_LIB_NAME = "libarkweb_render.so"; const std::string WEB_ENGINE_LIB_NAME = "libweb_engine.so"; const std::string WEB_RENDER_LIB_NAME = "libnweb_render.so"; } // namespace static bool SetSeccompPolicyForRenderer(void *nwebRenderHandle) { #ifdef WITH_SECCOMP if (IsEnableSeccomp()) { using SeccompFuncType = bool (*)(void); SeccompFuncType funcSetRendererSeccompPolicy = reinterpret_cast(dlsym(nwebRenderHandle, "SetRendererSeccompPolicy")); if (funcSetRendererSeccompPolicy != nullptr && funcSetRendererSeccompPolicy()) { return true; } APPSPAWN_LOGE("SetRendererSeccompPolicy dlsym errno: %{public}d", errno); return false; } #endif return true; } APPSPAWN_STATIC std::string GetArkWebEngineLibName() { std::string arkWebEngineLibPath = ARK_WEB_CORE_HAP_LIB_PATH + "/" + ARK_WEB_ENGINE_LIB_NAME; bool isArkWebEngineLibPathExist = access(arkWebEngineLibPath.c_str(), F_OK) == 0; return isArkWebEngineLibPathExist ? ARK_WEB_ENGINE_LIB_NAME : WEB_ENGINE_LIB_NAME; } APPSPAWN_STATIC std::string GetArkWebRenderLibName() { std::string arkWebRenderLibPath = ARK_WEB_CORE_HAP_LIB_PATH + "/" + ARK_WEB_RENDER_LIB_NAME; bool isArkWebRenderLibPathExist = access(arkWebRenderLibPath.c_str(), F_OK) == 0; return isArkWebRenderLibPathExist ? ARK_WEB_RENDER_LIB_NAME : WEB_RENDER_LIB_NAME; } APPSPAWN_STATIC int RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) { uint32_t len = 0; char *renderCmd = reinterpret_cast(GetAppPropertyExt( reinterpret_cast(client), MSG_EXT_NAME_RENDER_CMD, &len)); if (renderCmd == nullptr) { return -1; } std::string renderStr(renderCmd); void *webEngineHandle = nullptr; void *nwebRenderHandle = nullptr; const std::string& libPath = ARK_WEB_CORE_HAP_LIB_PATH; const std::string engineLibName = GetArkWebEngineLibName(); const std::string renderLibName = GetArkWebRenderLibName(); #ifdef __MUSL__ Dl_namespace dlns; dlns_init(&dlns, "nweb_ns"); dlns_create(&dlns, libPath.c_str()); // preload libweb_engine webEngineHandle = dlopen_ns(&dlns, engineLibName.c_str(), RTLD_NOW | RTLD_GLOBAL); // load libnweb_render nwebRenderHandle = dlopen_ns(&dlns, renderLibName.c_str(), RTLD_NOW | RTLD_GLOBAL); #else // preload libweb_engine const std::string engineLibPath = libPath + "/" + engineLibName; webEngineHandle = dlopen(engineLibPath.c_str(), RTLD_NOW | RTLD_GLOBAL); // load libnweb_render const std::string renderLibPath = libPath + "/" + renderLibName; nwebRenderHandle = dlopen(renderLibPath.c_str(), RTLD_NOW | RTLD_GLOBAL); #endif if (webEngineHandle == nullptr) { APPSPAWN_LOGE("Fail to dlopen libweb_engine.so, errno: %{public}d", errno); } if (nwebRenderHandle == nullptr) { APPSPAWN_LOGE("Fail to dlopen libnweb_render.so, errno: %{public}d", errno); return -1; } std::string processType = reinterpret_cast(GetAppPropertyExt( reinterpret_cast(client), MSG_EXT_NAME_PROCESS_TYPE, &len)); if (processType == "render" && !SetSeccompPolicyForRenderer(nwebRenderHandle)) { return -1; } using FuncType = void (*)(const char *cmd); FuncType funcNWebRenderMain = reinterpret_cast(dlsym(nwebRenderHandle, "NWebRenderMain")); if (funcNWebRenderMain == nullptr) { APPSPAWN_LOGE("webviewspawn dlsym errno: %{public}d", errno); return -1; } AppSpawnEnvClear(content, client); APPSPAWN_LOGI("RunChildProcessorNweb %{public}s", renderStr.c_str()); funcNWebRenderMain(renderStr.c_str()); return 0; } static int PreLoadNwebSpawn(AppSpawnMgr *content) { APPSPAWN_LOGI("PreLoadNwebSpawn %{public}d", IsNWebSpawnMode(content)); if (!IsNWebSpawnMode(content)) { return 0; } // register RegChildLooper(&content->content, RunChildProcessor); return 0; } MODULE_CONSTRUCTOR(void) { APPSPAWN_LOGI("Load nweb module ..."); AddPreloadHook(HOOK_PRIO_HIGHEST, PreLoadNwebSpawn); }