1/* 2 * Copyright (c) 2024 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 <algorithm> 17#include <cerrno> 18#include <ctime> 19#include <dlfcn.h> 20#include <map> 21#include <mutex> 22#include <string> 23 24#ifdef __MUSL__ 25#include <cerrno> 26#include <dlfcn_ext.h> 27#include <sys/mman.h> 28#endif 29 30#include "appspawn_hook.h" 31#include "appspawn_manager.h" 32#include "appspawn_utils.h" 33 34#ifdef WITH_SECCOMP 35#include "seccomp_policy.h" 36#endif 37 38#ifndef APPSPAWN_TEST 39#define APPSPAWN_STATIC static 40#else 41#define APPSPAWN_STATIC 42#endif 43 44namespace { 45#if defined(webview_arm64) 46 const std::string ARK_WEB_CORE_HAP_LIB_PATH = 47 "/data/storage/el1/bundle/arkwebcore/libs/arm64"; 48#elif defined(webview_x86_64) 49 const std::string ARK_WEB_CORE_HAP_LIB_PATH = 50 "/data/storage/el1/bundle/arkwebcore/libs/x86_64"; 51#else 52 const std::string ARK_WEB_CORE_HAP_LIB_PATH = 53 "/data/storage/el1/bundle/arkwebcore/libs/arm"; 54#endif 55 const std::string ARK_WEB_ENGINE_LIB_NAME = "libarkweb_engine.so"; 56 const std::string ARK_WEB_RENDER_LIB_NAME = "libarkweb_render.so"; 57 const std::string WEB_ENGINE_LIB_NAME = "libweb_engine.so"; 58 const std::string WEB_RENDER_LIB_NAME = "libnweb_render.so"; 59} // namespace 60 61APPSPAWN_STATIC bool SetSeccompPolicyForRenderer(void *nwebRenderHandle) 62{ 63#ifdef WITH_SECCOMP 64 if (IsEnableSeccomp()) { 65 using SeccompFuncType = bool (*)(void); 66 SeccompFuncType funcSetRendererSeccompPolicy = 67 reinterpret_cast<SeccompFuncType>(dlsym(nwebRenderHandle, "SetRendererSeccompPolicy")); 68 if (funcSetRendererSeccompPolicy != nullptr && funcSetRendererSeccompPolicy()) { 69 return true; 70 } 71 APPSPAWN_LOGE("SetRendererSeccompPolicy dlsym errno: %{public}d", errno); 72 return false; 73 } 74#endif 75 return true; 76} 77 78APPSPAWN_STATIC std::string GetArkWebEngineLibName() 79{ 80 std::string arkWebEngineLibPath = ARK_WEB_CORE_HAP_LIB_PATH + "/" 81 + ARK_WEB_ENGINE_LIB_NAME; 82 bool isArkWebEngineLibPathExist = access(arkWebEngineLibPath.c_str(), F_OK) == 0; 83 return isArkWebEngineLibPathExist ? 84 ARK_WEB_ENGINE_LIB_NAME : WEB_ENGINE_LIB_NAME; 85} 86 87APPSPAWN_STATIC std::string GetArkWebRenderLibName() 88{ 89 std::string arkWebRenderLibPath = ARK_WEB_CORE_HAP_LIB_PATH + "/" 90 + ARK_WEB_RENDER_LIB_NAME; 91 bool isArkWebRenderLibPathExist = access(arkWebRenderLibPath.c_str(), F_OK) == 0; 92 return isArkWebRenderLibPathExist ? 93 ARK_WEB_RENDER_LIB_NAME : WEB_RENDER_LIB_NAME; 94} 95 96APPSPAWN_STATIC int RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) 97{ 98 EnableCache(); 99 uint32_t len = 0; 100 char *renderCmd = reinterpret_cast<char *>(GetAppPropertyExt( 101 reinterpret_cast<AppSpawningCtx *>(client), MSG_EXT_NAME_RENDER_CMD, &len)); 102 APPSPAWN_CHECK_ONLY_EXPER(renderCmd != nullptr, return -1); 103 std::string renderStr(renderCmd); 104 void *webEngineHandle = nullptr; 105 void *nwebRenderHandle = nullptr; 106 107 const std::string& libPath = ARK_WEB_CORE_HAP_LIB_PATH; 108 const std::string engineLibName = GetArkWebEngineLibName(); 109 const std::string renderLibName = GetArkWebRenderLibName(); 110 111#ifdef __MUSL__ 112 Dl_namespace dlns; 113 dlns_init(&dlns, "nweb_ns"); 114 dlns_create(&dlns, libPath.c_str()); 115 // preload libweb_engine 116 webEngineHandle = 117 dlopen_ns(&dlns, engineLibName.c_str(), RTLD_NOW | RTLD_GLOBAL); 118 // load libnweb_render 119 nwebRenderHandle = 120 dlopen_ns(&dlns, renderLibName.c_str(), RTLD_NOW | RTLD_GLOBAL); 121#else 122 // preload libweb_engine 123 const std::string engineLibPath = libPath + "/" + engineLibName; 124 webEngineHandle = dlopen(engineLibPath.c_str(), RTLD_NOW | RTLD_GLOBAL); 125 126 // load libnweb_render 127 const std::string renderLibPath = libPath + "/" + renderLibName; 128 nwebRenderHandle = dlopen(renderLibPath.c_str(), RTLD_NOW | RTLD_GLOBAL); 129#endif 130 if (webEngineHandle == nullptr) { 131 APPSPAWN_LOGE("Fail to dlopen libweb_engine.so, errno: %{public}d", errno); 132 } 133 if (nwebRenderHandle == nullptr) { 134 APPSPAWN_LOGE("Fail to dlopen libnweb_render.so, errno: %{public}d", errno); 135 return -1; 136 } 137 138 std::string processType = reinterpret_cast<char *>(GetAppPropertyExt( 139 reinterpret_cast<AppSpawningCtx *>(client), MSG_EXT_NAME_PROCESS_TYPE, &len)); 140 if (processType == "render" && !SetSeccompPolicyForRenderer(nwebRenderHandle)) { 141 return -1; 142 } 143 using FuncType = void (*)(const char *cmd); 144 145 FuncType funcNWebRenderMain = reinterpret_cast<FuncType>(dlsym(nwebRenderHandle, "NWebRenderMain")); 146 if (funcNWebRenderMain == nullptr) { 147 APPSPAWN_LOGE("webviewspawn dlsym errno: %{public}d", errno); 148 return -1; 149 } 150 AppSpawnEnvClear(content, client); 151 APPSPAWN_LOGI("RunChildProcessorNweb %{public}s", renderStr.c_str()); 152 funcNWebRenderMain(renderStr.c_str()); 153 return 0; 154} 155 156static int PreLoadNwebSpawn(AppSpawnMgr *content) 157{ 158 APPSPAWN_LOGI("PreLoadNwebSpawn %{public}d", IsNWebSpawnMode(content)); 159 if (!IsNWebSpawnMode(content)) { 160 return 0; 161 } 162 // register 163 RegChildLooper(&content->content, RunChildProcessor); 164 return 0; 165} 166 167MODULE_CONSTRUCTOR(void) 168{ 169 APPSPAWN_LOGI("Load nweb module ..."); 170 AddPreloadHook(HOOK_PRIO_HIGHEST, PreLoadNwebSpawn); 171} 172