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