169570cc8Sopenharmony_ci/*
269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License.
569570cc8Sopenharmony_ci * You may obtain a copy of the License at
669570cc8Sopenharmony_ci *
769570cc8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
869570cc8Sopenharmony_ci *
969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and
1369570cc8Sopenharmony_ci * limitations under the License.
1469570cc8Sopenharmony_ci */
1569570cc8Sopenharmony_ci
1669570cc8Sopenharmony_ci#include <algorithm>
1769570cc8Sopenharmony_ci#include <cerrno>
1869570cc8Sopenharmony_ci#include <ctime>
1969570cc8Sopenharmony_ci#include <dlfcn.h>
2069570cc8Sopenharmony_ci#include <map>
2169570cc8Sopenharmony_ci#include <mutex>
2269570cc8Sopenharmony_ci#include <string>
2369570cc8Sopenharmony_ci
2469570cc8Sopenharmony_ci#ifdef __MUSL__
2569570cc8Sopenharmony_ci#include <cerrno>
2669570cc8Sopenharmony_ci#include <dlfcn_ext.h>
2769570cc8Sopenharmony_ci#include <sys/mman.h>
2869570cc8Sopenharmony_ci#endif
2969570cc8Sopenharmony_ci
3069570cc8Sopenharmony_ci#include "appspawn_hook.h"
3169570cc8Sopenharmony_ci#include "appspawn_manager.h"
3269570cc8Sopenharmony_ci#include "appspawn_utils.h"
3369570cc8Sopenharmony_ci
3469570cc8Sopenharmony_ci#ifdef WITH_SECCOMP
3569570cc8Sopenharmony_ci#include "seccomp_policy.h"
3669570cc8Sopenharmony_ci#endif
3769570cc8Sopenharmony_ci
3869570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST
3969570cc8Sopenharmony_ci#define APPSPAWN_STATIC static
4069570cc8Sopenharmony_ci#else
4169570cc8Sopenharmony_ci#define APPSPAWN_STATIC
4269570cc8Sopenharmony_ci#endif
4369570cc8Sopenharmony_ci
4469570cc8Sopenharmony_cinamespace {
4569570cc8Sopenharmony_ci#if defined(webview_arm64)
4669570cc8Sopenharmony_ci    const std::string ARK_WEB_CORE_HAP_LIB_PATH =
4769570cc8Sopenharmony_ci        "/data/storage/el1/bundle/arkwebcore/libs/arm64";
4869570cc8Sopenharmony_ci#elif defined(webview_x86_64)
4969570cc8Sopenharmony_ci    const std::string ARK_WEB_CORE_HAP_LIB_PATH =
5069570cc8Sopenharmony_ci        "/data/storage/el1/bundle/arkwebcore/libs/x86_64";
5169570cc8Sopenharmony_ci#else
5269570cc8Sopenharmony_ci    const std::string ARK_WEB_CORE_HAP_LIB_PATH =
5369570cc8Sopenharmony_ci        "/data/storage/el1/bundle/arkwebcore/libs/arm";
5469570cc8Sopenharmony_ci#endif
5569570cc8Sopenharmony_ci    const std::string ARK_WEB_ENGINE_LIB_NAME = "libarkweb_engine.so";
5669570cc8Sopenharmony_ci    const std::string ARK_WEB_RENDER_LIB_NAME = "libarkweb_render.so";
5769570cc8Sopenharmony_ci    const std::string WEB_ENGINE_LIB_NAME = "libweb_engine.so";
5869570cc8Sopenharmony_ci    const std::string WEB_RENDER_LIB_NAME = "libnweb_render.so";
5969570cc8Sopenharmony_ci}  // namespace
6069570cc8Sopenharmony_ci
6169570cc8Sopenharmony_ciAPPSPAWN_STATIC bool SetSeccompPolicyForRenderer(void *nwebRenderHandle)
6269570cc8Sopenharmony_ci{
6369570cc8Sopenharmony_ci#ifdef WITH_SECCOMP
6469570cc8Sopenharmony_ci    if (IsEnableSeccomp()) {
6569570cc8Sopenharmony_ci        using SeccompFuncType = bool (*)(void);
6669570cc8Sopenharmony_ci        SeccompFuncType funcSetRendererSeccompPolicy =
6769570cc8Sopenharmony_ci                reinterpret_cast<SeccompFuncType>(dlsym(nwebRenderHandle, "SetRendererSeccompPolicy"));
6869570cc8Sopenharmony_ci        if (funcSetRendererSeccompPolicy != nullptr && funcSetRendererSeccompPolicy()) {
6969570cc8Sopenharmony_ci            return true;
7069570cc8Sopenharmony_ci        }
7169570cc8Sopenharmony_ci        APPSPAWN_LOGE("SetRendererSeccompPolicy dlsym errno: %{public}d", errno);
7269570cc8Sopenharmony_ci        return false;
7369570cc8Sopenharmony_ci    }
7469570cc8Sopenharmony_ci#endif
7569570cc8Sopenharmony_ci    return true;
7669570cc8Sopenharmony_ci}
7769570cc8Sopenharmony_ci
7869570cc8Sopenharmony_ciAPPSPAWN_STATIC std::string GetArkWebEngineLibName()
7969570cc8Sopenharmony_ci{
8069570cc8Sopenharmony_ci    std::string arkWebEngineLibPath = ARK_WEB_CORE_HAP_LIB_PATH + "/"
8169570cc8Sopenharmony_ci            + ARK_WEB_ENGINE_LIB_NAME;
8269570cc8Sopenharmony_ci    bool isArkWebEngineLibPathExist = access(arkWebEngineLibPath.c_str(), F_OK) == 0;
8369570cc8Sopenharmony_ci    return isArkWebEngineLibPathExist ?
8469570cc8Sopenharmony_ci            ARK_WEB_ENGINE_LIB_NAME : WEB_ENGINE_LIB_NAME;
8569570cc8Sopenharmony_ci}
8669570cc8Sopenharmony_ci
8769570cc8Sopenharmony_ciAPPSPAWN_STATIC std::string GetArkWebRenderLibName()
8869570cc8Sopenharmony_ci{
8969570cc8Sopenharmony_ci    std::string arkWebRenderLibPath = ARK_WEB_CORE_HAP_LIB_PATH + "/"
9069570cc8Sopenharmony_ci            + ARK_WEB_RENDER_LIB_NAME;
9169570cc8Sopenharmony_ci    bool isArkWebRenderLibPathExist = access(arkWebRenderLibPath.c_str(), F_OK) == 0;
9269570cc8Sopenharmony_ci    return isArkWebRenderLibPathExist ?
9369570cc8Sopenharmony_ci            ARK_WEB_RENDER_LIB_NAME : WEB_RENDER_LIB_NAME;
9469570cc8Sopenharmony_ci}
9569570cc8Sopenharmony_ci
9669570cc8Sopenharmony_ciAPPSPAWN_STATIC int RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client)
9769570cc8Sopenharmony_ci{
9869570cc8Sopenharmony_ci    EnableCache();
9969570cc8Sopenharmony_ci    uint32_t len = 0;
10069570cc8Sopenharmony_ci    char *renderCmd = reinterpret_cast<char *>(GetAppPropertyExt(
10169570cc8Sopenharmony_ci        reinterpret_cast<AppSpawningCtx *>(client), MSG_EXT_NAME_RENDER_CMD, &len));
10269570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(renderCmd != nullptr, return -1);
10369570cc8Sopenharmony_ci    std::string renderStr(renderCmd);
10469570cc8Sopenharmony_ci    void *webEngineHandle = nullptr;
10569570cc8Sopenharmony_ci    void *nwebRenderHandle = nullptr;
10669570cc8Sopenharmony_ci
10769570cc8Sopenharmony_ci    const std::string& libPath = ARK_WEB_CORE_HAP_LIB_PATH;
10869570cc8Sopenharmony_ci    const std::string engineLibName = GetArkWebEngineLibName();
10969570cc8Sopenharmony_ci    const std::string renderLibName = GetArkWebRenderLibName();
11069570cc8Sopenharmony_ci
11169570cc8Sopenharmony_ci#ifdef __MUSL__
11269570cc8Sopenharmony_ci    Dl_namespace dlns;
11369570cc8Sopenharmony_ci    dlns_init(&dlns, "nweb_ns");
11469570cc8Sopenharmony_ci    dlns_create(&dlns, libPath.c_str());
11569570cc8Sopenharmony_ci    // preload libweb_engine
11669570cc8Sopenharmony_ci    webEngineHandle =
11769570cc8Sopenharmony_ci        dlopen_ns(&dlns, engineLibName.c_str(), RTLD_NOW | RTLD_GLOBAL);
11869570cc8Sopenharmony_ci    // load libnweb_render
11969570cc8Sopenharmony_ci    nwebRenderHandle =
12069570cc8Sopenharmony_ci        dlopen_ns(&dlns, renderLibName.c_str(), RTLD_NOW | RTLD_GLOBAL);
12169570cc8Sopenharmony_ci#else
12269570cc8Sopenharmony_ci    // preload libweb_engine
12369570cc8Sopenharmony_ci    const std::string engineLibPath = libPath + "/" + engineLibName;
12469570cc8Sopenharmony_ci    webEngineHandle = dlopen(engineLibPath.c_str(), RTLD_NOW | RTLD_GLOBAL);
12569570cc8Sopenharmony_ci
12669570cc8Sopenharmony_ci    // load libnweb_render
12769570cc8Sopenharmony_ci    const std::string renderLibPath = libPath + "/" + renderLibName;
12869570cc8Sopenharmony_ci    nwebRenderHandle = dlopen(renderLibPath.c_str(), RTLD_NOW | RTLD_GLOBAL);
12969570cc8Sopenharmony_ci#endif
13069570cc8Sopenharmony_ci    if (webEngineHandle == nullptr) {
13169570cc8Sopenharmony_ci        APPSPAWN_LOGE("Fail to dlopen libweb_engine.so, errno: %{public}d", errno);
13269570cc8Sopenharmony_ci    }
13369570cc8Sopenharmony_ci    if (nwebRenderHandle == nullptr) {
13469570cc8Sopenharmony_ci        APPSPAWN_LOGE("Fail to dlopen libnweb_render.so, errno: %{public}d", errno);
13569570cc8Sopenharmony_ci        return -1;
13669570cc8Sopenharmony_ci    }
13769570cc8Sopenharmony_ci
13869570cc8Sopenharmony_ci    std::string processType = reinterpret_cast<char *>(GetAppPropertyExt(
13969570cc8Sopenharmony_ci        reinterpret_cast<AppSpawningCtx *>(client), MSG_EXT_NAME_PROCESS_TYPE, &len));
14069570cc8Sopenharmony_ci    if (processType == "render" && !SetSeccompPolicyForRenderer(nwebRenderHandle)) {
14169570cc8Sopenharmony_ci        return -1;
14269570cc8Sopenharmony_ci    }
14369570cc8Sopenharmony_ci    using FuncType = void (*)(const char *cmd);
14469570cc8Sopenharmony_ci
14569570cc8Sopenharmony_ci    FuncType funcNWebRenderMain = reinterpret_cast<FuncType>(dlsym(nwebRenderHandle, "NWebRenderMain"));
14669570cc8Sopenharmony_ci    if (funcNWebRenderMain == nullptr) {
14769570cc8Sopenharmony_ci        APPSPAWN_LOGE("webviewspawn dlsym errno: %{public}d", errno);
14869570cc8Sopenharmony_ci        return -1;
14969570cc8Sopenharmony_ci    }
15069570cc8Sopenharmony_ci    AppSpawnEnvClear(content, client);
15169570cc8Sopenharmony_ci    APPSPAWN_LOGI("RunChildProcessorNweb %{public}s", renderStr.c_str());
15269570cc8Sopenharmony_ci    funcNWebRenderMain(renderStr.c_str());
15369570cc8Sopenharmony_ci    return 0;
15469570cc8Sopenharmony_ci}
15569570cc8Sopenharmony_ci
15669570cc8Sopenharmony_cistatic int PreLoadNwebSpawn(AppSpawnMgr *content)
15769570cc8Sopenharmony_ci{
15869570cc8Sopenharmony_ci    APPSPAWN_LOGI("PreLoadNwebSpawn %{public}d", IsNWebSpawnMode(content));
15969570cc8Sopenharmony_ci    if (!IsNWebSpawnMode(content)) {
16069570cc8Sopenharmony_ci        return 0;
16169570cc8Sopenharmony_ci    }
16269570cc8Sopenharmony_ci    // register
16369570cc8Sopenharmony_ci    RegChildLooper(&content->content, RunChildProcessor);
16469570cc8Sopenharmony_ci    return 0;
16569570cc8Sopenharmony_ci}
16669570cc8Sopenharmony_ci
16769570cc8Sopenharmony_ciMODULE_CONSTRUCTOR(void)
16869570cc8Sopenharmony_ci{
16969570cc8Sopenharmony_ci    APPSPAWN_LOGI("Load nweb module ...");
17069570cc8Sopenharmony_ci    AddPreloadHook(HOOK_PRIO_HIGHEST, PreLoadNwebSpawn);
17169570cc8Sopenharmony_ci}
172