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
62static void WaitChildTimeout(const TimerHandle taskHandle, void *context);
63static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context);
64static void WaitChildDied(pid_t pid);
65static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen);
66static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message);
67
68#ifdef USE_ENCAPS
69static 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
79static void CloseDevEncaps(int fd)
80{
81    if (fd < 0) {
82        return;
83    }
84    close(fd);
85}
86#endif
87
88// FD_CLOEXEC
89static 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
98static 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
112static 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
142static 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
152static 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
183APPSPAWN_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
212static 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
224static 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
243static 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
252static 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
272static 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
287static 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
296static 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
308static 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
345APPSPAWN_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
367static 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
407APPSPAWN_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
428static 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
486static 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
511APPSPAWN_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
536static 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
549static 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
561static 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
575static int OpenPidFd(pid_t pid, unsigned int flags)
576{
577    return syscall(SYS_pidfd_open, pid, flags);
578}
579
580static 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
621static 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
630static 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
659static 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
675static 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
690fail:
691    munmap((char *)content->propertyBuffer, MAX_MEM_SIZE);
692    content->propertyBuffer = NULL;
693    return ret;
694}
695
696static 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
719static 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
738static 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
760static 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
805static 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
842static 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
861static 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
869static 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
884static 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
932static uint32_t g_lastDiedAppId = 0;
933static uint32_t g_crashTimes = 0;
934#define MAX_CRASH_TIME 5
935static 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
958static 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
973static 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
993static 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
1045static 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
1057static 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
1081void 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
1109APPSPAWN_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
1153static 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
1198static 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
1233static 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
1255APPSPAWN_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
1264static 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
1272AppSpawnContent *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
1296AppSpawnContent *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
1348static 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
1365static 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
1384static 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
1398static 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
1409static 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
1453static 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
1509static 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
1541APPSPAWN_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
1571APPSPAWN_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
1582APPSPAWN_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
1620static 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}