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 #ifndef APPSPAWN_MANAGER_H
17 #define APPSPAWN_MANAGER_H
18
19 #include <limits.h>
20 #include <stdbool.h>
21 #include <unistd.h>
22
23 #include "appspawn.h"
24 #include "appspawn_hook.h"
25 #include "appspawn_msg.h"
26 #include "appspawn_server.h"
27 #include "appspawn_utils.h"
28 #include "list.h"
29 #include "loop_event.h"
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 #define MODE_ID_INDEX 1
36 #define MODE_VALUE_INDEX 2
37 #define FD_ID_INDEX 3
38 #define FD_VALUE_INDEX 4
39 #define FLAGS_VALUE_INDEX 5
40 #define SHM_SIZE_INDEX 6
41 #define PARAM_ID_INDEX 7
42 #define PARAM_VALUE_INDEX 8
43 #define CLIENT_ID_INDEX 9
44 #define ARG_NULL 10
45
46 #define MAX_DIED_PROCESS_COUNT 5
47
48 #define INVALID_OFFSET 0xffffffff
49
50 #define APP_STATE_IDLE 1
51 #define APP_STATE_SPAWNING 2
52 #define APPSPAWN_MAX_TIME 3000000
53
54 #define APPSPAWN_INLINE __attribute__((always_inline)) inline
55
56 typedef struct AppSpawnContent AppSpawnContent;
57 typedef struct AppSpawnClient AppSpawnClient;
58 typedef struct TagAppSpawnConnection AppSpawnConnection;
59
60 typedef struct TagAppSpawnMsgNode {
61 AppSpawnConnection *connection;
62 AppSpawnMsg msgHeader;
63 uint32_t tlvCount;
64 uint32_t *tlvOffset; // 记录属性的在msg中的偏移,不完全拷贝试消息完整
65 uint8_t *buffer;
66 } AppSpawnMsgNode;
67
68 typedef struct {
69 int32_t fd[2]; // 2 fd count
70 WatcherHandle watcherHandle;
71 WatcherHandle pidFdWatcherHandle;
72 TimerHandle timer;
73 char *childMsg;
74 uint32_t msgSize;
75 char *coldRunPath;
76 } AppSpawnForkCtx;
77
78 typedef struct TagAppSpawningCtx {
79 AppSpawnClient client;
80 struct ListNode node;
81 AppSpawnForkCtx forkCtx;
82 AppSpawnMsgNode *message;
83 bool isPrefork;
84 pid_t pid;
85 int state;
86 struct timespec spawnStart;
87 } AppSpawningCtx;
88
89 typedef struct TagAppSpawnedProcess {
90 struct ListNode node;
91 uid_t uid;
92 pid_t pid;
93 uint32_t max;
94 int exitStatus;
95 struct timespec spawnStart;
96 struct timespec spawnEnd;
97 #ifdef DEBUG_BEGETCTL_BOOT
98 AppSpawnMsgNode *message;
99 #endif
100 bool isDebuggable;
101 char name[0];
102 } AppSpawnedProcess;
103
104 typedef struct SpawnTime {
105 int minAppspawnTime;
106 int maxAppspawnTime;
107 } SpawnTime;
108
109 typedef struct TagAppSpawnMgr {
110 AppSpawnContent content;
111 TaskHandle server;
112 SignalHandle sigHandler;
113 pid_t servicePid;
114 struct ListNode appQueue; // save app pid and name
115 uint32_t diedAppCount;
116 uint32_t flags;
117 struct ListNode diedQueue; // save app pid and name
118 struct ListNode appSpawnQueue; // save app pid and name
119 struct timespec perLoadStart;
120 struct timespec perLoadEnd;
121 struct ListNode extData;
122 struct SpawnTime spawnTime;
123 } AppSpawnMgr;
124
125 /**
126 * @brief App Spawn Mgr object op
127 *
128 */
129 AppSpawnMgr *CreateAppSpawnMgr(int mode);
130 AppSpawnMgr *GetAppSpawnMgr(void);
131 void DeleteAppSpawnMgr(AppSpawnMgr *mgr);
132 AppSpawnContent *GetAppSpawnContent(void);
133
134 /**
135 * @brief 孵化成功后进程或者app实例的操作
136 *
137 */
138 typedef void (*AppTraversal)(const AppSpawnMgr *mgr, AppSpawnedProcess *appInfo, void *data);
139 void TraversalSpawnedProcess(AppTraversal traversal, void *data);
140 AppSpawnedProcess *AddSpawnedProcess(pid_t pid, const char *processName, bool isDebuggable);
141 AppSpawnedProcess *GetSpawnedProcess(pid_t pid);
142 AppSpawnedProcess *GetSpawnedProcessByName(const char *name);
143 void TerminateSpawnedProcess(AppSpawnedProcess *node);
144
145 /**
146 * @brief 孵化过程中的ctx对象的操作
147 *
148 */
149 typedef void (*ProcessTraversal)(const AppSpawnMgr *mgr, AppSpawningCtx *ctx, void *data);
150 void AppSpawningCtxTraversal(ProcessTraversal traversal, void *data);
151 AppSpawningCtx *GetAppSpawningCtxByPid(pid_t pid);
152 AppSpawningCtx *CreateAppSpawningCtx();
153 void DeleteAppSpawningCtx(AppSpawningCtx *property);
154 int KillAndWaitStatus(pid_t pid, int sig, int *exitStatus);
155
156 /**
157 * @brief 消息解析、处理
158 *
159 */
160 void ProcessAppSpawnDumpMsg(const AppSpawnMsgNode *message);
161 int ProcessTerminationStatusMsg(const AppSpawnMsgNode *message, AppSpawnResult *result);
162
163 AppSpawnMsgNode *CreateAppSpawnMsg(void);
164 void DeleteAppSpawnMsg(AppSpawnMsgNode *msgNode);
165 int CheckAppSpawnMsg(const AppSpawnMsgNode *message);
166 int DecodeAppSpawnMsg(AppSpawnMsgNode *message);
167 int GetAppSpawnMsgFromBuffer(const uint8_t *buffer, uint32_t bufferLen,
168 AppSpawnMsgNode **outMsg, uint32_t *msgRecvLen, uint32_t *reminder);
169 AppSpawnMsgNode *RebuildAppSpawnMsgNode(AppSpawnMsgNode *message, AppSpawnedProcess *appInfo);
170
171 /**
172 * @brief 消息内容操作接口
173 *
174 */
175 void DumpAppSpawnMsg(const AppSpawnMsgNode *message);
176 void *GetAppSpawnMsgInfo(const AppSpawnMsgNode *message, int type);
177 void *GetAppSpawnMsgExtInfo(const AppSpawnMsgNode *message, const char *name, uint32_t *len);
178 int CheckAppSpawnMsgFlag(const AppSpawnMsgNode *message, uint32_t type, uint32_t index);
179 int SetAppSpawnMsgFlag(const AppSpawnMsgNode *message, uint32_t type, uint32_t index);
180
IsSpawnServer(const AppSpawnMgr * content)181 APPSPAWN_INLINE int IsSpawnServer(const AppSpawnMgr *content)
182 {
183 return (content != NULL) && (content->servicePid == getpid());
184 }
185
IsAppSpawnMode(const AppSpawnMgr * content)186 APPSPAWN_INLINE int IsAppSpawnMode(const AppSpawnMgr *content)
187 {
188 return (content != NULL) &&
189 (content->content.mode == MODE_FOR_APP_SPAWN || content->content.mode == MODE_FOR_APP_COLD_RUN);
190 }
191
IsNWebSpawnMode(const AppSpawnMgr * content)192 APPSPAWN_INLINE int IsNWebSpawnMode(const AppSpawnMgr *content)
193 {
194 return (content != NULL) &&
195 (content->content.mode == MODE_FOR_NWEB_SPAWN || content->content.mode == MODE_FOR_NWEB_COLD_RUN);
196 }
197
IsColdRunMode(const AppSpawnMgr * content)198 APPSPAWN_INLINE int IsColdRunMode(const AppSpawnMgr *content)
199 {
200 return (content != NULL) &&
201 (content->content.mode == MODE_FOR_APP_COLD_RUN || content->content.mode == MODE_FOR_NWEB_COLD_RUN);
202 }
203
IsDeveloperModeOn(const AppSpawningCtx * property)204 APPSPAWN_INLINE int IsDeveloperModeOn(const AppSpawningCtx *property)
205 {
206 return (property != NULL && ((property->client.flags & APP_DEVELOPER_MODE) == APP_DEVELOPER_MODE));
207 }
208
IsJitFortModeOn(const AppSpawningCtx * property)209 APPSPAWN_INLINE int IsJitFortModeOn(const AppSpawningCtx *property)
210 {
211 return (property != NULL && ((property->client.flags & APP_JITFORT_MODE) == APP_JITFORT_MODE));
212 }
213
GetAppSpawnMsgType(const AppSpawningCtx * appProperty)214 APPSPAWN_INLINE int GetAppSpawnMsgType(const AppSpawningCtx *appProperty)
215 {
216 return (appProperty != NULL && appProperty->message != NULL) ?
217 appProperty->message->msgHeader.msgType : MAX_TYPE_INVALID;
218 }
219
GetProcessName(const AppSpawningCtx * property)220 APPSPAWN_INLINE const char *GetProcessName(const AppSpawningCtx *property)
221 {
222 if (property == NULL || property->message == NULL) {
223 return NULL;
224 }
225 return property->message->msgHeader.processName;
226 }
227
GetBundleName(const AppSpawningCtx * property)228 APPSPAWN_INLINE const char *GetBundleName(const AppSpawningCtx *property)
229 {
230 if (property == NULL || property->message == NULL) {
231 return NULL;
232 }
233 AppSpawnMsgBundleInfo *info = (AppSpawnMsgBundleInfo *)GetAppSpawnMsgInfo(property->message, TLV_BUNDLE_INFO);
234 if (info != NULL) {
235 return info->bundleName;
236 }
237 return NULL;
238 }
239
GetAppProperty(const AppSpawningCtx * property,uint32_t type)240 APPSPAWN_INLINE void *GetAppProperty(const AppSpawningCtx *property, uint32_t type)
241 {
242 APPSPAWN_CHECK(property != NULL && property->message != NULL,
243 return NULL, "Invalid property for type %{public}u", type);
244 return GetAppSpawnMsgInfo(property->message, type);
245 }
246
GetAppPropertyExt(const AppSpawningCtx * property,const char * name,uint32_t * len)247 APPSPAWN_INLINE void *GetAppPropertyExt(const AppSpawningCtx *property, const char *name, uint32_t *len)
248 {
249 APPSPAWN_CHECK(name != NULL, return NULL, "Invalid name ");
250 APPSPAWN_CHECK(property != NULL && property->message != NULL,
251 return NULL, "Invalid property for name %{public}s", name);
252 return GetAppSpawnMsgExtInfo(property->message, name, len);
253 }
254
CheckAppMsgFlagsSet(const AppSpawningCtx * property,uint32_t index)255 APPSPAWN_INLINE int CheckAppMsgFlagsSet(const AppSpawningCtx *property, uint32_t index)
256 {
257 APPSPAWN_CHECK(property != NULL && property->message != NULL,
258 return 0, "Invalid property for name %{public}u", TLV_MSG_FLAGS);
259 return CheckAppSpawnMsgFlag(property->message, TLV_MSG_FLAGS, index);
260 }
261
CheckAppPermissionFlagSet(const AppSpawningCtx * property,uint32_t index)262 APPSPAWN_INLINE int CheckAppPermissionFlagSet(const AppSpawningCtx *property, uint32_t index)
263 {
264 APPSPAWN_CHECK(property != NULL && property->message != NULL,
265 return 0, "Invalid property for name %{public}u", TLV_PERMISSION);
266 return CheckAppSpawnMsgFlag(property->message, TLV_PERMISSION, index);
267 }
268
SetAppPermissionFlags(const AppSpawningCtx * property,uint32_t index)269 APPSPAWN_INLINE int SetAppPermissionFlags(const AppSpawningCtx *property, uint32_t index)
270 {
271 APPSPAWN_CHECK(property != NULL && property->message != NULL,
272 return -1, "Invalid property for name %{public}u", TLV_PERMISSION);
273 return SetAppSpawnMsgFlag(property->message, TLV_PERMISSION, index);
274 }
275
IsIsolatedNativeSpawnMode(const AppSpawnMgr * content,const AppSpawningCtx * property)276 APPSPAWN_INLINE int IsIsolatedNativeSpawnMode(const AppSpawnMgr *content, const AppSpawningCtx *property)
277 {
278 return (content != NULL) && (content->content.mode == MODE_FOR_NATIVE_SPAWN) &&
279 CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE);
280 }
281
282 #ifdef __cplusplus
283 }
284 #endif
285 #endif // APPSPAWN_MANAGER_H
286