• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param);
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