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 "appspawn_service.h"
17
18 #include <dlfcn.h>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/signalfd.h>
25 #include <sys/socket.h>
26 #include <sys/wait.h>
27 #include <sys/mman.h>
28 #include <sys/syscall.h>
29 #include <signal.h>
30 #include <sys/mount.h>
31 #include <unistd.h>
32 #include <sys/prctl.h>
33 #include <sched.h>
34 #include "appspawn.h"
35 #include "appspawn_hook.h"
36 #include "appspawn_modulemgr.h"
37 #include "appspawn_manager.h"
38 #include "appspawn_msg.h"
39 #include "appspawn_server.h"
40 #include "appspawn_trace.h"
41 #include "appspawn_utils.h"
42 #include "init_socket.h"
43 #include "init_utils.h"
44 #include "parameter.h"
45 #include "appspawn_adapter.h"
46 #ifndef OHOS_LITE
47 #include "appspawn_reclaim.h"
48 #endif
49 #include "securec.h"
50 #include "cJSON.h"
51 #ifdef APPSPAWN_HISYSEVENT
52 #include "appspawn_hisysevent.h"
53 #include "hisysevent_adapter.h"
54 #endif
55 #define PARAM_BUFFER_SIZE 10
56 #define PATH_SIZE 256
57 #define FD_PATH_SIZE 128
58
59 #define PREFORK_PROCESS "apppool"
60 #define APPSPAWN_MSG_USER_CHECK_COUNT 4
61 #define USER_ID_MIN_VALUE 100
62 #define USER_ID_MAX_VALUE 10736
63 #define LOCK_STATUS_PARAM_SIZE 64
64 #ifndef PIDFD_NONBLOCK
65 #define PIDFD_NONBLOCK O_NONBLOCK
66 #endif
67
68 static void WaitChildTimeout(const TimerHandle taskHandle, void *context);
69 static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context);
70 static void WaitChildDied(pid_t pid);
71 static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen);
72 static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message);
73
74 // FD_CLOEXEC
SetFdCtrl(int fd,int opt)75 static inline void SetFdCtrl(int fd, int opt)
76 {
77 int option = fcntl(fd, F_GETFD);
78 APPSPAWN_CHECK(option >= 0, return, "SetFdCtrl fcntl failed %{public}d, %{public}d", option, errno);
79 int ret = fcntl(fd, F_SETFD, (unsigned int)option | (unsigned int)opt);
80 if (ret < 0) {
81 APPSPAWN_LOGI("Set fd %{public}d option %{public}d %{public}d result: %{public}d", fd, option, opt, errno);
82 }
83 }
84
AppQueueDestroyProc(const AppSpawnMgr * mgr,AppSpawnedProcess * appInfo,void * data)85 static void AppQueueDestroyProc(const AppSpawnMgr *mgr, AppSpawnedProcess *appInfo, void *data)
86 {
87 pid_t pid = appInfo->pid;
88 APPSPAWN_LOGI("kill %{public}s pid: %{public}d", appInfo->name, appInfo->pid);
89 // notify child proess died,clean sandbox info
90 ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo);
91 OH_ListRemove(&appInfo->node);
92 OH_ListInit(&appInfo->node);
93 free(appInfo);
94 if (pid > 0 && kill(pid, SIGKILL) != 0) {
95 APPSPAWN_LOGE("unable to kill process, pid: %{public}d errno: %{public}d", pid, errno);
96 }
97 }
98
StopAppSpawn(void)99 static void StopAppSpawn(void)
100 {
101 AppSpawnContent *content = GetAppSpawnContent();
102 if (content != NULL && content->reservedPid > 0) {
103 int ret = kill(content->reservedPid, SIGKILL);
104 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "kill reserved pid %{public}d failed %{public}d %{public}d",
105 content->reservedPid, ret, errno);
106 content->reservedPid = 0;
107 }
108 TraversalSpawnedProcess(AppQueueDestroyProc, NULL);
109 APPSPAWN_LOGI("StopAppSpawn ");
110 #ifdef APPSPAWN_HISYSEVENT
111 AppSpawnHiSysEventWrite();
112 #endif
113 LE_StopLoop(LE_GetDefaultLoop());
114 }
115
DumpStatus(const char * appName,pid_t pid,int status,int * signal)116 static inline void DumpStatus(const char *appName, pid_t pid, int status, int *signal)
117 {
118 if (WIFSIGNALED(status)) {
119 *signal = WTERMSIG(status);
120 APPSPAWN_LOGW("%{public}s with pid %{public}d exit with signal:%{public}d", appName, pid, *signal);
121 }
122 if (WIFEXITED(status)) {
123 *signal = WEXITSTATUS(status);
124 APPSPAWN_LOGW("%{public}s with pid %{public}d exit with code:%{public}d", appName, pid, *signal);
125 }
126 }
127
WriteSignalInfoToFd(AppSpawnedProcess * appInfo,AppSpawnContent * content,int signal)128 APPSPAWN_STATIC void WriteSignalInfoToFd(AppSpawnedProcess *appInfo, AppSpawnContent *content, int signal)
129 {
130 APPSPAWN_CHECK(content->signalFd > 0, return, "Invalid signal fd[%{public}d]", content->signalFd);
131 APPSPAWN_CHECK(appInfo->pid > 0, return, "Invalid pid[%{public}d]", appInfo->pid);
132 APPSPAWN_CHECK(appInfo->uid > 0, return, "Invalid uid[%{public}d]", appInfo->uid);
133 APPSPAWN_CHECK(appInfo->name != NULL, return, "Invalid name");
134
135 cJSON *root = cJSON_CreateObject();
136 if (root == NULL) {
137 APPSPAWN_LOGE("signal json write create root object unsuccess");
138 return;
139 }
140 cJSON_AddNumberToObject(root, "pid", appInfo->pid);
141 cJSON_AddNumberToObject(root, "uid", appInfo->uid);
142 cJSON_AddNumberToObject(root, "signal", signal);
143 cJSON_AddStringToObject(root, "bundleName", appInfo->name);
144 char *jsonString = cJSON_Print(root);
145 cJSON_Delete(root);
146 APPSPAWN_CHECK(jsonString != NULL, return, "jsonString is NULL");
147 int ret = write(content->signalFd, jsonString, strlen(jsonString) + 1);
148 if (ret < 0) {
149 free(jsonString);
150 APPSPAWN_LOGE("Spawn Listen failed to write signal info to fd errno %{public}d", errno);
151 return;
152 }
153 APPSPAWN_LOGV("Spawn Listen write signal info %{public}s to fd %{public}d success", jsonString, content->signalFd);
154 free(jsonString);
155 }
156
HandleDiedPid(pid_t pid,uid_t uid,int status)157 static void HandleDiedPid(pid_t pid, uid_t uid, int status)
158 {
159 AppSpawnContent *content = GetAppSpawnContent();
160 APPSPAWN_CHECK(content != NULL, return, "Invalid content");
161
162 if (pid == content->reservedPid) {
163 APPSPAWN_LOGW("HandleDiedPid with reservedPid %{public}d", pid);
164 content->reservedPid = 0;
165 }
166 int signal = 0;
167 AppSpawnedProcess *appInfo = GetSpawnedProcess(pid);
168 if (appInfo == NULL) { // If an exception occurs during app spawning, kill pid, return failed
169 WaitChildDied(pid);
170 DumpStatus("unknown", pid, status, &signal);
171 return;
172 }
173
174 appInfo->exitStatus = status;
175 APPSPAWN_CHECK_ONLY_LOG(appInfo->uid == uid, "Invalid uid %{public}u %{public}u", appInfo->uid, uid);
176 DumpStatus(appInfo->name, pid, status, &signal);
177 WriteSignalInfoToFd(appInfo, content, signal);
178 ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo);
179 ProcessMgrHookExecute(STAGE_SERVER_APP_UMOUNT, GetAppSpawnContent(), appInfo);
180
181 // move app info to died queue in NWEBSPAWN, or delete appinfo
182 TerminateSpawnedProcess(appInfo);
183 }
184
ProcessSignal(const struct signalfd_siginfo * siginfo)185 APPSPAWN_STATIC void ProcessSignal(const struct signalfd_siginfo *siginfo)
186 {
187 APPSPAWN_LOGI("ProcessSignal signum %{public}d %{public}d", siginfo->ssi_signo, siginfo->ssi_pid);
188 switch (siginfo->ssi_signo) {
189 case SIGCHLD: { // delete pid from app map
190 pid_t pid;
191 int status;
192 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
193 APPSPAWN_CHECK(WIFSIGNALED(status) || WIFEXITED(status), return,
194 "ProcessSignal with wrong status:%{public}d", status);
195 HandleDiedPid(pid, siginfo->ssi_uid, status);
196 }
197 #if (defined(CJAPP_SPAWN) || defined(NATIVE_SPAWN))
198 if (OH_ListGetCnt(&GetAppSpawnMgr()->appQueue) == 0) {
199 LE_StopLoop(LE_GetDefaultLoop());
200 }
201 #endif
202 break;
203 }
204 case SIGTERM: { // appswapn killed, use kill without parameter
205 StopAppSpawn();
206 break;
207 }
208 default:
209 APPSPAWN_LOGI("SigHandler, unsupported signal %{public}d.", siginfo->ssi_signo);
210 break;
211 }
212 }
213
AppSpawningCtxOnClose(const AppSpawnMgr * mgr,AppSpawningCtx * ctx,void * data)214 static void AppSpawningCtxOnClose(const AppSpawnMgr *mgr, AppSpawningCtx *ctx, void *data)
215 {
216 if (ctx == NULL || ctx->message == NULL || ctx->message->connection != data) {
217 return;
218 }
219 APPSPAWN_LOGI("Kill process, pid: %{public}d app: %{public}s", ctx->pid, GetProcessName(ctx));
220 if (ctx->pid > 0 && kill(ctx->pid, SIGKILL) != 0) {
221 APPSPAWN_LOGE("unable to kill process, pid: %{public}d errno: %{public}d", ctx->pid, errno);
222 }
223 DeleteAppSpawningCtx(ctx);
224 }
225
OnClose(const TaskHandle taskHandle)226 static void OnClose(const TaskHandle taskHandle)
227 {
228 if (!IsSpawnServer(GetAppSpawnMgr())) {
229 return;
230 }
231 AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle);
232 APPSPAWN_CHECK(connection != NULL, return, "Invalid connection");
233 if (connection->receiverCtx.timer) {
234 LE_StopTimer(LE_GetDefaultLoop(), connection->receiverCtx.timer);
235 connection->receiverCtx.timer = NULL;
236 }
237 APPSPAWN_LOGI("OnClose connectionId: %{public}u socket %{public}d",
238 connection->connectionId, LE_GetSocketFd(taskHandle));
239 DeleteAppSpawnMsg(&connection->receiverCtx.incompleteMsg);
240 connection->receiverCtx.incompleteMsg = NULL;
241 // connect close, to close spawning app
242 AppSpawningCtxTraversal(AppSpawningCtxOnClose, connection);
243 }
244
OnDisConnect(const TaskHandle taskHandle)245 static void OnDisConnect(const TaskHandle taskHandle)
246 {
247 AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle);
248 APPSPAWN_CHECK(connection != NULL, return, "Invalid connection");
249 APPSPAWN_LOGI("OnDisConnect connectionId: %{public}u socket %{public}d",
250 connection->connectionId, LE_GetSocketFd(taskHandle));
251 OnClose(taskHandle);
252 }
253
SendMessageComplete(const TaskHandle taskHandle,BufferHandle handle)254 static void SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle)
255 {
256 AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle);
257 APPSPAWN_CHECK(connection != NULL, return, "Invalid connection");
258 uint32_t bufferSize = sizeof(AppSpawnResponseMsg);
259 AppSpawnResponseMsg *msg = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, NULL, &bufferSize);
260 if (msg == NULL) {
261 return;
262 }
263 AppSpawnedProcess *appInfo = GetSpawnedProcess(msg->result.pid);
264 if (appInfo == NULL) {
265 return;
266 }
267 APPSPAWN_LOGI("SendMessageComplete connectionId: %{public}u result %{public}d app %{public}s pid %{public}d",
268 connection->connectionId, LE_GetSendResult(handle), appInfo->name, msg->result.pid);
269 if (LE_GetSendResult(handle) != 0 && msg->result.pid > 0) {
270 kill(msg->result.pid, SIGKILL);
271 }
272 }
273
SendResponse(const AppSpawnConnection * connection,const AppSpawnMsg * msg,int result,pid_t pid)274 static int SendResponse(const AppSpawnConnection *connection, const AppSpawnMsg *msg, int result, pid_t pid)
275 {
276 APPSPAWN_LOGV("SendResponse connectionId: %{public}u result: 0x%{public}x pid: %{public}d",
277 connection->connectionId, result, pid);
278 uint32_t bufferSize = sizeof(AppSpawnResponseMsg);
279 BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize);
280 AppSpawnResponseMsg *buffer = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, NULL, &bufferSize);
281 APPSPAWN_CHECK(buffer != NULL, return APPSPAWN_ERROR_UTILS_MEM_FAIL, "buffer is null");
282 int ret = memcpy_s(buffer, bufferSize, msg, sizeof(AppSpawnMsg));
283 APPSPAWN_CHECK(ret == 0, LE_FreeBuffer(LE_GetDefaultLoop(), NULL, handle);
284 return -1, "Failed to memcpy_s bufferSize");
285 buffer->result.result = result;
286 buffer->result.pid = pid;
287 return LE_Send(LE_GetDefaultLoop(), connection->stream, handle, bufferSize);
288 }
289
WaitMsgCompleteTimeOut(const TimerHandle taskHandle,void * context)290 static void WaitMsgCompleteTimeOut(const TimerHandle taskHandle, void *context)
291 {
292 AppSpawnConnection *connection = (AppSpawnConnection *)context;
293 APPSPAWN_LOGE("Long time no msg complete so close connectionId: %{public}u", connection->connectionId);
294 DeleteAppSpawnMsg(&connection->receiverCtx.incompleteMsg);
295 connection->receiverCtx.incompleteMsg = NULL;
296 LE_CloseStreamTask(LE_GetDefaultLoop(), connection->stream);
297 }
298
StartTimerForCheckMsg(AppSpawnConnection * connection)299 static inline int StartTimerForCheckMsg(AppSpawnConnection *connection)
300 {
301 if (connection->receiverCtx.timer != NULL) {
302 return 0;
303 }
304 int ret = LE_CreateTimer(LE_GetDefaultLoop(), &connection->receiverCtx.timer, WaitMsgCompleteTimeOut, connection);
305 if (ret == 0) {
306 ret = LE_StartTimer(LE_GetDefaultLoop(), connection->receiverCtx.timer, MAX_WAIT_MSG_COMPLETE, 1);
307 }
308 return ret;
309 }
310
HandleRecvMessage(const TaskHandle taskHandle,uint8_t * buffer,int bufferSize,int flags)311 static int HandleRecvMessage(const TaskHandle taskHandle, uint8_t * buffer, int bufferSize, int flags)
312 {
313 int socketFd = LE_GetSocketFd(taskHandle);
314 struct iovec iov = {
315 .iov_base = buffer,
316 .iov_len = bufferSize,
317 };
318 char ctrlBuffer[CMSG_SPACE(APP_MAX_FD_COUNT * sizeof(int))];
319 struct msghdr msg = {
320 .msg_iov = &iov,
321 .msg_iovlen = 1,
322 .msg_control = ctrlBuffer,
323 .msg_controllen = sizeof(ctrlBuffer),
324 };
325
326 AppSpawnConnection *connection = (AppSpawnConnection *) LE_GetUserData(taskHandle);
327 APPSPAWN_CHECK(connection != NULL, return -1, "Invalid connection");
328 errno = 0;
329 int recvLen = recvmsg(socketFd, &msg, flags);
330 APPSPAWN_CHECK_ONLY_LOG(errno == 0, "recvmsg with errno %{public}d", errno);
331 struct cmsghdr *cmsg = NULL;
332 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
333 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
334 int fdCount = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
335 int *fd = (int *) CMSG_DATA(cmsg);
336 APPSPAWN_CHECK(fdCount <= APP_MAX_FD_COUNT, return -1,
337 "failed to recv fd %{public}d %{public}d", connection->receiverCtx.fdCount, fdCount);
338 int ret = memcpy_s(connection->receiverCtx.fds,
339 fdCount * sizeof(int), fd, fdCount * sizeof(int));
340 APPSPAWN_CHECK(ret == 0, return -1, "memcpy_s fd ret %{public}d", ret);
341 connection->receiverCtx.fdCount = fdCount;
342 }
343 }
344
345 return recvLen;
346 }
347
OnConnectionUserCheck(uid_t uid)348 APPSPAWN_STATIC bool OnConnectionUserCheck(uid_t uid)
349 {
350 const uid_t uids[APPSPAWN_MSG_USER_CHECK_COUNT] = {
351 0, // root 0
352 3350, // app_fwk_update 3350
353 5523, // foundation 5523
354 1090, //storage_manager 1090
355 };
356
357 for (int i = 0; i < APPSPAWN_MSG_USER_CHECK_COUNT; i++) {
358 if (uid == uids[i]) {
359 return true;
360 }
361 }
362
363 // shell 2000
364 if (uid == 2000 && IsDeveloperModeOpen()) {
365 return true;
366 }
367
368 return false;
369 }
370
OnConnection(const LoopHandle loopHandle,const TaskHandle server)371 static int OnConnection(const LoopHandle loopHandle, const TaskHandle server)
372 {
373 APPSPAWN_CHECK(server != NULL && loopHandle != NULL, return -1, "Error server");
374 static uint32_t connectionId = 0;
375 TaskHandle stream;
376 LE_StreamInfo info = {};
377 info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
378 info.baseInfo.close = OnClose;
379 info.baseInfo.userDataSize = sizeof(AppSpawnConnection);
380 info.disConnectComplete = OnDisConnect;
381 info.sendMessageComplete = SendMessageComplete;
382 info.recvMessage = OnReceiveRequest;
383 info.handleRecvMsg = HandleRecvMessage;
384 LE_STATUS ret = LE_AcceptStreamClient(loopHandle, server, &stream, &info);
385 APPSPAWN_CHECK(ret == 0, return -1, "Failed to alloc stream");
386
387 AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(stream);
388 APPSPAWN_CHECK(connection != NULL, return -1, "Failed to alloc stream");
389 struct ucred cred = {-1, -1, -1};
390 socklen_t credSize = sizeof(struct ucred);
391 if ((getsockopt(LE_GetSocketFd(stream), SOL_SOCKET, SO_PEERCRED, &cred, &credSize) < 0) ||
392 !OnConnectionUserCheck(cred.uid)) {
393 APPSPAWN_LOGE("Invalid uid %{public}d from client", cred.uid);
394 LE_CloseStreamTask(LE_GetDefaultLoop(), stream);
395 return -1;
396 }
397 SetFdCtrl(LE_GetSocketFd(stream), FD_CLOEXEC);
398
399 connection->connectionId = ++connectionId;
400 connection->stream = stream;
401 connection->receiverCtx.fdCount = 0;
402 connection->receiverCtx.incompleteMsg = NULL;
403 connection->receiverCtx.timer = NULL;
404 connection->receiverCtx.msgRecvLen = 0;
405 connection->receiverCtx.nextMsgId = 1;
406 APPSPAWN_LOGI("OnConnection connectionId: %{public}u fd %{public}d ",
407 connection->connectionId, LE_GetSocketFd(stream));
408 return 0;
409 }
410
MsgDevicedebugCheck(TaskHandle stream,AppSpawnMsgNode * message)411 APPSPAWN_STATIC bool MsgDevicedebugCheck(TaskHandle stream, AppSpawnMsgNode *message)
412 {
413 struct ucred cred = {0, 0, 0};
414 socklen_t credSize = sizeof(cred);
415 if (getsockopt(LE_GetSocketFd(stream), SOL_SOCKET, SO_PEERCRED, &cred, &credSize) < 0) {
416 return false;
417 }
418
419 if (cred.uid != DecodeUid("shell")) {
420 return true;
421 }
422
423 AppSpawnMsg *msg = &message->msgHeader;
424 APPSPAWN_CHECK(msg->msgType == MSG_DEVICE_DEBUG, return false,
425 "appspawn devicedebug msg type is not devicedebug [%{public}d]", msg->msgType);
426
427 return true;
428 }
429
OnReceiveRequest(const TaskHandle taskHandle,const uint8_t * buffer,uint32_t buffLen)430 static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen)
431 {
432 AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle);
433 APPSPAWN_CHECK(connection != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
434 return, "Failed to get client form socket");
435 APPSPAWN_CHECK(buffLen < MAX_MSG_TOTAL_LENGTH, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
436 return, "Message too long %{public}u", buffLen);
437
438 uint32_t reminder = 0;
439 uint32_t currLen = 0;
440 AppSpawnMsgNode *message = connection->receiverCtx.incompleteMsg; // incomplete msg
441 connection->receiverCtx.incompleteMsg = NULL;
442 int ret = 0;
443 do {
444 APPSPAWN_LOGI("connectionId:%{public}u buffLen:%{public}d", connection->connectionId, buffLen - currLen);
445
446 ret = GetAppSpawnMsgFromBuffer(buffer + currLen, buffLen - currLen,
447 &message, &connection->receiverCtx.msgRecvLen, &reminder);
448 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
449
450 if (connection->receiverCtx.msgRecvLen != message->msgHeader.msgLen) { // recv complete msg
451 connection->receiverCtx.incompleteMsg = message;
452 message = NULL;
453 break;
454 }
455 connection->receiverCtx.msgRecvLen = 0;
456 if (connection->receiverCtx.timer) {
457 LE_StopTimer(LE_GetDefaultLoop(), connection->receiverCtx.timer);
458 connection->receiverCtx.timer = NULL;
459 }
460
461 APPSPAWN_CHECK_ONLY_EXPER(MsgDevicedebugCheck(connection->stream, message),
462 LE_CloseTask(LE_GetDefaultLoop(), taskHandle); return);
463
464 // decode msg
465 ret = DecodeAppSpawnMsg(message);
466 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
467 StartAppspawnTrace("ProcessRecvMsg");
468 (void)ProcessRecvMsg(connection, message);
469 FinishAppspawnTrace();
470 message = NULL;
471 currLen += buffLen - reminder;
472 } while (reminder > 0);
473
474 if (message) {
475 DeleteAppSpawnMsg(&message);
476 }
477 if (ret != 0) {
478 LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
479 return;
480 }
481 if (connection->receiverCtx.incompleteMsg != NULL) { // Start the detection timer
482 ret = StartTimerForCheckMsg(connection);
483 APPSPAWN_CHECK(ret == 0, LE_CloseStreamTask(LE_GetDefaultLoop(), taskHandle);
484 return, "Failed to create time for connection");
485 }
486 }
487
GetMapMem(uint32_t clientId,const char * processName,uint32_t size,bool readOnly,bool isNweb)488 static char *GetMapMem(uint32_t clientId, const char *processName, uint32_t size, bool readOnly, bool isNweb)
489 {
490 char path[PATH_MAX] = {};
491 int len = sprintf_s(path, sizeof(path), APPSPAWN_MSG_DIR "%s/%s_%u",
492 isNweb ? "nwebspawn" : "appspawn", processName, clientId);
493 APPSPAWN_CHECK(len > 0, return NULL, "Failed to format path %{public}s", processName);
494 APPSPAWN_LOGV("GetMapMem for child %{public}s memSize %{public}u", path, size);
495 int prot = PROT_READ;
496 int mode = O_RDONLY;
497 if (!readOnly) {
498 mode = O_CREAT | O_RDWR | O_TRUNC;
499 prot = PROT_READ | PROT_WRITE;
500 }
501 int fd = open(path, mode, S_IRWXU);
502 APPSPAWN_CHECK(fd >= 0, return NULL, "Failed to open errno %{public}d path %{public}s", errno, path);
503 if (!readOnly) {
504 ftruncate(fd, size);
505 }
506 void *areaAddr = (void *)mmap(NULL, size, prot, MAP_SHARED, fd, 0);
507 close(fd);
508 APPSPAWN_CHECK(areaAddr != MAP_FAILED && areaAddr != NULL,
509 return NULL, "Failed to map memory error %{public}d fileName %{public}s ", errno, path);
510 return (char *)areaAddr;
511 }
512
WriteMsgToChild(AppSpawningCtx * property,bool isNweb)513 APPSPAWN_STATIC int WriteMsgToChild(AppSpawningCtx *property, bool isNweb)
514 {
515 APPSPAWN_CHECK(property != NULL && property->message != NULL, return APPSPAWN_MSG_INVALID,
516 "Failed to WriteMsgToChild property invalid");
517 const uint32_t memSize = (property->message->msgHeader.msgLen / 4096 + 1) * 4096; // 4096 4K
518 char *buffer = GetMapMem(property->client.id, GetProcessName(property), memSize, false, isNweb);
519 APPSPAWN_CHECK(buffer != NULL, return APPSPAWN_SYSTEM_ERROR,
520 "Failed to map memory error %{public}d fileName %{public}s ", errno, GetProcessName(property));
521 // copy msg header
522 int ret = memcpy_s(buffer, memSize, &property->message->msgHeader, sizeof(AppSpawnMsg));
523 if (ret == 0) {
524 ret = memcpy_s((char *)buffer + sizeof(AppSpawnMsg), memSize - sizeof(AppSpawnMsg),
525 property->message->buffer, property->message->msgHeader.msgLen - sizeof(AppSpawnMsg));
526 }
527 if (ret != 0) {
528 APPSPAWN_LOGE("Failed to copy msg fileName %{public}s ", GetProcessName(property));
529 munmap((char *)buffer, memSize);
530 return APPSPAWN_SYSTEM_ERROR;
531 }
532 property->forkCtx.msgSize = memSize;
533 property->forkCtx.childMsg = buffer;
534 APPSPAWN_LOGV("Write msg to child: %{public}u success", property->client.id);
535 return 0;
536 }
537
InitForkContext(AppSpawningCtx * property)538 static int InitForkContext(AppSpawningCtx *property)
539 {
540 if (pipe(property->forkCtx.fd) == -1) {
541 APPSPAWN_LOGE("create pipe fail, errno: %{public}d", errno);
542 return errno;
543 }
544 int option = fcntl(property->forkCtx.fd[0], F_GETFD);
545 if (option > 0) {
546 (void)fcntl(property->forkCtx.fd[0], F_SETFD, (unsigned int)option | O_NONBLOCK);
547 }
548 return 0;
549 }
550
ClosePidfdWatcher(const TaskHandle taskHandle)551 static void ClosePidfdWatcher(const TaskHandle taskHandle)
552 {
553 int fd = LE_GetSocketFd(taskHandle);
554 if (fd >= 0) {
555 close(fd);
556 }
557 void *p = LE_GetUserData(taskHandle);
558 if (p != NULL) {
559 free(*(void **)p);
560 }
561 }
562
ProcessChildProcessFd(const WatcherHandle taskHandle,int fd,uint32_t * events,const void * context)563 static void ProcessChildProcessFd(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
564 {
565 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return);
566 pid_t pid = *(pid_t *)context;
567 APPSPAWN_LOGI("Clear process group with pid %{public}d, pidFd %{public}d", pid, fd);
568 AppSpawnedProcess *appInfo = GetSpawnedProcess(pid);
569 if (appInfo == NULL) {
570 APPSPAWN_LOGW("Cannot get app info by bundle name: %{public}d", pid);
571 return;
572 }
573 ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo);
574 LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
575 }
576
OpenPidFd(pid_t pid,unsigned int flags)577 static int OpenPidFd(pid_t pid, unsigned int flags)
578 {
579 return syscall(SYS_pidfd_open, pid, flags);
580 }
581
WatchChildProcessFd(AppSpawningCtx * property)582 static void WatchChildProcessFd(AppSpawningCtx *property)
583 {
584 if (property->pid <= 0) {
585 APPSPAWN_LOGW("Invalid child process pid, skip watch");
586 return;
587 }
588 if (IsNWebSpawnMode((AppSpawnMgr *)GetAppSpawnContent())) {
589 APPSPAWN_LOGV("Nwebspawn don't need add pidfd");
590 return;
591 }
592 AppSpawnedProcess *appInfo = GetSpawnedProcess(property->pid);
593 if (appInfo == NULL) {
594 APPSPAWN_LOGW("Cannot get app info of pid %{public}d", property->pid);
595 return;
596 }
597 int fd = OpenPidFd(property->pid, PIDFD_NONBLOCK); // PIDFD_NONBLOCK since Linux kernel 5.10
598 if (fd < 0) {
599 APPSPAWN_LOGW("Failed to open pid fd for app: %{public}s, err = %{public}d",
600 GetBundleName(property), errno);
601 return;
602 }
603 APPSPAWN_LOGI("watch app process pid %{public}d, pidFd %{public}d", property->pid, fd);
604 LE_WatchInfo watchInfo = {};
605 watchInfo.fd = fd;
606 watchInfo.flags = WATCHER_ONCE;
607 watchInfo.events = EVENT_READ;
608 watchInfo.close = ClosePidfdWatcher;
609 watchInfo.processEvent = ProcessChildProcessFd;
610
611 pid_t *appPid = (pid_t *)malloc(sizeof(pid_t));
612 APPSPAWN_CHECK_ONLY_EXPER(appPid != NULL, return);
613 *appPid = property->pid;
614 LE_STATUS status = LE_StartWatcher(LE_GetDefaultLoop(), &property->forkCtx.pidFdWatcherHandle, &watchInfo, appPid);
615 if (status != LE_SUCCESS) {
616 #ifndef APPSPAWN_TEST
617 close(fd);
618 #endif
619 APPSPAWN_LOGW("Failed to watch child pid fd, pid is %{public}d", property->pid);
620 }
621 }
622
IsChildColdRun(AppSpawningCtx * property)623 static int IsChildColdRun(AppSpawningCtx *property)
624 {
625 return CheckAppMsgFlagsSet(property, APP_FLAGS_UBSAN_ENABLED)
626 || CheckAppMsgFlagsSet(property, APP_FLAGS_ASANENABLED)
627 || CheckAppMsgFlagsSet(property, APP_FLAGS_TSAN_ENABLED)
628 || CheckAppMsgFlagsSet(property, APP_FLAGS_HWASAN_ENABLED)
629 || (property->client.flags & APP_COLD_START);
630 }
631
AddChildWatcher(AppSpawningCtx * property)632 static int AddChildWatcher(AppSpawningCtx *property)
633 {
634 uint32_t defTimeout = IsChildColdRun(property) ? COLD_CHILD_RESPONSE_TIMEOUT : WAIT_CHILD_RESPONSE_TIMEOUT;
635 uint32_t timeout = GetSpawnTimeout(defTimeout);
636
637 LE_WatchInfo watchInfo = {};
638 watchInfo.fd = property->forkCtx.fd[0];
639 watchInfo.flags = WATCHER_ONCE;
640 watchInfo.events = EVENT_READ;
641 watchInfo.processEvent = ProcessChildResponse;
642 LE_STATUS status = LE_StartWatcher(LE_GetDefaultLoop(), &property->forkCtx.watcherHandle, &watchInfo, property);
643 APPSPAWN_LOGV("AddChildWatcher with timeout %{public}u fd %{public}d", timeout, watchInfo.fd);
644 APPSPAWN_CHECK(status == LE_SUCCESS,
645 return APPSPAWN_SYSTEM_ERROR, "Failed to watch child %{public}d", property->pid);
646 status = LE_CreateTimer(LE_GetDefaultLoop(), &property->forkCtx.timer, WaitChildTimeout, property);
647 if (status == LE_SUCCESS) {
648 status = LE_StartTimer(LE_GetDefaultLoop(), property->forkCtx.timer, timeout * 1000, 0); // 1000 1s
649 }
650 if (status != LE_SUCCESS) {
651 if (property->forkCtx.timer != NULL) {
652 LE_StopTimer(LE_GetDefaultLoop(), property->forkCtx.timer);
653 }
654 property->forkCtx.timer = NULL;
655 LE_RemoveWatcher(LE_GetDefaultLoop(), property->forkCtx.watcherHandle);
656 property->forkCtx.watcherHandle = NULL;
657 APPSPAWN_LOGE("Failed to watch child %{public}d", property->pid);
658 return APPSPAWN_SYSTEM_ERROR;
659 }
660 return 0;
661 }
662
IsSupportRunHnp()663 static bool IsSupportRunHnp()
664 {
665 char buffer[PARAM_BUFFER_SIZE] = {0};
666 int ret = GetParameter("const.startup.hnp.execute.enable", "false", buffer, PARAM_BUFFER_SIZE);
667 if (ret <= 0) {
668 APPSPAWN_LOGE("Get hnp execute enable param unsuccess! ret =%{public}d", ret);
669 return false;
670 }
671
672 if (strcmp(buffer, "true") == 0) {
673 return true;
674 }
675
676 return false;
677 }
678
ClearMMAP(int clientId,uint32_t memSize)679 static void ClearMMAP(int clientId, uint32_t memSize)
680 {
681 char path[PATH_MAX] = {0};
682 int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, APPSPAWN_MSG_DIR "appspawn/prefork_%d", clientId);
683 APPSPAWN_CHECK_ONLY_LOG(ret > 0, "snprintf failed with %{public}d %{public}d", ret, errno);
684 if (ret > 0 && access(path, F_OK) == 0) {
685 ret = unlink(path);
686 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "prefork unlink result %{public}d %{public}d", ret, errno);
687 }
688
689 AppSpawnContent *content = GetAppSpawnContent();
690 if (content != NULL && content->propertyBuffer != NULL) {
691 ret = munmap(content->propertyBuffer, memSize);
692 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "munmap failed %{public}d %{public}d", ret, errno);
693 content->propertyBuffer = NULL;
694 }
695 }
696
WritePreforkMsg(AppSpawningCtx * property,uint32_t memSize)697 static int WritePreforkMsg(AppSpawningCtx *property, uint32_t memSize)
698 {
699 AppSpawnContent *content = GetAppSpawnContent();
700 if (content == NULL || content->propertyBuffer == NULL) {
701 APPSPAWN_LOGE("buffer is null can not write propery");
702 return -1;
703 }
704
705 int ret = memcpy_s(content->propertyBuffer, memSize, &property->message->msgHeader, sizeof(AppSpawnMsg));
706 if (ret != 0) {
707 APPSPAWN_LOGE("memcpys_s msgHeader failed");
708 ClearMMAP(property->client.id, memSize);
709 return ret;
710 }
711
712 ret = memcpy_s((char *)content->propertyBuffer + sizeof(AppSpawnMsg), memSize - sizeof(AppSpawnMsg),
713 property->message->buffer, property->message->msgHeader.msgLen - sizeof(AppSpawnMsg));
714 if (ret != 0) {
715 APPSPAWN_LOGE("memcpys_s AppSpawnMsg failed");
716 ClearMMAP(property->client.id, memSize);
717 return ret;
718 }
719 ret = munmap((char *)content->propertyBuffer, memSize);
720 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "munmap failed %{public}d,%{public}d", ret, errno);
721 content->propertyBuffer = NULL;
722 return ret;
723 }
724
GetAppSpawnMsg(AppSpawningCtx * property,uint32_t memSize)725 static int GetAppSpawnMsg(AppSpawningCtx *property, uint32_t memSize)
726 {
727 uint8_t *buffer = (uint8_t *)GetMapMem(property->client.id, "prefork", memSize, true, false);
728 APPSPAWN_CHECK(buffer != NULL, return -1, "prefork buffer is null can not write propery");
729
730 uint32_t msgRecvLen = 0;
731 uint32_t remainLen = 0;
732 property->forkCtx.childMsg = (char *)buffer;
733 property->forkCtx.msgSize = memSize;
734 AppSpawnMsgNode *message = NULL;
735 int ret = GetAppSpawnMsgFromBuffer(buffer, ((AppSpawnMsg *)buffer)->msgLen, &message, &msgRecvLen, &remainLen);
736 // release map
737 APPSPAWN_LOGV("prefork GetAppSpawnMsg ret:%{public}d", ret);
738 if (ret == 0 && DecodeAppSpawnMsg(message) == 0 && CheckAppSpawnMsg(message) == 0) {
739 property->message = message;
740 message = NULL;
741 return 0;
742 }
743 DeleteAppSpawnMsg(&message);
744 return -1;
745 }
746
SetPreforkProcessName(AppSpawnContent * content)747 static int SetPreforkProcessName(AppSpawnContent *content)
748 {
749 int ret = prctl(PR_SET_NAME, PREFORK_PROCESS);
750 if (ret == -1) {
751 return errno;
752 }
753
754 ret = memset_s(content->longProcName,
755 (size_t)content->longProcNameLen, 0, (size_t)content->longProcNameLen);
756 if (ret != EOK) {
757 return EINVAL;
758 }
759
760 ret = strncpy_s(content->longProcName, content->longProcNameLen,
761 PREFORK_PROCESS, strlen(PREFORK_PROCESS));
762 if (ret != EOK) {
763 return EINVAL;
764 }
765
766 return 0;
767 }
768
ClearPipeFd(int pipe[],int length)769 static void ClearPipeFd(int pipe[], int length)
770 {
771 for (int i = 0; i < length; i++) {
772 if (pipe[i] > 0) {
773 close(pipe[i]);
774 pipe[i] = -1;
775 }
776 }
777 }
778
ProcessPreFork(AppSpawnContent * content,AppSpawningCtx * property)779 static void ProcessPreFork(AppSpawnContent *content, AppSpawningCtx *property)
780 {
781 APPSPAWN_CHECK(pipe(content->preforkFd) == 0, return, "prefork with prefork pipe failed %{public}d", errno);
782 ClearPipeFd(content->parentToChildFd, PIPE_FD_LENGTH);
783 APPSPAWN_LOGV("clear pipe fd finish %{public}d %{public}d",
784 content->parentToChildFd[0], content->parentToChildFd[1]);
785 APPSPAWN_CHECK(pipe(content->parentToChildFd) == 0, ClearPipeFd(content->preforkFd, PIPE_FD_LENGTH);
786 return, "prefork with prefork pipe failed %{public}d", errno);
787 enum fdsan_error_level errorLevel = fdsan_get_error_level();
788 StartAppspawnTrace("AppspawnPreFork");
789 content->reservedPid = fork();
790 APPSPAWN_LOGV("prefork fork finish %{public}d,%{public}d,%{public}d,%{public}d,%{public}d",
791 content->reservedPid, content->preforkFd[0], content->preforkFd[1], content->parentToChildFd[0],
792 content->parentToChildFd[1]);
793 if (content->reservedPid == 0) {
794 ClearPipeFd(property->forkCtx.fd, PIPE_FD_LENGTH);
795 int isRet = SetPreforkProcessName(content);
796 APPSPAWN_LOGV("prefork process start wait read msg with set processname %{public}d", isRet);
797 AppSpawnPreforkMsg preforkMsg = {0};
798 int infoSize = read(content->parentToChildFd[0], &preforkMsg, sizeof(AppSpawnPreforkMsg));
799 if (infoSize != sizeof(AppSpawnPreforkMsg) || preforkMsg.msgLen > MAX_MSG_TOTAL_LENGTH ||
800 preforkMsg.msgLen < sizeof(AppSpawnMsg)) {
801 APPSPAWN_LOGE("prefork process read msg failed %{public}d,%{public}d", infoSize, errno);
802 ProcessExit(0);
803 return;
804 }
805
806 property->client.id = preforkMsg.id;
807 property->client.flags = preforkMsg.flags;
808 property->isPrefork = true;
809 property->forkCtx.fd[0] = content->preforkFd[0];
810 property->forkCtx.fd[1] = content->preforkFd[1];
811 property->state = APP_STATE_SPAWNING;
812 const uint32_t memSize = (preforkMsg.msgLen / MAX_MSG_BLOCK_LEN + 1) * MAX_MSG_BLOCK_LEN;
813 if (GetAppSpawnMsg(property, memSize) == -1) {
814 APPSPAWN_LOGE("prefork child read GetAppSpawnMsg failed");
815 ClearMMAP(property->client.id, memSize);
816 content->notifyResToParent(content, &property->client, APPSPAWN_MSG_INVALID);
817 ProcessExit(0);
818 return;
819 }
820 ClearMMAP(property->client.id, memSize);
821 // Inherit the error level of the original process
822 (void)fdsan_set_error_level(errorLevel);
823 ProcessExit(AppSpawnChild(content, &property->client));
824 } else {
825 FinishAppspawnTrace();
826 if (content->reservedPid < 0) {
827 ClearPipeFd(content->preforkFd, PIPE_FD_LENGTH);
828 APPSPAWN_LOGE("prefork fork child process failed %{public}d, err %{public}d", content->reservedPid, errno);
829 }
830 }
831 }
832
NormalSpawnChild(AppSpawnContent * content,AppSpawnClient * client,pid_t * childPid)833 static int NormalSpawnChild(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid)
834 {
835 APPSPAWN_CHECK(client != NULL, return APPSPAWN_ARG_INVALID, "client is null");
836 int ret = InitForkContext((AppSpawningCtx *)client);
837 APPSPAWN_CHECK(ret == 0, return ret, "init fork context failed");
838 return AppSpawnProcessMsg(content, client, childPid);
839 }
840
AppSpawnProcessMsgForPrefork(AppSpawnContent * content,AppSpawnClient * client,pid_t * childPid)841 static int AppSpawnProcessMsgForPrefork(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid)
842 {
843 int ret = 0;
844 AppSpawningCtx *property = (AppSpawningCtx *)client;
845 if (content->reservedPid <= 0) {
846 ret = NormalSpawnChild(content, client, childPid);
847 } else {
848 const uint32_t memSize = (property->message->msgHeader.msgLen / MAX_MSG_BLOCK_LEN + 1) *
849 MAX_MSG_BLOCK_LEN;
850 content->propertyBuffer = GetMapMem(property->client.id, "prefork", memSize, false, false);
851 if (content->propertyBuffer == NULL) {
852 ClearMMAP(property->client.id, memSize);
853 return NormalSpawnChild(content, client, childPid);
854 }
855 ret = WritePreforkMsg(property, memSize);
856 if (ret != 0) {
857 ClearMMAP(property->client.id, memSize);
858 return NormalSpawnChild(content, client, childPid);
859 }
860 *childPid = content->reservedPid;
861 property->forkCtx.fd[0] = content->preforkFd[0];
862 property->forkCtx.fd[1] = content->preforkFd[1];
863 int option = fcntl(property->forkCtx.fd[0], F_GETFD);
864 if (option > 0) {
865 ret = fcntl(property->forkCtx.fd[0], F_SETFD, (unsigned int)option | O_NONBLOCK);
866 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "fcntl failed %{public}d,%{public}d", ret, errno);
867 }
868 AppSpawnPreforkMsg *preforkMsg = (AppSpawnPreforkMsg *)calloc(1, sizeof(AppSpawnPreforkMsg));
869 if (preforkMsg == NULL) {
870 APPSPAWN_LOGE("calloc failed");
871 ClearMMAP(property->client.id, memSize);
872 return NormalSpawnChild(content, client, childPid);
873 }
874
875 preforkMsg->id = client->id;
876 preforkMsg->flags = client->flags;
877 preforkMsg->msgLen = property->message->msgHeader.msgLen;
878 ssize_t writesize = write(content->parentToChildFd[1], preforkMsg, sizeof(AppSpawnPreforkMsg)) ;
879 APPSPAWN_CHECK(writesize == sizeof(AppSpawnPreforkMsg), kill(*childPid, SIGKILL);
880 *childPid = 0;
881 ret = -1,
882 "write msg to child failed %{public}d", errno);
883 free(preforkMsg);
884 }
885 ProcessPreFork(content, property);
886 return ret;
887 }
888
IsSupportPrefork(AppSpawnContent * content,AppSpawnClient * client)889 static bool IsSupportPrefork(AppSpawnContent *content, AppSpawnClient *client)
890 {
891 #ifdef APPSPAWN_SUPPORT_PREFORK
892 if (client == NULL || content == NULL) {
893 return false;
894 }
895 if (!content->enablePerfork) {
896 APPSPAWN_LOGV("g_enablePrefork %{public}d", content->enablePerfork);
897 return false;
898 }
899 AppSpawningCtx *property = (AppSpawningCtx *)client;
900
901 if (content->mode == MODE_FOR_APP_SPAWN && !IsChildColdRun(property)
902 && !CheckAppMsgFlagsSet(property, APP_FLAGS_CHILDPROCESS)) {
903 return true;
904 }
905 #endif
906 return false;
907 }
908
IsBootFinished(void)909 static bool IsBootFinished(void)
910 {
911 char buffer[32] = {0}; // 32 max
912 int ret = GetParameter("bootevent.boot.completed", "false", buffer, sizeof(buffer));
913 bool isBootCompleted = (ret > 0 && strcmp(buffer, "true") == 0);
914 return isBootCompleted;
915 }
916
917
RunAppSpawnProcessMsg(AppSpawnContent * content,AppSpawnClient * client,pid_t * childPid)918 static int RunAppSpawnProcessMsg(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid)
919 {
920 int ret = 0;
921
922 if (IsBootFinished() && IsSupportPrefork(content, client)) {
923 ret = AppSpawnProcessMsgForPrefork(content, client, childPid);
924 } else {
925 ret = NormalSpawnChild(content, client, childPid);
926 }
927 return ret;
928 }
929
ProcessSpawnReqMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)930 static void ProcessSpawnReqMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
931 {
932 int ret = CheckAppSpawnMsg(message);
933 if (ret != 0) {
934 SendResponse(connection, &message->msgHeader, ret, 0);
935 DeleteAppSpawnMsg(&message);
936 return;
937 }
938
939 if (IsDeveloperModeOpen()) {
940 if (IsSupportRunHnp()) {
941 SetAppSpawnMsgFlag(message, TLV_MSG_FLAGS, APP_FLAGS_DEVELOPER_MODE);
942 } else {
943 APPSPAWN_LOGV("Not support execute hnp file!");
944 }
945 }
946
947 AppSpawningCtx *property = CreateAppSpawningCtx();
948 if (property == NULL) {
949 SendResponse(connection, &message->msgHeader, APPSPAWN_SYSTEM_ERROR, 0);
950 DeleteAppSpawnMsg(&message);
951 return;
952 }
953
954 property->state = APP_STATE_SPAWNING;
955 property->message = message;
956 message->connection = connection;
957 // mount el2 dir
958 // getWrapBundleNameValue
959 AppSpawnHookExecute(STAGE_PARENT_PRE_FORK, 0, GetAppSpawnContent(), &property->client);
960 DumpAppSpawnMsg(property->message);
961
962 clock_gettime(CLOCK_MONOTONIC, &property->spawnStart);
963 ret = RunAppSpawnProcessMsg(GetAppSpawnContent(), &property->client, &property->pid);
964 AppSpawnHookExecute(STAGE_PARENT_POST_FORK, 0, GetAppSpawnContent(), &property->client);
965 if (ret != 0) { // wait child process result
966 SendResponse(connection, &message->msgHeader, ret, 0);
967 DeleteAppSpawningCtx(property);
968 return;
969 }
970 if (AddChildWatcher(property) != 0) { // wait child process result
971 kill(property->pid, SIGKILL);
972 SendResponse(connection, &message->msgHeader, ret, 0);
973 DeleteAppSpawningCtx(property);
974 return;
975 }
976 }
977
978 static uint32_t g_lastDiedAppId = 0;
979 static uint32_t g_crashTimes = 0;
980 #define MAX_CRASH_TIME 5
WaitChildDied(pid_t pid)981 static void WaitChildDied(pid_t pid)
982 {
983 AppSpawningCtx *property = GetAppSpawningCtxByPid(pid);
984 if (property != NULL && property->message != NULL && property->state == APP_STATE_SPAWNING) {
985 const char *processName = GetProcessName(property);
986 APPSPAWN_LOGI("Child process %{public}s fail \'child crash \'pid %{public}d appId: %{public}d",
987 processName, property->pid, property->client.id);
988 #ifdef APPSPAWN_HISYSEVENT
989 ReportSpawnChildProcessFail(processName, ERR_APPSPAWN_CHILD_CRASH, APPSPAWN_CHILD_CRASH);
990 #endif
991 if (property->client.id == g_lastDiedAppId + 1) {
992 g_crashTimes++;
993 } else {
994 g_crashTimes = 1;
995 }
996 g_lastDiedAppId = property->client.id;
997
998 SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_CHILD_CRASH, 0);
999 DeleteAppSpawningCtx(property);
1000
1001 if (g_crashTimes >= MAX_CRASH_TIME) {
1002 APPSPAWN_LOGW("Continuous failures in spawning the app, restart appspawn");
1003 #ifdef APPSPAWN_HISYSEVENT
1004 ReportKeyEvent(APPSPAWN_MAX_FAILURES_EXCEEDED);
1005 #endif
1006 StopAppSpawn();
1007 }
1008 }
1009 }
1010
WaitChildTimeout(const TimerHandle taskHandle,void * context)1011 static void WaitChildTimeout(const TimerHandle taskHandle, void *context)
1012 {
1013 AppSpawningCtx *property = (AppSpawningCtx *)context;
1014 APPSPAWN_LOGI("Child process %{public}s fail \'wait child timeout \'pid %{public}d appId: %{public}d",
1015 GetProcessName(property), property->pid, property->client.id);
1016 if (property->pid > 0) {
1017 #if (!defined(CJAPP_SPAWN) && !defined(NATIVE_SPAWN))
1018 DumpSpawnStack(property->pid);
1019 #endif
1020 kill(property->pid, SIGKILL);
1021 }
1022 #ifdef APPSPAWN_HISYSEVENT
1023 ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_TIMEOUT, APPSPAWN_SPAWN_TIMEOUT);
1024 #endif
1025 SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_SPAWN_TIMEOUT, 0);
1026 DeleteAppSpawningCtx(property);
1027 }
1028
ProcessChildFdCheck(int fd,AppSpawningCtx * property)1029 static int ProcessChildFdCheck(int fd, AppSpawningCtx *property)
1030 {
1031 int result = 0;
1032 (void)read(fd, &result, sizeof(result));
1033 APPSPAWN_LOGI("Child process %{public}s success pid %{public}d appId: %{public}d result: %{public}d",
1034 GetProcessName(property), property->pid, property->client.id, result);
1035 APPSPAWN_CHECK(property->message != NULL, return -1, "Invalid message in ctx %{public}d", property->client.id);
1036
1037 if (result != 0) {
1038 #ifdef APPSPAWN_HISYSEVENT
1039 ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_FAIL, result);
1040 #endif
1041 SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid);
1042 DeleteAppSpawningCtx(property);
1043 return -1;
1044 }
1045
1046 return 0;
1047 }
1048
ProcessChildResponse(const WatcherHandle taskHandle,int fd,uint32_t * events,const void * context)1049 static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
1050 {
1051 AppSpawningCtx *property = (AppSpawningCtx *)context;
1052 property->forkCtx.watcherHandle = NULL; // delete watcher
1053 LE_RemoveWatcher(LE_GetDefaultLoop(), (WatcherHandle)taskHandle);
1054
1055 if (ProcessChildFdCheck(fd, property) != 0) {
1056 return;
1057 }
1058
1059 // success
1060 bool isDebuggable = CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE);
1061 uint32_t appIndex = 0;
1062 if (CheckAppMsgFlagsSet(property, APP_FLAGS_CLONE_ENABLE)) {
1063 AppSpawnMsgBundleInfo *bundleInfo = (AppSpawnMsgBundleInfo *)GetAppProperty(property, TLV_BUNDLE_INFO);
1064 if (bundleInfo != NULL) {
1065 appIndex = bundleInfo->bundleIndex;
1066 }
1067 }
1068 AppSpawnedProcess *appInfo = AddSpawnedProcess(property->pid, GetBundleName(property), appIndex, isDebuggable);
1069 if (appInfo) {
1070 AppSpawnMsgDacInfo *dacInfo = GetAppProperty(property, TLV_DAC_INFO);
1071 appInfo->uid = dacInfo != NULL ? dacInfo->uid : 0;
1072 appInfo->spawnStart.tv_sec = property->spawnStart.tv_sec;
1073 appInfo->spawnStart.tv_nsec = property->spawnStart.tv_nsec;
1074 #ifdef DEBUG_BEGETCTL_BOOT
1075 if (IsDeveloperModeOpen()) {
1076 appInfo->message = property->message;
1077 }
1078 #endif
1079 clock_gettime(CLOCK_MONOTONIC, &appInfo->spawnEnd);
1080
1081 #ifdef APPSPAWN_HISYSEVENT
1082 //add process spawn duration into hisysevent,(ms)
1083 uint32_t spawnProcessDuration = (uint32_t)((appInfo->spawnEnd.tv_sec - appInfo->spawnStart.tv_sec) *
1084 (APPSPAWN_USEC_TO_NSEC)) +(uint32_t)((appInfo->spawnEnd.tv_nsec - appInfo->spawnStart.tv_nsec) /
1085 (APPSPAWN_MSEC_TO_NSEC));
1086 AppSpawnMgr *appspawnMgr = GetAppSpawnMgr();
1087 if (appspawnMgr != NULL) {
1088 AddStatisticEventInfo(appspawnMgr->hisyseventInfo, spawnProcessDuration, IsBootFinished());
1089 }
1090 #ifndef ASAN_DETECTOR
1091 uint64_t diff = DiffTime(&appInfo->spawnStart, &appInfo->spawnEnd);
1092 APPSPAWN_CHECK_ONLY_EXPER(diff < (IsChildColdRun(property) ? SPAWN_COLDRUN_DURATION : SPAWN_DURATION),
1093 ReportAbnormalDuration("SPAWNCHILD", diff));
1094 #endif
1095 #endif
1096 }
1097
1098 WatchChildProcessFd(property);
1099 ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, GetAppSpawnContent(), appInfo);
1100 // response
1101 AppSpawnHookExecute(STAGE_PARENT_PRE_RELY, 0, GetAppSpawnContent(), &property->client);
1102 StartAppspawnTrace("SendResponse");
1103 SendResponse(property->message->connection, &property->message->msgHeader, 0, property->pid);
1104 FinishAppspawnTrace();
1105 AppSpawnHookExecute(STAGE_PARENT_POST_RELY, 0, GetAppSpawnContent(), &property->client);
1106 #ifdef DEBUG_BEGETCTL_BOOT
1107 if (IsDeveloperModeOpen()) {
1108 property->message = NULL;
1109 }
1110 #endif
1111 DeleteAppSpawningCtx(property);
1112 }
1113
NotifyResToParent(AppSpawnContent * content,AppSpawnClient * client,int result)1114 static void NotifyResToParent(AppSpawnContent *content, AppSpawnClient *client, int result)
1115 {
1116 AppSpawningCtx *property = (AppSpawningCtx *)client;
1117 APPSPAWN_CHECK(property != NULL && client != NULL, return, "invalid param");
1118 int fd = property->forkCtx.fd[1];
1119 if (fd >= 0) {
1120 (void)write(fd, &result, sizeof(result));
1121 (void)close(fd);
1122 property->forkCtx.fd[1] = -1;
1123 }
1124 APPSPAWN_LOGV("NotifyResToParent client id: %{public}u result: 0x%{public}x", client->id, result);
1125 }
1126
CreateAppSpawnServer(TaskHandle * server,const char * socketName)1127 static int CreateAppSpawnServer(TaskHandle *server, const char *socketName)
1128 {
1129 char path[128] = {0}; // 128 max path
1130 int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", APPSPAWN_SOCKET_DIR, socketName);
1131 APPSPAWN_CHECK(ret > 0, return -1, "Failed to snprintf_s %{public}d", ret);
1132 int socketId = GetControlSocket(socketName);
1133 APPSPAWN_LOGI("get socket form env %{public}s socketId %{public}d", socketName, socketId);
1134
1135 LE_StreamServerInfo info = {};
1136 info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER;
1137 info.socketId = socketId;
1138 info.server = path;
1139 info.baseInfo.close = NULL;
1140 info.incommingConnect = OnConnection;
1141
1142 MakeDirRec(path, 0711, 0); // 0711 default mask
1143 ret = LE_CreateStreamServer(LE_GetDefaultLoop(), server, &info);
1144 APPSPAWN_CHECK(ret == 0, return -1, "Failed to create socket for %{public}s errno: %{public}d", path, errno);
1145 SetFdCtrl(LE_GetSocketFd(*server), FD_CLOEXEC);
1146
1147 APPSPAWN_LOGI("CreateAppSpawnServer path %{public}s fd %{public}d", path, LE_GetSocketFd(*server));
1148 return 0;
1149 }
1150
AppSpawnDestroyContent(AppSpawnContent * content)1151 void AppSpawnDestroyContent(AppSpawnContent *content)
1152 {
1153 if (content == NULL) {
1154 return;
1155 }
1156 if (content->parentToChildFd[0] > 0) {
1157 close(content->parentToChildFd[0]);
1158 content->parentToChildFd[0] = -1;
1159 }
1160 if (content->parentToChildFd[1] > 0) {
1161 close(content->parentToChildFd[1]);
1162 content->parentToChildFd[1] = -1;
1163 }
1164 AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content;
1165 if (appSpawnContent->sigHandler != NULL && appSpawnContent->servicePid == getpid()) {
1166 LE_CloseSignalTask(LE_GetDefaultLoop(), appSpawnContent->sigHandler);
1167 }
1168
1169 if (appSpawnContent->server != NULL && appSpawnContent->servicePid == getpid()) { // childProcess can't deal socket
1170 LE_CloseStreamTask(LE_GetDefaultLoop(), appSpawnContent->server);
1171 appSpawnContent->server = NULL;
1172 }
1173 DeleteAppSpawnMgr(appSpawnContent);
1174 LE_StopLoop(LE_GetDefaultLoop());
1175 LE_CloseLoop(LE_GetDefaultLoop());
1176 }
1177
AppSpawnColdStartApp(struct AppSpawnContent * content,AppSpawnClient * client)1178 APPSPAWN_STATIC int AppSpawnColdStartApp(struct AppSpawnContent *content, AppSpawnClient *client)
1179 {
1180 AppSpawningCtx *property = (AppSpawningCtx *)client;
1181 #ifdef CJAPP_SPAWN
1182 char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/cjappspawn";
1183 #elif NATIVE_SPAWN
1184 char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/nativespawn";
1185 #elif HYBRID_SPAWN
1186 char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/hybridspawn";
1187 #elif NWEB_SPAWN
1188 char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/nwebspawn";
1189 #else
1190 char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/appspawn";
1191 #endif
1192 APPSPAWN_LOGI("ColdStartApp::processName: %{public}s path: %{public}s", GetProcessName(property), path);
1193
1194 // for cold run, use shared memory to exchange message
1195 APPSPAWN_LOGV("Write msg to child %{public}s", GetProcessName(property));
1196 int ret = WriteMsgToChild(property, IsNWebSpawnMode((AppSpawnMgr *)content));
1197 APPSPAWN_CHECK(ret == 0, return APPSPAWN_SYSTEM_ERROR, "Failed to write msg to child");
1198
1199 char buffer[4][32] = {0}; // 4 32 buffer for fd
1200 int len = sprintf_s(buffer[0], sizeof(buffer[0]), " %d ", property->forkCtx.fd[1]);
1201 APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format fd");
1202 len = sprintf_s(buffer[1], sizeof(buffer[1]), " %u ", property->client.flags);
1203 APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format flags");
1204 len = sprintf_s(buffer[2], sizeof(buffer[2]), " %u ", property->forkCtx.msgSize); // 2 2 index for dest path
1205 APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format shmId ");
1206 len = sprintf_s(buffer[3], sizeof(buffer[3]), " %u ", property->client.id); // 3 3 index for client id
1207 APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format shmId ");
1208 #ifndef APPSPAWN_TEST
1209 char *mode = IsNWebSpawnMode((AppSpawnMgr *)content) ? "nweb_cold" : "app_cold";
1210 // 2 2 index for dest path
1211 const char *const formatCmds[] = {
1212 path, "-mode", mode, "-fd", buffer[0], buffer[1], buffer[2],
1213 "-param", GetProcessName(property), buffer[3], NULL
1214 };
1215
1216 ret = execv(path, (char **)formatCmds);
1217 if (ret != 0) {
1218 APPSPAWN_LOGE("Failed to execv, errno: %{public}d", errno);
1219 }
1220 #endif
1221 APPSPAWN_LOGV("ColdStartApp::processName: %{public}s end", GetProcessName(property));
1222 return 0;
1223 }
1224
GetAppSpawningCtxFromArg(AppSpawnMgr * content,int argc,char * const argv[])1225 static AppSpawningCtx *GetAppSpawningCtxFromArg(AppSpawnMgr *content, int argc, char *const argv[])
1226 {
1227 AppSpawningCtx *property = CreateAppSpawningCtx();
1228 APPSPAWN_CHECK(property != NULL, return NULL, "Create app spawning ctx fail");
1229 property->forkCtx.fd[1] = atoi(argv[FD_VALUE_INDEX]);
1230 property->client.flags = (uint32_t)atoi(argv[FLAGS_VALUE_INDEX]);
1231 property->client.flags &= ~APP_COLD_START;
1232
1233 int isNweb = IsNWebSpawnMode(content);
1234 uint32_t size = (uint32_t)atoi(argv[SHM_SIZE_INDEX]);
1235 property->client.id = (uint32_t)atoi(argv[CLIENT_ID_INDEX]);
1236 uint8_t *buffer = (uint8_t *)GetMapMem(property->client.id,
1237 argv[PARAM_VALUE_INDEX], size, true, isNweb);
1238 if (buffer == NULL) {
1239 APPSPAWN_LOGE("Failed to map errno %{public}d %{public}s", property->client.id, argv[PARAM_VALUE_INDEX]);
1240 NotifyResToParent(&content->content, &property->client, APPSPAWN_SYSTEM_ERROR);
1241 DeleteAppSpawningCtx(property);
1242 return NULL;
1243 }
1244
1245 uint32_t msgRecvLen = 0;
1246 uint32_t remainLen = 0;
1247 AppSpawnMsgNode *message = NULL;
1248 int ret = GetAppSpawnMsgFromBuffer(buffer, ((AppSpawnMsg *)buffer)->msgLen, &message, &msgRecvLen, &remainLen);
1249 // release map
1250 munmap((char *)buffer, size);
1251 //unlink
1252 char path[PATH_MAX] = {0};
1253 int len = sprintf_s(path, sizeof(path), APPSPAWN_MSG_DIR "%s/%s_%u",
1254 isNweb ? "nwebspawn" : "appspawn", argv[PARAM_VALUE_INDEX], property->client.id);
1255 if (len > 0) {
1256 unlink(path);
1257 }
1258
1259 if (ret == 0 && DecodeAppSpawnMsg(message) == 0 && CheckAppSpawnMsg(message) == 0) {
1260 property->message = message;
1261 message = NULL;
1262 return property;
1263 }
1264 NotifyResToParent(&content->content, &property->client, APPSPAWN_MSG_INVALID);
1265 DeleteAppSpawnMsg(&message);
1266 DeleteAppSpawningCtx(property);
1267 return NULL;
1268 }
1269
AppSpawnColdRun(AppSpawnContent * content,int argc,char * const argv[])1270 static void AppSpawnColdRun(AppSpawnContent *content, int argc, char *const argv[])
1271 {
1272 APPSPAWN_CHECK(argc >= ARG_NULL, return, "Invalid arg for cold start %{public}d", argc);
1273 AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content;
1274 APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content");
1275
1276 AppSpawningCtx *property = GetAppSpawningCtxFromArg(appSpawnContent, argc, argv);
1277 if (property == NULL) {
1278 APPSPAWN_LOGE("Failed to get property from arg");
1279 return;
1280 }
1281 DumpAppSpawnMsg(property->message);
1282
1283 int ret = AppSpawnExecuteSpawningHook(content, &property->client);
1284 if (ret == 0) {
1285 ret = AppSpawnExecutePreReplyHook(content, &property->client);
1286 // success
1287 NotifyResToParent(content, &property->client, ret);
1288
1289 (void)AppSpawnExecutePostReplyHook(content, &property->client);
1290
1291 ret = APPSPAWN_SYSTEM_ERROR;
1292 if (content->runChildProcessor != NULL) {
1293 ret = content->runChildProcessor(content, &property->client);
1294 }
1295 } else {
1296 NotifyResToParent(content, &property->client, ret);
1297 }
1298
1299 if (ret != 0) {
1300 AppSpawnEnvClear(content, &property->client);
1301 }
1302 APPSPAWN_LOGI("AppSpawnColdRun exit %{public}d.", getpid());
1303 }
1304
AppSpawnRun(AppSpawnContent * content,int argc,char * const argv[])1305 static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[])
1306 {
1307 APPSPAWN_LOGI("AppSpawnRun");
1308 AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content;
1309 APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content");
1310
1311 LE_STATUS status = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, ProcessSignal);
1312 if (status == 0) {
1313 (void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGCHLD);
1314 (void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGTERM);
1315 }
1316
1317 if (IsAppSpawnMode(appSpawnContent) || IsHybridSpawnMode(appSpawnContent)) {
1318 struct sched_param param = { 0 };
1319 param.sched_priority = 1;
1320 int ret = sched_setscheduler(0, SCHED_FIFO, ¶m);
1321 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "UpdateSchedPrio failed ret: %{public}d, %{public}d", ret, errno);
1322 }
1323 LE_RunLoop(LE_GetDefaultLoop());
1324 APPSPAWN_LOGI("AppSpawnRun exit mode: %{public}d ", content->mode);
1325
1326 (void)ServerStageHookExecute(STAGE_SERVER_EXIT, content); // service exit,plugin can deal task
1327 AppSpawnDestroyContent(content);
1328 }
1329
AppSpawnClearEnv(AppSpawnMgr * content,AppSpawningCtx * property)1330 APPSPAWN_STATIC int AppSpawnClearEnv(AppSpawnMgr *content, AppSpawningCtx *property)
1331 {
1332 APPSPAWN_CHECK(content != NULL, return 0, "Invalid appspawn content");
1333 StartAppspawnTrace("AppSpawnClearEnv");
1334 DeleteAppSpawningCtx(property);
1335 AppSpawnDestroyContent(&content->content);
1336 APPSPAWN_LOGV("clear %{public}d end", getpid());
1337 FinishAppspawnTrace();
1338 return 0;
1339 }
1340
IsEnablePrefork(void)1341 static int IsEnablePrefork(void)
1342 {
1343 char buffer[32] = {0};
1344 int ret = GetParameter("persist.sys.prefork.enable", "true", buffer, sizeof(buffer));
1345 APPSPAWN_LOGV("IsEnablePrefork result %{public}d, %{public}s", ret, buffer);
1346 return strcmp(buffer, "true") == 0;
1347 }
1348
AppSpawnCreateContent(const char * socketName,char * longProcName,uint32_t nameLen,int mode)1349 AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t nameLen, int mode)
1350 {
1351 APPSPAWN_CHECK(socketName != NULL && longProcName != NULL, return NULL, "Invalid name");
1352 APPSPAWN_LOGI("AppSpawnCreateContent %{public}s %{public}u mode %{public}d", socketName, nameLen, mode);
1353
1354 AppSpawnMgr *appSpawnContent = CreateAppSpawnMgr(mode);
1355 APPSPAWN_CHECK(appSpawnContent != NULL, return NULL, "Failed to alloc memory for appspawn");
1356 #ifdef APPSPAWN_HISYSEVENT
1357 appSpawnContent->hisyseventInfo = InitHisyseventTimer();
1358 #endif
1359 appSpawnContent->content.longProcName = longProcName;
1360 appSpawnContent->content.longProcNameLen = nameLen;
1361 appSpawnContent->content.notifyResToParent = NotifyResToParent;
1362 if (IsColdRunMode(appSpawnContent)) {
1363 appSpawnContent->content.runAppSpawn = AppSpawnColdRun;
1364 } else {
1365 appSpawnContent->content.runAppSpawn = AppSpawnRun;
1366 appSpawnContent->content.coldStartApp = AppSpawnColdStartApp;
1367
1368 int ret = CreateAppSpawnServer(&appSpawnContent->server, socketName);
1369 APPSPAWN_CHECK(ret == 0, AppSpawnDestroyContent(&appSpawnContent->content);
1370 return NULL, "Failed to create server");
1371 }
1372 appSpawnContent->content.enablePerfork = IsEnablePrefork();
1373 return &appSpawnContent->content;
1374 }
1375
StartSpawnService(const AppSpawnStartArg * startArg,uint32_t argvSize,int argc,char * const argv[])1376 AppSpawnContent *StartSpawnService(const AppSpawnStartArg *startArg, uint32_t argvSize, int argc, char *const argv[])
1377 {
1378 APPSPAWN_CHECK(startArg != NULL && argv != NULL, return NULL, "Invalid start arg");
1379 pid_t pid = 0;
1380 AppSpawnStartArg *arg = (AppSpawnStartArg *)startArg;
1381 APPSPAWN_LOGV("Start appspawn argvSize %{public}d mode %{public}d service %{public}s",
1382 argvSize, arg->mode, arg->serviceName);
1383
1384 if (arg->initArg) {
1385 int ret = memset_s(argv[0], argvSize, 0, (size_t)argvSize);
1386 APPSPAWN_CHECK(ret == EOK, return NULL, "Failed to memset argv[0]");
1387 ret = strncpy_s(argv[0], argvSize, arg->serviceName, strlen(arg->serviceName));
1388 APPSPAWN_CHECK(ret == EOK, return NULL, "Failed to copy service name %{public}s", arg->serviceName);
1389 }
1390
1391 // load module appspawn/common
1392 AppSpawnLoadAutoRunModules(MODULE_COMMON);
1393 AppSpawnModuleMgrInstall(ASAN_MODULE_PATH);
1394
1395 APPSPAWN_CHECK(LE_GetDefaultLoop() != NULL, return NULL, "Invalid default loop");
1396 AppSpawnContent *content = AppSpawnCreateContent(arg->socketName, argv[0], argvSize, arg->mode);
1397 APPSPAWN_CHECK(content != NULL, return NULL, "Failed to create content for %{public}s", arg->socketName);
1398
1399 AppSpawnLoadAutoRunModules(arg->moduleType); // load corresponding plugin according to startup mode
1400 int ret = ServerStageHookExecute(STAGE_SERVER_PRELOAD, content); // Preload, prase the sandbox
1401 APPSPAWN_CHECK(ret == 0, AppSpawnDestroyContent(content);
1402 return NULL, "Failed to prepare load %{public}s result: %{public}d", arg->serviceName, ret);
1403 #ifndef APPSPAWN_TEST
1404 APPSPAWN_CHECK(content->runChildProcessor != NULL, AppSpawnDestroyContent(content);
1405 return NULL, "No child processor %{public}s result: %{public}d", arg->serviceName, ret);
1406 #endif
1407 AddAppSpawnHook(STAGE_CHILD_PRE_RUN, HOOK_PRIO_LOWEST, AppSpawnClearEnv);
1408 if (arg->mode == MODE_FOR_APP_SPAWN) {
1409 SetParameter("bootevent.appspawn.started", "true");
1410 }
1411 return content;
1412 }
1413
ProcessSpawnBegetctlMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)1414 static AppSpawnMsgNode *ProcessSpawnBegetctlMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1415 {
1416 uint32_t len = 0;
1417 const char *cmdMsg = (const char *)GetAppSpawnMsgExtInfo(message, MSG_EXT_NAME_BEGET_PID, &len);
1418 APPSPAWN_CHECK(cmdMsg != NULL, return NULL, "Failed to get extInfo");
1419 AppSpawnedProcess *appInfo = GetSpawnedProcess(atoi(cmdMsg));
1420 APPSPAWN_CHECK(appInfo != NULL, return NULL, "Failed to get app info");
1421 AppSpawnMsgNode *msgNode = RebuildAppSpawnMsgNode(message, appInfo);
1422 APPSPAWN_CHECK(msgNode != NULL, return NULL, "Failed to rebuild app message node");
1423 int ret = DecodeAppSpawnMsg(msgNode);
1424 if (ret != 0) {
1425 DeleteAppSpawnMsg(&msgNode);
1426 return NULL;
1427 }
1428 return msgNode;
1429 }
1430
ProcessBegetCmdMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)1431 static void ProcessBegetCmdMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1432 {
1433 AppSpawnMsg *msg = &message->msgHeader;
1434 if (!IsDeveloperModeOpen()) {
1435 SendResponse(connection, msg, APPSPAWN_DEBUG_MODE_NOT_SUPPORT, 0);
1436 DeleteAppSpawnMsg(&message);
1437 return;
1438 }
1439 AppSpawnMsgNode *msgNode = ProcessSpawnBegetctlMsg(connection, message);
1440 if (msgNode == NULL) {
1441 SendResponse(connection, msg, APPSPAWN_DEBUG_MODE_NOT_SUPPORT, 0);
1442 DeleteAppSpawnMsg(&message);
1443 return;
1444 }
1445 ProcessSpawnReqMsg(connection, msgNode);
1446 DeleteAppSpawnMsg(&message);
1447 DeleteAppSpawnMsg(&msgNode);
1448 }
1449
GetArkWebInstallPath(const char * key,char * value)1450 static int GetArkWebInstallPath(const char *key, char *value)
1451 {
1452 int len = GetParameter(key, "", value, PATH_SIZE);
1453 APPSPAWN_CHECK(len > 0, return -1, "Failed to get arkwebcore install path from param, len %{public}d", len);
1454 for (int i = len - 1; i >= 0; i--) {
1455 if (value[i] == '/') {
1456 value[i] = '\0';
1457 return i;
1458 }
1459 value[i] = '\0';
1460 }
1461 return -1;
1462 }
1463
CheckAllDigit(char * userId)1464 static bool CheckAllDigit(char *userId)
1465 {
1466 for (int i = 0; userId[i] != '\0'; i++) {
1467 if (!isdigit(userId[i])) {
1468 return false;
1469 }
1470 }
1471 return true;
1472 }
1473
1474 #ifdef APPSPAWN_SANDBOX_NEW
ProcessSpawnRemountMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)1475 static int ProcessSpawnRemountMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1476 {
1477 APPSPAWN_LOGI("ProcessSpawnRemountMsg in new sandbox, do not handle it");
1478 return 0;
1479 }
1480
ProcessSpawnRestartMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)1481 static void ProcessSpawnRestartMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1482 {
1483 APPSPAWN_LOGI("ProcessSpawnRestartMsg in new sandbox, do not handle it");
1484 SendResponse(connection, &message->msgHeader, 0, 0);
1485 }
1486 #else
ProcessSpawnRemountMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)1487 static int ProcessSpawnRemountMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1488 {
1489 char srcPath[PATH_SIZE] = {0};
1490 int len = GetArkWebInstallPath("persist.arkwebcore.install_path", srcPath);
1491 APPSPAWN_CHECK(len > 0, return -1, "Failed to get arkwebcore install path");
1492
1493 char *rootPath = "/mnt/sandbox";
1494 DIR *rootDir = opendir(rootPath);
1495 APPSPAWN_CHECK(rootDir != NULL, return -1, "Failed to opendir %{public}s, errno %{public}d", rootPath, errno);
1496
1497 struct dirent *ent;
1498 while ((ent = readdir(rootDir)) != NULL) {
1499 char *userId = ent->d_name;
1500 if (strcmp(userId, ".") == 0 || strcmp(userId, "..") == 0 || !CheckAllDigit(userId)) {
1501 continue;
1502 }
1503
1504 char userIdPath[PATH_SIZE] = {0};
1505 int ret = snprintf_s(userIdPath, sizeof(userIdPath), sizeof(userIdPath) - 1, "%s/%s", rootPath, userId);
1506 APPSPAWN_CHECK(ret > 0, continue, "Failed to snprintf_s, errno %{public}d", errno);
1507
1508 DIR *userIdDir = opendir(userIdPath);
1509 APPSPAWN_CHECK(userIdDir != NULL, continue, "Failed to open %{public}s, errno %{public}d", userIdPath, errno);
1510
1511 while ((ent = readdir(userIdDir)) != NULL) {
1512 char *bundleName = ent->d_name;
1513 if (strcmp(bundleName, ".") == 0 || strcmp(bundleName, "..") == 0) {
1514 continue;
1515 }
1516 char destPath[PATH_SIZE] = {0};
1517 ret = snprintf_s(destPath, sizeof(destPath), sizeof(destPath) - 1,
1518 "%s/%s/data/storage/el1/bundle/arkwebcore", userIdPath, bundleName);
1519 APPSPAWN_CHECK(ret > 0, continue, "Failed to snprintf_s, errno %{public}d", errno);
1520
1521 umount2(destPath, MNT_DETACH);
1522 ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL);
1523 if (ret != 0 && errno == EBUSY) {
1524 ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL);
1525 APPSPAWN_LOGV("mount again %{public}s to %{public}s, ret %{public}d", srcPath, destPath, ret);
1526 }
1527 APPSPAWN_CHECK(ret == 0, continue,
1528 "Failed to bind mount %{public}s to %{public}s, errno %{public}d", srcPath, destPath, errno);
1529
1530 ret = mount(NULL, destPath, NULL, MS_SHARED, NULL);
1531 APPSPAWN_CHECK(ret == 0, continue,
1532 "Failed to shared mount %{public}s to %{public}s, errno %{public}d", srcPath, destPath, errno);
1533
1534 APPSPAWN_LOGV("Remount %{public}s to %{public}s success", srcPath, destPath);
1535 }
1536 closedir(userIdDir);
1537 }
1538 closedir(rootDir);
1539 return 0;
1540 }
1541
ProcessSpawnRestartMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)1542 static void ProcessSpawnRestartMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1543 {
1544 AppSpawnContent *content = GetAppSpawnContent();
1545 if (!IsNWebSpawnMode((AppSpawnMgr *)content)) {
1546 SendResponse(connection, &message->msgHeader, APPSPAWN_MSG_INVALID, 0);
1547 DeleteAppSpawnMsg(&message);
1548 APPSPAWN_LOGE("Restart msg only support nwebspawn");
1549 return;
1550 }
1551
1552 TraversalSpawnedProcess(AppQueueDestroyProc, NULL);
1553 SendResponse(connection, &message->msgHeader, 0, 0);
1554 DeleteAppSpawnMsg(&message);
1555 (void) ServerStageHookExecute(STAGE_SERVER_EXIT, content);
1556
1557 errno = 0;
1558 int fd = GetControlSocket(NWEBSPAWN_SOCKET_NAME);
1559 APPSPAWN_CHECK(fd >= 0, return, "Get fd failed %{public}d, errno %{public}d", fd, errno);
1560
1561 int ret = 0;
1562 int op = fcntl(fd, F_GETFD);
1563 APPSPAWN_CHECK_ONLY_LOG(op >= 0, "fcntl failed %{public}d", op);
1564 if (op > 0) {
1565 ret = fcntl(fd, F_SETFD, (unsigned int)op & ~FD_CLOEXEC);
1566 if (ret < 0) {
1567 APPSPAWN_LOGE("Set fd failed %{public}d, %{public}d, ret %{public}d, errno %{public}d", fd, op, ret, errno);
1568 }
1569 }
1570
1571 char *path = "/system/bin/nwebspawn";
1572 char *mode = NWEBSPAWN_RESTART;
1573 const char *const formatCmds[] = {path, "-mode", mode, NULL};
1574 ret = execv(path, (char **)formatCmds);
1575 APPSPAWN_LOGE("Failed to execv, ret %{public}d, errno %{public}d", ret, errno);
1576 }
1577 #endif
1578
ProcessUninstallDebugHap(AppSpawnConnection * connection,AppSpawnMsgNode * message)1579 APPSPAWN_STATIC void ProcessUninstallDebugHap(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1580 {
1581 APPSPAWN_LOGI("ProcessUninstallDebugHap start");
1582 AppSpawningCtx *property = CreateAppSpawningCtx();
1583 if (property == NULL) {
1584 SendResponse(connection, &message->msgHeader, APPSPAWN_SYSTEM_ERROR, 0);
1585 DeleteAppSpawnMsg(&message);
1586 return;
1587 }
1588
1589 property->message = message;
1590 property->message->connection = connection;
1591 int ret = AppSpawnHookExecute(STAGE_PARENT_UNINSTALL, 0, GetAppSpawnContent(), &property->client);
1592 SendResponse(connection, &message->msgHeader, ret, 0);
1593 DeleteAppSpawningCtx(property);
1594 }
1595
AppspawpnDevicedebugKill(int pid,cJSON * args)1596 APPSPAWN_STATIC int AppspawpnDevicedebugKill(int pid, cJSON *args)
1597 {
1598 cJSON *signal = cJSON_GetObjectItem(args, "signal");
1599 APPSPAWN_CHECK(cJSON_IsNumber(signal), return -1, "appspawn devicedebug json get signal fail");
1600
1601 AppSpawnedProcess *appInfo = GetSpawnedProcess(pid);
1602 APPSPAWN_CHECK(appInfo != NULL, return APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_EXIST,
1603 "appspawn devicedebug get app info unsuccess, pid=%{public}d", pid);
1604 APPSPAWN_CHECK(appInfo->isDebuggable, return APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_DEBUGGABLE,
1605 "appspawn devicedebug process is not debuggable, pid=%{public}d", pid);
1606
1607 APPSPAWN_LOGI("appspawn devicedebug debugable=%{public}d, pid=%{public}d, signal=%{public}d",
1608 appInfo->isDebuggable, pid, signal->valueint);
1609
1610 if (kill(pid, signal->valueint) != 0) {
1611 APPSPAWN_LOGE("appspawn devicedebug unable to kill process, pid: %{public}d ret %{public}d", pid, errno);
1612 return -1;
1613 }
1614
1615 return 0;
1616 }
1617
AppspawnDevicedebugDeal(const char * op,int pid,cJSON * args)1618 APPSPAWN_STATIC int AppspawnDevicedebugDeal(const char* op, int pid, cJSON *args)
1619 {
1620 if (strcmp(op, "kill") == 0) {
1621 return AppspawpnDevicedebugKill(pid, args);
1622 }
1623 APPSPAWN_LOGE("appspawn devicedebug op:%{public}s invalid", op);
1624
1625 return -1;
1626 }
1627
ProcessAppSpawnDeviceDebugMsg(AppSpawnMsgNode * message)1628 APPSPAWN_STATIC int ProcessAppSpawnDeviceDebugMsg(AppSpawnMsgNode *message)
1629 {
1630 APPSPAWN_CHECK_ONLY_EXPER(message != NULL, return -1);
1631 uint32_t len = 0;
1632
1633 const char* jsonString = (char *)GetAppSpawnMsgExtInfo(message, "devicedebug", &len);
1634 if (jsonString == NULL || len == 0) {
1635 APPSPAWN_LOGE("appspawn devicedebug get devicedebug fail");
1636 return -1;
1637 }
1638
1639 cJSON *json = cJSON_Parse(jsonString);
1640 APPSPAWN_CHECK(json != NULL, return -1, "appspawn devicedebug json parse fail");
1641
1642 cJSON *app = cJSON_GetObjectItem(json, "app");
1643 APPSPAWN_CHECK(cJSON_IsNumber(app), cJSON_Delete(json);
1644 return -1, "appspawn devicedebug json get app fail");
1645
1646 cJSON *op = cJSON_GetObjectItem(json, "op");
1647 APPSPAWN_CHECK(cJSON_IsString(op) && op->valuestring != NULL, cJSON_Delete(json);
1648 return -1, "appspawn devicedebug json get op fail");
1649
1650 cJSON *args = cJSON_GetObjectItem(json, "args");
1651 APPSPAWN_CHECK(cJSON_IsObject(args), cJSON_Delete(json);
1652 return -1, "appspawn devicedebug json get args fail");
1653
1654 int result = AppspawnDevicedebugDeal(op->valuestring, app->valueint, args);
1655 cJSON_Delete(json);
1656 return result;
1657 }
1658
ProcessAppSpawnLockStatusMsg(AppSpawnMsgNode * message)1659 static void ProcessAppSpawnLockStatusMsg(AppSpawnMsgNode *message)
1660 {
1661 APPSPAWN_CHECK_ONLY_EXPER(message != NULL, return);
1662 uint32_t len = 0;
1663 char *lockstatus = (char *)GetAppSpawnMsgExtInfo(message, "lockstatus", &len);
1664 APPSPAWN_CHECK(lockstatus != NULL, return, "failed to get lockstatus");
1665 APPSPAWN_LOGI("appspawn get lockstatus %{public}s from storage_manager", lockstatus);
1666 char *userLockStatus = NULL;
1667 // userLockStatus format example: 100:0 100 for userid 0:unlock 1:lock
1668 char *userIdStr = strtok_r(lockstatus, ":", &userLockStatus);
1669 APPSPAWN_CHECK(userIdStr != NULL && userLockStatus != NULL, return,
1670 "lockstatus not satisfied format, failed to get userLockStatus");
1671 int userId = atoi(userIdStr);
1672 if (userId < USER_ID_MIN_VALUE || userId > USER_ID_MAX_VALUE) {
1673 APPSPAWN_LOGE("userId err %{public}s", userIdStr);
1674 return;
1675 }
1676 if (strcmp(userLockStatus, "0") != 0 && strcmp(userLockStatus, "1") != 0) {
1677 APPSPAWN_LOGE("userLockStatus err %{public}s", userLockStatus);
1678 return;
1679 }
1680 char lockStatusParam[LOCK_STATUS_PARAM_SIZE] = {0};
1681 int ret = snprintf_s(lockStatusParam, sizeof(lockStatusParam), sizeof(lockStatusParam) - 1,
1682 "startup.appspawn.lockstatus_%d", userId);
1683 APPSPAWN_CHECK(ret > 0, return, "get lock status param failed, errno %{public}d", errno);
1684 ret = SetParameter(lockStatusParam, userLockStatus);
1685 APPSPAWN_CHECK(ret == 0, return, "failed to set lockstatus param value ret %{public}d", ret);
1686 #ifdef APPSPAWN_HISYSEVENT
1687 ReportKeyEvent(strcmp(userLockStatus, "0") == 0 ? UNLOCK_SUCCESS : LOCK_SUCCESS);
1688 #endif
1689 if (strcmp(userLockStatus, "0") == 0) {
1690 ServerStageHookExecute(STAGE_SERVER_LOCK, GetAppSpawnContent());
1691 }
1692 }
1693
AppSpawnReqMsgFdGet(AppSpawnConnection * connection,AppSpawnMsgNode * message,const char * fdName,int * fd)1694 APPSPAWN_STATIC int AppSpawnReqMsgFdGet(AppSpawnConnection *connection, AppSpawnMsgNode *message,
1695 const char *fdName, int *fd)
1696 {
1697 APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL && connection != NULL, return -1);
1698 APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset != NULL, return -1);
1699 int findFdIndex = 0;
1700 AppSpawnMsgReceiverCtx recvCtx = connection->receiverCtx;
1701 APPSPAWN_CHECK(recvCtx.fds != NULL && recvCtx.fdCount > 0, return 0,
1702 "no need get fd info %{public}d, %{public}d", recvCtx.fds != NULL, recvCtx.fdCount);
1703
1704 for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) {
1705 if (message->tlvOffset[index] == INVALID_OFFSET) {
1706 return APPSPAWN_SYSTEM_ERROR;
1707 }
1708 uint8_t *data = message->buffer + message->tlvOffset[index];
1709 if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) {
1710 continue;
1711 }
1712 AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data;
1713 if (strcmp(tlv->tlvName, MSG_EXT_NAME_APP_FD) != 0) {
1714 continue;
1715 }
1716 APPSPAWN_CHECK(findFdIndex < recvCtx.fdCount && recvCtx.fds[findFdIndex] > 0, return -1,
1717 "check get fd args failed %{public}d, %{public}d, %{public}d",
1718 findFdIndex, recvCtx.fdCount, recvCtx.fds[findFdIndex]);
1719
1720 if (strcmp((const char *)(data + sizeof(AppSpawnTlvExt)), fdName) == 0 && recvCtx.fds[findFdIndex] > 0) {
1721 *fd = recvCtx.fds[findFdIndex];
1722 APPSPAWN_LOGI("Spawn Listen fd %{public}s get success %{public}d", fdName, recvCtx.fds[findFdIndex]);
1723 break;
1724 }
1725 findFdIndex++;
1726 if (findFdIndex >= recvCtx.fdCount) {
1727 break;
1728 }
1729 }
1730 return 0;
1731 }
1732
ProcessObserveProcessSignalMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)1733 APPSPAWN_STATIC void ProcessObserveProcessSignalMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1734 {
1735 APPSPAWN_CHECK_ONLY_EXPER(message != NULL, return);
1736 int fd = 0;
1737 int ret = AppSpawnReqMsgFdGet(connection, message, SPAWN_LISTEN_FD_NAME, &fd);
1738 if (fd <= 0 || ret != 0) {
1739 APPSPAWN_LOGE("Spawn Listen appspawn signal fd get unsuccess");
1740 SendResponse(connection, &message->msgHeader, APPSPAWN_SYSTEM_ERROR, 0);
1741 DeleteAppSpawnMsg(&message);
1742 return;
1743 }
1744
1745 AppSpawnContent *content = GetAppSpawnContent();
1746 APPSPAWN_CHECK(content != NULL, return, "Spawn Listen appspawn content is null");
1747 content->signalFd = fd;
1748 connection->receiverCtx.fdCount = 0;
1749 SendResponse(connection, &message->msgHeader, 0, 0);
1750 DeleteAppSpawnMsg(&message);
1751 }
1752
ProcessSpawnDlopenMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)1753 static void ProcessSpawnDlopenMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1754 {
1755 AppSpawnMsg* msg = &message->msgHeader;
1756 APPSPAWN_LOGI("Recv ProcessSpawnReqMsg message header magic: 0x%{public}x type: %{public}u"
1757 "id: %{public}u len: %{public}u processName: %{public}s",
1758 msg->magic,
1759 msg->msgType,
1760 msg->msgId,
1761 msg->msgLen,
1762 msg->processName);
1763
1764 #if (defined(PRE_DLOPEN_ARKWEB_LIB) && !defined(ASAN_DETECTOR))
1765 Dl_namespace dlns;
1766 if (dlns_get("nweb_ns", &dlns) != 0) {
1767 char arkwebLibPath[PATH_SIZE] = "";
1768 if (snprintf_s(arkwebLibPath, sizeof(arkwebLibPath), sizeof(arkwebLibPath) - 1,
1769 "%s%s%s", "/data/app/el1/bundle/public/", msg->processName,
1770 "/libs/arm64:/data/storage/el1/bundle/arkwebcore/libs/arm64") < 0) {
1771 APPSPAWN_LOGE("FAILED to get arkwebLibPath");
1772 SendResponse(connection, msg, -1, 0);
1773 return;
1774 }
1775 APPSPAWN_LOGI("ProcessSpawnDlopenMsg arkwebLibPath: %{public}s", arkwebLibPath);
1776
1777 dlns_init(&dlns, "nweb_ns");
1778 dlns_create(&dlns, arkwebLibPath);
1779
1780 Dl_namespace ndkns;
1781 dlns_get("ndk", &ndkns);
1782 dlns_inherit(&dlns, &ndkns, "allow_all_shared_libs");
1783 }
1784
1785 void* webEngineHandle = dlopen_ns(&dlns, "libarkweb_engine.so", RTLD_NOW | RTLD_GLOBAL);
1786 if (!webEngineHandle) {
1787 APPSPAWN_LOGE("FAILED to dlopen libarkweb_engine.so in appspawn %{public}s", dlerror());
1788 SendResponse(connection, msg, -1, 0);
1789 } else {
1790 APPSPAWN_LOGI("SUCCESS to dlopen libarkweb_engine.so in appspawn");
1791 SendResponse(connection, msg, 0, 0);
1792 #ifndef OHOS_LITE
1793 ReclaimFileCache();
1794 #endif
1795 }
1796 #else
1797 SendResponse(connection, msg, 0, 0);
1798 #endif
1799 }
1800
ProcessRecvMsg(AppSpawnConnection * connection,AppSpawnMsgNode * message)1801 static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message)
1802 {
1803 AppSpawnMsg *msg = &message->msgHeader;
1804 APPSPAWN_LOGI("Recv message header magic 0x%{public}x type %{public}u id %{public}u len %{public}u %{public}s",
1805 msg->magic, msg->msgType, msg->msgId, msg->msgLen, msg->processName);
1806 APPSPAWN_CHECK_ONLY_LOG(connection->receiverCtx.nextMsgId == msg->msgId,
1807 "Invalid msg id %{public}u %{public}u", connection->receiverCtx.nextMsgId, msg->msgId);
1808 connection->receiverCtx.nextMsgId++;
1809
1810 int ret;
1811 switch (msg->msgType) {
1812 case MSG_GET_RENDER_TERMINATION_STATUS: { // get status
1813 AppSpawnResult result = {0};
1814 ret = ProcessTerminationStatusMsg(message, &result);
1815 SendResponse(connection, msg, ret == 0 ? result.result : ret, result.pid);
1816 DeleteAppSpawnMsg(&message);
1817 break;
1818 }
1819 case MSG_SPAWN_NATIVE_PROCESS: // spawn msg
1820 case MSG_APP_SPAWN: {
1821 ProcessSpawnReqMsg(connection, message);
1822 break;
1823 }
1824 case MSG_DUMP:
1825 ProcessAppSpawnDumpMsg(message);
1826 SendResponse(connection, msg, 0, 0);
1827 DeleteAppSpawnMsg(&message);
1828 break;
1829 case MSG_BEGET_CMD: {
1830 ProcessBegetCmdMsg(connection, message);
1831 break;
1832 }
1833 case MSG_BEGET_SPAWNTIME:
1834 SendResponse(connection, msg, GetAppSpawnMgr()->spawnTime.minAppspawnTime,
1835 GetAppSpawnMgr()->spawnTime.maxAppspawnTime);
1836 DeleteAppSpawnMsg(&message);
1837 break;
1838 case MSG_UPDATE_MOUNT_POINTS:
1839 ret = ProcessSpawnRemountMsg(connection, message);
1840 SendResponse(connection, msg, ret, 0);
1841 break;
1842 case MSG_RESTART_SPAWNER:
1843 ProcessSpawnRestartMsg(connection, message);
1844 break;
1845 case MSG_DEVICE_DEBUG:
1846 ret = ProcessAppSpawnDeviceDebugMsg(message);
1847 SendResponse(connection, msg, ret, 0);
1848 DeleteAppSpawnMsg(&message);
1849 break;
1850 case MSG_UNINSTALL_DEBUG_HAP:
1851 ProcessUninstallDebugHap(connection, message);
1852 break;
1853 case MSG_LOCK_STATUS:
1854 ProcessAppSpawnLockStatusMsg(message);
1855 SendResponse(connection, msg, 0, 0);
1856 DeleteAppSpawnMsg(&message);
1857 break;
1858 case MSG_OBSERVE_PROCESS_SIGNAL_STATUS:
1859 ProcessObserveProcessSignalMsg(connection, message);
1860 break;
1861 case MSG_LOAD_WEBLIB_IN_APPSPAWN:
1862 ProcessSpawnDlopenMsg(connection, message);
1863 DeleteAppSpawnMsg(&message);
1864 break;
1865 default:
1866 SendResponse(connection, msg, APPSPAWN_MSG_INVALID, 0);
1867 DeleteAppSpawnMsg(&message);
1868 break;
1869 }
1870 }
1871