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 NWEB_HAP_LIB_PATH = "/data/storage/el1/bundle/nweb/libs/arm64";
40 #elif defined(webview_x86_64)
41 const std::string NWEB_HAP_LIB_PATH = "/data/storage/el1/bundle/nweb/libs/x86_64";
42 #else
43 const std::string NWEB_HAP_LIB_PATH = "/data/storage/el1/bundle/nweb/libs/arm";
44 #endif
45 } // namespace
46
SetSeccompPolicyForRenderer(void * nwebRenderHandle)47 static bool SetSeccompPolicyForRenderer(void *nwebRenderHandle)
48 {
49 #ifdef WITH_SECCOMP
50 if (IsEnableSeccomp()) {
51 using SeccompFuncType = bool (*)(void);
52 SeccompFuncType funcSetRendererSeccompPolicy =
53 reinterpret_cast<SeccompFuncType>(dlsym(nwebRenderHandle, "SetRendererSeccompPolicy"));
54 if (funcSetRendererSeccompPolicy != nullptr && funcSetRendererSeccompPolicy()) {
55 return true;
56 }
57 APPSPAWN_LOGE("SetRendererSeccompPolicy dlsym errno: %{public}d", errno);
58 return false;
59 }
60 #endif
61 return true;
62 }
63
RunChildProcessor(AppSpawnContent * content,AppSpawnClient * client)64 static int RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client)
65 {
66 uint32_t len = 0;
67 char *renderCmd = reinterpret_cast<char *>(GetAppPropertyExt(
68 reinterpret_cast<AppSpawningCtx *>(client), MSG_EXT_NAME_RENDER_CMD, &len));
69 if (renderCmd == nullptr) {
70 return -1;
71 }
72 std::string renderStr(renderCmd);
73 void *webEngineHandle = nullptr;
74 void *nwebRenderHandle = nullptr;
75 #ifdef __MUSL__
76 Dl_namespace dlns;
77 dlns_init(&dlns, "nweb_ns");
78 dlns_create(&dlns, NWEB_HAP_LIB_PATH.c_str());
79
80 // preload libweb_engine
81 webEngineHandle = dlopen_ns(&dlns, "libweb_engine.so", RTLD_NOW | RTLD_GLOBAL);
82
83 // load libnweb_render
84 nwebRenderHandle = dlopen_ns(&dlns, "libnweb_render.so", RTLD_NOW | RTLD_GLOBAL);
85 #else
86 // preload libweb_engine
87 const std::string engineLibDir = NWEB_HAP_LIB_PATH + "/libweb_engine.so";
88 webEngineHandle = dlopen(engineLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
89
90 // load libnweb_render
91 const std::string renderLibDir = NWEB_HAP_LIB_PATH + "/libnweb_render.so";
92 nwebRenderHandle = dlopen(renderLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
93 #endif
94 if (webEngineHandle == nullptr) {
95 APPSPAWN_LOGE("Fail to dlopen libweb_engine.so, errno: %{public}d", errno);
96 }
97
98 if (nwebRenderHandle == nullptr) {
99 APPSPAWN_LOGE("Fail to dlopen libnweb_render.so, errno: %{public}d", errno);
100 return -1;
101 }
102
103 if (!SetSeccompPolicyForRenderer(nwebRenderHandle)) {
104 return -1;
105 }
106 using FuncType = void (*)(const char *cmd);
107
108 FuncType funcNWebRenderMain = reinterpret_cast<FuncType>(dlsym(nwebRenderHandle, "NWebRenderMain"));
109 if (funcNWebRenderMain == nullptr) {
110 APPSPAWN_LOGE("webviewspawn dlsym errno: %{public}d", errno);
111 return -1;
112 }
113 AppSpawnEnvClear(content, client);
114 funcNWebRenderMain(renderStr.c_str());
115 APPSPAWN_LOGI("RunChildProcessorNweb %{public}s", renderStr.c_str());
116 return 0;
117 }
118
PreLoadNwebSpawn(AppSpawnMgr * content)119 static int PreLoadNwebSpawn(AppSpawnMgr *content)
120 {
121 APPSPAWN_LOGI("PreLoadNwebSpawn %{public}d", IsNWebSpawnMode(content));
122 if (!IsNWebSpawnMode(content)) {
123 return 0;
124 }
125 // register
126 RegChildLooper(&content->content, RunChildProcessor);
127 return 0;
128 }
129
MODULE_CONSTRUCTOR(void)130 MODULE_CONSTRUCTOR(void)
131 {
132 APPSPAWN_LOGI("Load nweb module ...");
133 AddPreloadHook(HOOK_PRIO_HIGHEST, PreLoadNwebSpawn);
134 }
135