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