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
44 namespace {
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
SetSeccompPolicyForRenderer(void *nwebRenderHandle)61 APPSPAWN_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
GetArkWebEngineLibName()78 APPSPAWN_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
GetArkWebRenderLibName()87 APPSPAWN_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
RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client)96 APPSPAWN_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
PreLoadNwebSpawn(AppSpawnMgr *content)156 static 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
MODULE_CONSTRUCTOR(void)167 MODULE_CONSTRUCTOR(void)
168 {
169 APPSPAWN_LOGI("Load nweb module ...");
170 AddPreloadHook(HOOK_PRIO_HIGHEST, PreLoadNwebSpawn);
171 }
172