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 <cerrno> 17#include <cstring> 18#include <dlfcn.h> 19#include <set> 20#include <string> 21#include <unistd.h> 22#include <utility> 23#include <vector> 24 25#include "appspawn_hook.h" 26#include "appspawn_server.h" 27#include "appspawn_service.h" 28#include "appspawn_manager.h" 29#include "appspawn_utils.h" 30#include "parameters.h" 31#ifndef APPSPAWN_TEST 32#include "main_thread.h" 33#endif 34 35APPSPAWN_STATIC int BuildFdInfoMap(const AppSpawnMsgNode *message, std::map<std::string, int> &fdMap, int isColdRun) 36{ 37 APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL, return -1); 38 APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset != NULL, return -1); 39 int findFdIndex = 0; 40 AppSpawnMsgReceiverCtx recvCtx; 41 if (!isColdRun) { 42 APPSPAWN_CHECK_ONLY_EXPER(message->connection != NULL, return -1); 43 recvCtx = message->connection->receiverCtx; 44 if (recvCtx.fdCount <= 0) { 45 APPSPAWN_LOGI("no need to build fd info %{public}d, %{public}d", recvCtx.fds != NULL, recvCtx.fdCount); 46 return 0; 47 } 48 } 49 for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) { 50 if (message->tlvOffset[index] == INVALID_OFFSET) { 51 return -1; 52 } 53 uint8_t *data = message->buffer + message->tlvOffset[index]; 54 if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) { 55 continue; 56 } 57 AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data; 58 if (strcmp(tlv->tlvName, MSG_EXT_NAME_APP_FD) != 0) { 59 continue; 60 } 61 std::string key((char *)data + sizeof(AppSpawnTlvExt)); 62 if (isColdRun) { 63 std::string envKey = std::string(APP_FDENV_PREFIX) + key; 64 char *fdChar = getenv(envKey.c_str()); 65 APPSPAWN_CHECK(fdChar != NULL, continue, "getfd from env failed %{public}s", envKey.c_str()); 66 int fd = atoi(fdChar); 67 APPSPAWN_CHECK(fd > 0, continue, "getfd from env atoi errno %{public}s,%{public}d", envKey.c_str(), fd); 68 fdMap[key] = fd; 69 } else { 70 APPSPAWN_CHECK(findFdIndex < recvCtx.fdCount && recvCtx.fds[findFdIndex] > 0, 71 return -1, "invalid fd info %{public}d %{public}d", findFdIndex, recvCtx.fds[findFdIndex]); 72 fdMap[key] = recvCtx.fds[findFdIndex++]; 73 if (findFdIndex >= recvCtx.fdCount) { 74 break; 75 } 76 } 77 } 78 return 0; 79} 80 81static int RunChildThread(const AppSpawnMgr *content, const AppSpawningCtx *property) 82{ 83 std::string checkExit; 84 if (OHOS::system::GetBoolParameter("persist.init.debug.checkexit", true)) { 85 checkExit = std::to_string(getpid()); 86 } 87 setenv(APPSPAWN_CHECK_EXIT, checkExit.c_str(), true); 88 if (CheckAppMsgFlagsSet(property, APP_FLAGS_CHILDPROCESS)) { 89 std::map<std::string, int> fdMap; 90 BuildFdInfoMap(property->message, fdMap, IsColdRunMode(content)); 91 AppSpawnEnvClear((AppSpawnContent *)&content->content, (AppSpawnClient *)&property->client); 92 OHOS::AppExecFwk::MainThread::StartChild(fdMap); 93 } else { 94 AppSpawnEnvClear((AppSpawnContent *)&content->content, (AppSpawnClient *)&property->client); 95 OHOS::AppExecFwk::MainThread::Start(); 96 } 97 unsetenv(APPSPAWN_CHECK_EXIT); 98 return 0; 99} 100 101static int RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) 102{ 103 APPSPAWN_CHECK(client != NULL && content != NULL, return -1, "Invalid client"); 104 AppSpawningCtx *property = reinterpret_cast<AppSpawningCtx *>(client); 105 106 return RunChildThread(reinterpret_cast<AppSpawnMgr *>(content), property); 107} 108 109APPSPAWN_STATIC int PreLoadNativeSpawn(AppSpawnMgr *content) 110{ 111 content->content.mode = MODE_FOR_NATIVE_SPAWN; 112 RegChildLooper(&content->content, RunChildProcessor); 113 return 0; 114} 115 116MODULE_CONSTRUCTOR(void) 117{ 118 APPSPAWN_LOGV("Load native module ..."); 119 AddPreloadHook(HOOK_PRIO_HIGHEST, PreLoadNativeSpawn); 120}