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