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
BuildFdInfoMap(const AppSpawnMsgNode * message,std::map<std::string,int> & fdMap,int isColdRun)35 APPSPAWN_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
RunChildThread(const AppSpawnMgr * content,const AppSpawningCtx * property)81 static 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
RunChildProcessor(AppSpawnContent * content,AppSpawnClient * client)101 static 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
PreLoadNativeSpawn(AppSpawnMgr * content)109 APPSPAWN_STATIC int PreLoadNativeSpawn(AppSpawnMgr *content)
110 {
111 content->content.mode = MODE_FOR_NATIVE_SPAWN;
112 RegChildLooper(&content->content, RunChildProcessor);
113 return 0;
114 }
115
MODULE_CONSTRUCTOR(void)116 MODULE_CONSTRUCTOR(void)
117 {
118 APPSPAWN_LOGV("Load native module ...");
119 AddPreloadHook(HOOK_PRIO_HIGHEST, PreLoadNativeSpawn);
120 }