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 <cerrno>
1769570cc8Sopenharmony_ci#include <cstring>
1869570cc8Sopenharmony_ci#include <dlfcn.h>
1969570cc8Sopenharmony_ci#include <set>
2069570cc8Sopenharmony_ci#include <string>
2169570cc8Sopenharmony_ci#include <unistd.h>
2269570cc8Sopenharmony_ci#include <utility>
2369570cc8Sopenharmony_ci#include <vector>
2469570cc8Sopenharmony_ci
2569570cc8Sopenharmony_ci#include "appspawn_hook.h"
2669570cc8Sopenharmony_ci#include "appspawn_server.h"
2769570cc8Sopenharmony_ci#include "appspawn_service.h"
2869570cc8Sopenharmony_ci#include "appspawn_manager.h"
2969570cc8Sopenharmony_ci#include "appspawn_utils.h"
3069570cc8Sopenharmony_ci#include "parameters.h"
3169570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST
3269570cc8Sopenharmony_ci#include "main_thread.h"
3369570cc8Sopenharmony_ci#endif
3469570cc8Sopenharmony_ci
3569570cc8Sopenharmony_ciAPPSPAWN_STATIC int BuildFdInfoMap(const AppSpawnMsgNode *message, std::map<std::string, int> &fdMap, int isColdRun)
3669570cc8Sopenharmony_ci{
3769570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL, return -1);
3869570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset != NULL, return -1);
3969570cc8Sopenharmony_ci    int findFdIndex = 0;
4069570cc8Sopenharmony_ci    AppSpawnMsgReceiverCtx recvCtx;
4169570cc8Sopenharmony_ci    if (!isColdRun) {
4269570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(message->connection != NULL, return -1);
4369570cc8Sopenharmony_ci        recvCtx = message->connection->receiverCtx;
4469570cc8Sopenharmony_ci        if (recvCtx.fdCount <= 0) {
4569570cc8Sopenharmony_ci            APPSPAWN_LOGI("no need to build fd info %{public}d, %{public}d", recvCtx.fds != NULL, recvCtx.fdCount);
4669570cc8Sopenharmony_ci            return 0;
4769570cc8Sopenharmony_ci        }
4869570cc8Sopenharmony_ci    }
4969570cc8Sopenharmony_ci    for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) {
5069570cc8Sopenharmony_ci        if (message->tlvOffset[index] == INVALID_OFFSET) {
5169570cc8Sopenharmony_ci            return -1;
5269570cc8Sopenharmony_ci        }
5369570cc8Sopenharmony_ci        uint8_t *data = message->buffer + message->tlvOffset[index];
5469570cc8Sopenharmony_ci        if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) {
5569570cc8Sopenharmony_ci            continue;
5669570cc8Sopenharmony_ci        }
5769570cc8Sopenharmony_ci        AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data;
5869570cc8Sopenharmony_ci        if (strcmp(tlv->tlvName, MSG_EXT_NAME_APP_FD) != 0) {
5969570cc8Sopenharmony_ci            continue;
6069570cc8Sopenharmony_ci        }
6169570cc8Sopenharmony_ci        std::string key((char *)data + sizeof(AppSpawnTlvExt));
6269570cc8Sopenharmony_ci        if (isColdRun) {
6369570cc8Sopenharmony_ci            std::string envKey = std::string(APP_FDENV_PREFIX) + key;
6469570cc8Sopenharmony_ci            char *fdChar = getenv(envKey.c_str());
6569570cc8Sopenharmony_ci            APPSPAWN_CHECK(fdChar != NULL, continue, "getfd from env failed %{public}s", envKey.c_str());
6669570cc8Sopenharmony_ci            int fd = atoi(fdChar);
6769570cc8Sopenharmony_ci            APPSPAWN_CHECK(fd > 0, continue, "getfd from env atoi errno %{public}s,%{public}d", envKey.c_str(), fd);
6869570cc8Sopenharmony_ci            fdMap[key] = fd;
6969570cc8Sopenharmony_ci        } else {
7069570cc8Sopenharmony_ci            APPSPAWN_CHECK(findFdIndex < recvCtx.fdCount && recvCtx.fds[findFdIndex] > 0,
7169570cc8Sopenharmony_ci                return -1, "invalid fd info  %{public}d %{public}d", findFdIndex, recvCtx.fds[findFdIndex]);
7269570cc8Sopenharmony_ci            fdMap[key] = recvCtx.fds[findFdIndex++];
7369570cc8Sopenharmony_ci            if (findFdIndex >= recvCtx.fdCount) {
7469570cc8Sopenharmony_ci                break;
7569570cc8Sopenharmony_ci            }
7669570cc8Sopenharmony_ci        }
7769570cc8Sopenharmony_ci    }
7869570cc8Sopenharmony_ci    return 0;
7969570cc8Sopenharmony_ci}
8069570cc8Sopenharmony_ci
8169570cc8Sopenharmony_cistatic int RunChildThread(const AppSpawnMgr *content, const AppSpawningCtx *property)
8269570cc8Sopenharmony_ci{
8369570cc8Sopenharmony_ci    std::string checkExit;
8469570cc8Sopenharmony_ci    if (OHOS::system::GetBoolParameter("persist.init.debug.checkexit", true)) {
8569570cc8Sopenharmony_ci        checkExit = std::to_string(getpid());
8669570cc8Sopenharmony_ci    }
8769570cc8Sopenharmony_ci    setenv(APPSPAWN_CHECK_EXIT, checkExit.c_str(), true);
8869570cc8Sopenharmony_ci    if (CheckAppMsgFlagsSet(property, APP_FLAGS_CHILDPROCESS)) {
8969570cc8Sopenharmony_ci        std::map<std::string, int> fdMap;
9069570cc8Sopenharmony_ci        BuildFdInfoMap(property->message, fdMap, IsColdRunMode(content));
9169570cc8Sopenharmony_ci        AppSpawnEnvClear((AppSpawnContent *)&content->content, (AppSpawnClient *)&property->client);
9269570cc8Sopenharmony_ci        OHOS::AppExecFwk::MainThread::StartChild(fdMap);
9369570cc8Sopenharmony_ci    } else {
9469570cc8Sopenharmony_ci        AppSpawnEnvClear((AppSpawnContent *)&content->content, (AppSpawnClient *)&property->client);
9569570cc8Sopenharmony_ci        OHOS::AppExecFwk::MainThread::Start();
9669570cc8Sopenharmony_ci    }
9769570cc8Sopenharmony_ci    unsetenv(APPSPAWN_CHECK_EXIT);
9869570cc8Sopenharmony_ci    return 0;
9969570cc8Sopenharmony_ci}
10069570cc8Sopenharmony_ci
10169570cc8Sopenharmony_cistatic int RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client)
10269570cc8Sopenharmony_ci{
10369570cc8Sopenharmony_ci    APPSPAWN_CHECK(client != NULL && content != NULL, return -1, "Invalid client");
10469570cc8Sopenharmony_ci    AppSpawningCtx *property = reinterpret_cast<AppSpawningCtx *>(client);
10569570cc8Sopenharmony_ci
10669570cc8Sopenharmony_ci    return RunChildThread(reinterpret_cast<AppSpawnMgr *>(content), property);
10769570cc8Sopenharmony_ci}
10869570cc8Sopenharmony_ci
10969570cc8Sopenharmony_ciAPPSPAWN_STATIC int PreLoadNativeSpawn(AppSpawnMgr *content)
11069570cc8Sopenharmony_ci{
11169570cc8Sopenharmony_ci    content->content.mode = MODE_FOR_NATIVE_SPAWN;
11269570cc8Sopenharmony_ci    RegChildLooper(&content->content, RunChildProcessor);
11369570cc8Sopenharmony_ci    return 0;
11469570cc8Sopenharmony_ci}
11569570cc8Sopenharmony_ci
11669570cc8Sopenharmony_ciMODULE_CONSTRUCTOR(void)
11769570cc8Sopenharmony_ci{
11869570cc8Sopenharmony_ci    APPSPAWN_LOGV("Load native module ...");
11969570cc8Sopenharmony_ci    AddPreloadHook(HOOK_PRIO_HIGHEST, PreLoadNativeSpawn);
12069570cc8Sopenharmony_ci}