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