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