169570cc8Sopenharmony_ci/* 269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License. 569570cc8Sopenharmony_ci * You may obtain a copy of the License at 669570cc8Sopenharmony_ci * 769570cc8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 869570cc8Sopenharmony_ci * 969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and 1369570cc8Sopenharmony_ci * limitations under the License. 1469570cc8Sopenharmony_ci */ 1569570cc8Sopenharmony_ci 1669570cc8Sopenharmony_ci#include "appspawn_service.h" 1769570cc8Sopenharmony_ci 1869570cc8Sopenharmony_ci#include <dirent.h> 1969570cc8Sopenharmony_ci#include <fcntl.h> 2069570cc8Sopenharmony_ci#include <stdio.h> 2169570cc8Sopenharmony_ci#include <stdlib.h> 2269570cc8Sopenharmony_ci#include <string.h> 2369570cc8Sopenharmony_ci#include <sys/signalfd.h> 2469570cc8Sopenharmony_ci#include <sys/socket.h> 2569570cc8Sopenharmony_ci#include <sys/wait.h> 2669570cc8Sopenharmony_ci#include <sys/mman.h> 2769570cc8Sopenharmony_ci#include <sys/syscall.h> 2869570cc8Sopenharmony_ci#include <signal.h> 2969570cc8Sopenharmony_ci#include <sys/mount.h> 3069570cc8Sopenharmony_ci#include <unistd.h> 3169570cc8Sopenharmony_ci#include <sys/prctl.h> 3269570cc8Sopenharmony_ci 3369570cc8Sopenharmony_ci#include "appspawn.h" 3469570cc8Sopenharmony_ci#include "appspawn_hook.h" 3569570cc8Sopenharmony_ci#include "appspawn_modulemgr.h" 3669570cc8Sopenharmony_ci#include "appspawn_manager.h" 3769570cc8Sopenharmony_ci#include "appspawn_msg.h" 3869570cc8Sopenharmony_ci#include "appspawn_server.h" 3969570cc8Sopenharmony_ci#include "appspawn_utils.h" 4069570cc8Sopenharmony_ci#include "init_socket.h" 4169570cc8Sopenharmony_ci#include "init_utils.h" 4269570cc8Sopenharmony_ci#include "parameter.h" 4369570cc8Sopenharmony_ci#include "appspawn_adapter.h" 4469570cc8Sopenharmony_ci#include "securec.h" 4569570cc8Sopenharmony_ci#include "cJSON.h" 4669570cc8Sopenharmony_ci#ifdef APPSPAWN_HISYSEVENT 4769570cc8Sopenharmony_ci#include "appspawn_hisysevent.h" 4869570cc8Sopenharmony_ci#endif 4969570cc8Sopenharmony_ci#ifdef USE_ENCAPS 5069570cc8Sopenharmony_ci#include <sys/ioctl.h> 5169570cc8Sopenharmony_ci#endif 5269570cc8Sopenharmony_ci#define PARAM_BUFFER_SIZE 10 5369570cc8Sopenharmony_ci#define PATH_SIZE 256 5469570cc8Sopenharmony_ci#define FD_PATH_SIZE 128 5569570cc8Sopenharmony_ci#define MAX_MEM_SIZE (4 * 1024) 5669570cc8Sopenharmony_ci#define APPSPAWN_MSG_USER_CHECK_COUNT 3 5769570cc8Sopenharmony_ci#define PREFORK_PROCESS "apppool" 5869570cc8Sopenharmony_ci#ifndef PIDFD_NONBLOCK 5969570cc8Sopenharmony_ci#define PIDFD_NONBLOCK O_NONBLOCK 6069570cc8Sopenharmony_ci#endif 6169570cc8Sopenharmony_ci 6269570cc8Sopenharmony_cistatic void WaitChildTimeout(const TimerHandle taskHandle, void *context); 6369570cc8Sopenharmony_cistatic void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context); 6469570cc8Sopenharmony_cistatic void WaitChildDied(pid_t pid); 6569570cc8Sopenharmony_cistatic void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen); 6669570cc8Sopenharmony_cistatic void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message); 6769570cc8Sopenharmony_ci 6869570cc8Sopenharmony_ci#ifdef USE_ENCAPS 6969570cc8Sopenharmony_cistatic int OpenDevEncaps(void) 7069570cc8Sopenharmony_ci{ 7169570cc8Sopenharmony_ci int fd = open("/dev/encaps", O_RDWR); 7269570cc8Sopenharmony_ci if (fd < 0) { 7369570cc8Sopenharmony_ci APPSPAWN_LOGE("AppSpawnChild SetEncapsFlag open failed"); 7469570cc8Sopenharmony_ci return -1; 7569570cc8Sopenharmony_ci } 7669570cc8Sopenharmony_ci return fd; 7769570cc8Sopenharmony_ci} 7869570cc8Sopenharmony_ci 7969570cc8Sopenharmony_cistatic void CloseDevEncaps(int fd) 8069570cc8Sopenharmony_ci{ 8169570cc8Sopenharmony_ci if (fd < 0) { 8269570cc8Sopenharmony_ci return; 8369570cc8Sopenharmony_ci } 8469570cc8Sopenharmony_ci close(fd); 8569570cc8Sopenharmony_ci} 8669570cc8Sopenharmony_ci#endif 8769570cc8Sopenharmony_ci 8869570cc8Sopenharmony_ci// FD_CLOEXEC 8969570cc8Sopenharmony_cistatic inline void SetFdCtrl(int fd, int opt) 9069570cc8Sopenharmony_ci{ 9169570cc8Sopenharmony_ci int option = fcntl(fd, F_GETFD); 9269570cc8Sopenharmony_ci int ret = fcntl(fd, F_SETFD, (unsigned int)option | (unsigned int)opt); 9369570cc8Sopenharmony_ci if (ret < 0) { 9469570cc8Sopenharmony_ci APPSPAWN_LOGI("Set fd %{public}d option %{public}d %{public}d result: %{public}d", fd, option, opt, errno); 9569570cc8Sopenharmony_ci } 9669570cc8Sopenharmony_ci} 9769570cc8Sopenharmony_ci 9869570cc8Sopenharmony_cistatic void AppQueueDestroyProc(const AppSpawnMgr *mgr, AppSpawnedProcess *appInfo, void *data) 9969570cc8Sopenharmony_ci{ 10069570cc8Sopenharmony_ci pid_t pid = appInfo->pid; 10169570cc8Sopenharmony_ci APPSPAWN_LOGI("kill %{public}s pid: %{public}d", appInfo->name, appInfo->pid); 10269570cc8Sopenharmony_ci // notify child proess died,clean sandbox info 10369570cc8Sopenharmony_ci ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo); 10469570cc8Sopenharmony_ci OH_ListRemove(&appInfo->node); 10569570cc8Sopenharmony_ci OH_ListInit(&appInfo->node); 10669570cc8Sopenharmony_ci free(appInfo); 10769570cc8Sopenharmony_ci if (pid > 0 && kill(pid, SIGKILL) != 0) { 10869570cc8Sopenharmony_ci APPSPAWN_LOGE("unable to kill process, pid: %{public}d errno: %{public}d", pid, errno); 10969570cc8Sopenharmony_ci } 11069570cc8Sopenharmony_ci} 11169570cc8Sopenharmony_ci 11269570cc8Sopenharmony_cistatic void StopAppSpawn(void) 11369570cc8Sopenharmony_ci{ 11469570cc8Sopenharmony_ci // delete nwespawn, and wait exit. Otherwise, the process of nwebspawn spawning will become zombie 11569570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = GetSpawnedProcessByName(NWEBSPAWN_SERVER_NAME); 11669570cc8Sopenharmony_ci if (appInfo != NULL) { 11769570cc8Sopenharmony_ci APPSPAWN_LOGI("kill %{public}s pid: %{public}d", appInfo->name, appInfo->pid); 11869570cc8Sopenharmony_ci int exitStatus = 0; 11969570cc8Sopenharmony_ci KillAndWaitStatus(appInfo->pid, SIGTERM, &exitStatus); 12069570cc8Sopenharmony_ci OH_ListRemove(&appInfo->node); 12169570cc8Sopenharmony_ci OH_ListInit(&appInfo->node); 12269570cc8Sopenharmony_ci free(appInfo); 12369570cc8Sopenharmony_ci } 12469570cc8Sopenharmony_ci // delete nativespawn, and wait exit. Otherwise, the process of nativespawn spawning will become zombie 12569570cc8Sopenharmony_ci appInfo = GetSpawnedProcessByName(NATIVESPAWN_SERVER_NAME); 12669570cc8Sopenharmony_ci if (appInfo != NULL) { 12769570cc8Sopenharmony_ci APPSPAWN_LOGI("kill %{public}s pid: %{public}d", appInfo->name, appInfo->pid); 12869570cc8Sopenharmony_ci int exitStatus = 0; 12969570cc8Sopenharmony_ci KillAndWaitStatus(appInfo->pid, SIGTERM, &exitStatus); 13069570cc8Sopenharmony_ci OH_ListRemove(&appInfo->node); 13169570cc8Sopenharmony_ci OH_ListInit(&appInfo->node); 13269570cc8Sopenharmony_ci free(appInfo); 13369570cc8Sopenharmony_ci } 13469570cc8Sopenharmony_ci TraversalSpawnedProcess(AppQueueDestroyProc, NULL); 13569570cc8Sopenharmony_ci APPSPAWN_LOGI("StopAppSpawn "); 13669570cc8Sopenharmony_ci#ifdef APPSPAWN_HISYSEVENT 13769570cc8Sopenharmony_ci AppSpawnHiSysEventWrite(); 13869570cc8Sopenharmony_ci#endif 13969570cc8Sopenharmony_ci LE_StopLoop(LE_GetDefaultLoop()); 14069570cc8Sopenharmony_ci} 14169570cc8Sopenharmony_ci 14269570cc8Sopenharmony_cistatic inline void DumpStatus(const char *appName, pid_t pid, int status) 14369570cc8Sopenharmony_ci{ 14469570cc8Sopenharmony_ci if (WIFSIGNALED(status)) { 14569570cc8Sopenharmony_ci APPSPAWN_LOGW("%{public}s with pid %{public}d exit with signal:%{public}d", appName, pid, WTERMSIG(status)); 14669570cc8Sopenharmony_ci } 14769570cc8Sopenharmony_ci if (WIFEXITED(status)) { 14869570cc8Sopenharmony_ci APPSPAWN_LOGW("%{public}s with pid %{public}d exit with code:%{public}d", appName, pid, WEXITSTATUS(status)); 14969570cc8Sopenharmony_ci } 15069570cc8Sopenharmony_ci} 15169570cc8Sopenharmony_ci 15269570cc8Sopenharmony_cistatic void HandleDiedPid(pid_t pid, uid_t uid, int status) 15369570cc8Sopenharmony_ci{ 15469570cc8Sopenharmony_ci AppSpawnContent *content = GetAppSpawnContent(); 15569570cc8Sopenharmony_ci if (pid == content->reservedPid) { 15669570cc8Sopenharmony_ci APPSPAWN_LOGW("HandleDiedPid with reservedPid %{public}d", pid); 15769570cc8Sopenharmony_ci content->reservedPid = 0; 15869570cc8Sopenharmony_ci } 15969570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = GetSpawnedProcess(pid); 16069570cc8Sopenharmony_ci if (appInfo == NULL) { // If an exception occurs during app spawning, kill pid, return failed 16169570cc8Sopenharmony_ci WaitChildDied(pid); 16269570cc8Sopenharmony_ci DumpStatus("unknown", pid, status); 16369570cc8Sopenharmony_ci return; 16469570cc8Sopenharmony_ci } 16569570cc8Sopenharmony_ci 16669570cc8Sopenharmony_ci appInfo->exitStatus = status; 16769570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_LOG(appInfo->uid == uid, "Invalid uid %{public}u %{public}u", appInfo->uid, uid); 16869570cc8Sopenharmony_ci DumpStatus(appInfo->name, pid, status); 16969570cc8Sopenharmony_ci ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo); 17069570cc8Sopenharmony_ci 17169570cc8Sopenharmony_ci // if current process of death is nwebspawn, restart appspawn 17269570cc8Sopenharmony_ci if (strcmp(appInfo->name, NWEBSPAWN_SERVER_NAME) == 0) { 17369570cc8Sopenharmony_ci OH_ListRemove(&appInfo->node); 17469570cc8Sopenharmony_ci free(appInfo); 17569570cc8Sopenharmony_ci APPSPAWN_LOGW("Current process of death is nwebspawn, pid = %{public}d, restart appspawn", pid); 17669570cc8Sopenharmony_ci StopAppSpawn(); 17769570cc8Sopenharmony_ci return; 17869570cc8Sopenharmony_ci } 17969570cc8Sopenharmony_ci // move app info to died queue in NWEBSPAWN, or delete appinfo 18069570cc8Sopenharmony_ci TerminateSpawnedProcess(appInfo); 18169570cc8Sopenharmony_ci} 18269570cc8Sopenharmony_ci 18369570cc8Sopenharmony_ciAPPSPAWN_STATIC void ProcessSignal(const struct signalfd_siginfo *siginfo) 18469570cc8Sopenharmony_ci{ 18569570cc8Sopenharmony_ci APPSPAWN_LOGI("ProcessSignal signum %{public}d %{public}d", siginfo->ssi_signo, siginfo->ssi_pid); 18669570cc8Sopenharmony_ci switch (siginfo->ssi_signo) { 18769570cc8Sopenharmony_ci case SIGCHLD: { // delete pid from app map 18869570cc8Sopenharmony_ci pid_t pid; 18969570cc8Sopenharmony_ci int status; 19069570cc8Sopenharmony_ci while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 19169570cc8Sopenharmony_ci APPSPAWN_CHECK(WIFSIGNALED(status) || WIFEXITED(status), return, 19269570cc8Sopenharmony_ci "ProcessSignal with wrong status:%{public}d", status); 19369570cc8Sopenharmony_ci HandleDiedPid(pid, siginfo->ssi_uid, status); 19469570cc8Sopenharmony_ci } 19569570cc8Sopenharmony_ci#if (defined(CJAPP_SPAWN) || defined(NATIVE_SPAWN)) 19669570cc8Sopenharmony_ci if (OH_ListGetCnt(&GetAppSpawnMgr()->appQueue) == 0) { 19769570cc8Sopenharmony_ci LE_StopLoop(LE_GetDefaultLoop()); 19869570cc8Sopenharmony_ci } 19969570cc8Sopenharmony_ci#endif 20069570cc8Sopenharmony_ci break; 20169570cc8Sopenharmony_ci } 20269570cc8Sopenharmony_ci case SIGTERM: { // appswapn killed, use kill without parameter 20369570cc8Sopenharmony_ci StopAppSpawn(); 20469570cc8Sopenharmony_ci break; 20569570cc8Sopenharmony_ci } 20669570cc8Sopenharmony_ci default: 20769570cc8Sopenharmony_ci APPSPAWN_LOGI("SigHandler, unsupported signal %{public}d.", siginfo->ssi_signo); 20869570cc8Sopenharmony_ci break; 20969570cc8Sopenharmony_ci } 21069570cc8Sopenharmony_ci} 21169570cc8Sopenharmony_ci 21269570cc8Sopenharmony_cistatic void AppSpawningCtxOnClose(const AppSpawnMgr *mgr, AppSpawningCtx *ctx, void *data) 21369570cc8Sopenharmony_ci{ 21469570cc8Sopenharmony_ci if (ctx == NULL || ctx->message == NULL || ctx->message->connection != data) { 21569570cc8Sopenharmony_ci return; 21669570cc8Sopenharmony_ci } 21769570cc8Sopenharmony_ci APPSPAWN_LOGI("Kill process, pid: %{public}d app: %{public}s", ctx->pid, GetProcessName(ctx)); 21869570cc8Sopenharmony_ci if (ctx->pid > 0 && kill(ctx->pid, SIGKILL) != 0) { 21969570cc8Sopenharmony_ci APPSPAWN_LOGE("unable to kill process, pid: %{public}d errno: %{public}d", ctx->pid, errno); 22069570cc8Sopenharmony_ci } 22169570cc8Sopenharmony_ci DeleteAppSpawningCtx(ctx); 22269570cc8Sopenharmony_ci} 22369570cc8Sopenharmony_ci 22469570cc8Sopenharmony_cistatic void OnClose(const TaskHandle taskHandle) 22569570cc8Sopenharmony_ci{ 22669570cc8Sopenharmony_ci if (!IsSpawnServer(GetAppSpawnMgr())) { 22769570cc8Sopenharmony_ci return; 22869570cc8Sopenharmony_ci } 22969570cc8Sopenharmony_ci AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle); 23069570cc8Sopenharmony_ci APPSPAWN_CHECK(connection != NULL, return, "Invalid connection"); 23169570cc8Sopenharmony_ci if (connection->receiverCtx.timer) { 23269570cc8Sopenharmony_ci LE_StopTimer(LE_GetDefaultLoop(), connection->receiverCtx.timer); 23369570cc8Sopenharmony_ci connection->receiverCtx.timer = NULL; 23469570cc8Sopenharmony_ci } 23569570cc8Sopenharmony_ci APPSPAWN_LOGI("OnClose connectionId: %{public}u socket %{public}d", 23669570cc8Sopenharmony_ci connection->connectionId, LE_GetSocketFd(taskHandle)); 23769570cc8Sopenharmony_ci DeleteAppSpawnMsg(connection->receiverCtx.incompleteMsg); 23869570cc8Sopenharmony_ci connection->receiverCtx.incompleteMsg = NULL; 23969570cc8Sopenharmony_ci // connect close, to close spawning app 24069570cc8Sopenharmony_ci AppSpawningCtxTraversal(AppSpawningCtxOnClose, connection); 24169570cc8Sopenharmony_ci} 24269570cc8Sopenharmony_ci 24369570cc8Sopenharmony_cistatic void OnDisConnect(const TaskHandle taskHandle) 24469570cc8Sopenharmony_ci{ 24569570cc8Sopenharmony_ci AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle); 24669570cc8Sopenharmony_ci APPSPAWN_CHECK(connection != NULL, return, "Invalid connection"); 24769570cc8Sopenharmony_ci APPSPAWN_LOGI("OnDisConnect connectionId: %{public}u socket %{public}d", 24869570cc8Sopenharmony_ci connection->connectionId, LE_GetSocketFd(taskHandle)); 24969570cc8Sopenharmony_ci OnClose(taskHandle); 25069570cc8Sopenharmony_ci} 25169570cc8Sopenharmony_ci 25269570cc8Sopenharmony_cistatic void SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle) 25369570cc8Sopenharmony_ci{ 25469570cc8Sopenharmony_ci AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle); 25569570cc8Sopenharmony_ci APPSPAWN_CHECK(connection != NULL, return, "Invalid connection"); 25669570cc8Sopenharmony_ci uint32_t bufferSize = sizeof(AppSpawnResponseMsg); 25769570cc8Sopenharmony_ci AppSpawnResponseMsg *msg = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, NULL, &bufferSize); 25869570cc8Sopenharmony_ci if (msg == NULL) { 25969570cc8Sopenharmony_ci return; 26069570cc8Sopenharmony_ci } 26169570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = GetSpawnedProcess(msg->result.pid); 26269570cc8Sopenharmony_ci if (appInfo == NULL) { 26369570cc8Sopenharmony_ci return; 26469570cc8Sopenharmony_ci } 26569570cc8Sopenharmony_ci APPSPAWN_LOGI("SendMessageComplete connectionId: %{public}u result %{public}d app %{public}s pid %{public}d", 26669570cc8Sopenharmony_ci connection->connectionId, LE_GetSendResult(handle), appInfo->name, msg->result.pid); 26769570cc8Sopenharmony_ci if (LE_GetSendResult(handle) != 0 && msg->result.pid > 0) { 26869570cc8Sopenharmony_ci kill(msg->result.pid, SIGKILL); 26969570cc8Sopenharmony_ci } 27069570cc8Sopenharmony_ci} 27169570cc8Sopenharmony_ci 27269570cc8Sopenharmony_cistatic int SendResponse(const AppSpawnConnection *connection, const AppSpawnMsg *msg, int result, pid_t pid) 27369570cc8Sopenharmony_ci{ 27469570cc8Sopenharmony_ci APPSPAWN_LOGV("SendResponse connectionId: %{public}u result: 0x%{public}x pid: %{public}d", 27569570cc8Sopenharmony_ci connection->connectionId, result, pid); 27669570cc8Sopenharmony_ci uint32_t bufferSize = sizeof(AppSpawnResponseMsg); 27769570cc8Sopenharmony_ci BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize); 27869570cc8Sopenharmony_ci AppSpawnResponseMsg *buffer = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, NULL, &bufferSize); 27969570cc8Sopenharmony_ci int ret = memcpy_s(buffer, bufferSize, msg, sizeof(AppSpawnMsg)); 28069570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, LE_FreeBuffer(LE_GetDefaultLoop(), NULL, handle); 28169570cc8Sopenharmony_ci return -1, "Failed to memcpy_s bufferSize"); 28269570cc8Sopenharmony_ci buffer->result.result = result; 28369570cc8Sopenharmony_ci buffer->result.pid = pid; 28469570cc8Sopenharmony_ci return LE_Send(LE_GetDefaultLoop(), connection->stream, handle, bufferSize); 28569570cc8Sopenharmony_ci} 28669570cc8Sopenharmony_ci 28769570cc8Sopenharmony_cistatic void WaitMsgCompleteTimeOut(const TimerHandle taskHandle, void *context) 28869570cc8Sopenharmony_ci{ 28969570cc8Sopenharmony_ci AppSpawnConnection *connection = (AppSpawnConnection *)context; 29069570cc8Sopenharmony_ci APPSPAWN_LOGE("Long time no msg complete so close connectionId: %{public}u", connection->connectionId); 29169570cc8Sopenharmony_ci DeleteAppSpawnMsg(connection->receiverCtx.incompleteMsg); 29269570cc8Sopenharmony_ci connection->receiverCtx.incompleteMsg = NULL; 29369570cc8Sopenharmony_ci LE_CloseStreamTask(LE_GetDefaultLoop(), connection->stream); 29469570cc8Sopenharmony_ci} 29569570cc8Sopenharmony_ci 29669570cc8Sopenharmony_cistatic inline int StartTimerForCheckMsg(AppSpawnConnection *connection) 29769570cc8Sopenharmony_ci{ 29869570cc8Sopenharmony_ci if (connection->receiverCtx.timer != NULL) { 29969570cc8Sopenharmony_ci return 0; 30069570cc8Sopenharmony_ci } 30169570cc8Sopenharmony_ci int ret = LE_CreateTimer(LE_GetDefaultLoop(), &connection->receiverCtx.timer, WaitMsgCompleteTimeOut, connection); 30269570cc8Sopenharmony_ci if (ret == 0) { 30369570cc8Sopenharmony_ci ret = LE_StartTimer(LE_GetDefaultLoop(), connection->receiverCtx.timer, MAX_WAIT_MSG_COMPLETE, 1); 30469570cc8Sopenharmony_ci } 30569570cc8Sopenharmony_ci return ret; 30669570cc8Sopenharmony_ci} 30769570cc8Sopenharmony_ci 30869570cc8Sopenharmony_cistatic int HandleRecvMessage(const TaskHandle taskHandle, uint8_t * buffer, int bufferSize, int flags) 30969570cc8Sopenharmony_ci{ 31069570cc8Sopenharmony_ci int socketFd = LE_GetSocketFd(taskHandle); 31169570cc8Sopenharmony_ci struct iovec iov = { 31269570cc8Sopenharmony_ci .iov_base = buffer, 31369570cc8Sopenharmony_ci .iov_len = bufferSize, 31469570cc8Sopenharmony_ci }; 31569570cc8Sopenharmony_ci char ctrlBuffer[CMSG_SPACE(APP_MAX_FD_COUNT * sizeof(int))]; 31669570cc8Sopenharmony_ci struct msghdr msg = { 31769570cc8Sopenharmony_ci .msg_iov = &iov, 31869570cc8Sopenharmony_ci .msg_iovlen = 1, 31969570cc8Sopenharmony_ci .msg_control = ctrlBuffer, 32069570cc8Sopenharmony_ci .msg_controllen = sizeof(ctrlBuffer), 32169570cc8Sopenharmony_ci }; 32269570cc8Sopenharmony_ci 32369570cc8Sopenharmony_ci AppSpawnConnection *connection = (AppSpawnConnection *) LE_GetUserData(taskHandle); 32469570cc8Sopenharmony_ci APPSPAWN_CHECK(connection != NULL, return -1, "Invalid connection"); 32569570cc8Sopenharmony_ci errno = 0; 32669570cc8Sopenharmony_ci int recvLen = recvmsg(socketFd, &msg, flags); 32769570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_LOG(errno == 0, "recvmsg with errno %{public}d", errno); 32869570cc8Sopenharmony_ci struct cmsghdr *cmsg = NULL; 32969570cc8Sopenharmony_ci for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 33069570cc8Sopenharmony_ci if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { 33169570cc8Sopenharmony_ci int fdCount = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); 33269570cc8Sopenharmony_ci int *fd = (int *) CMSG_DATA(cmsg); 33369570cc8Sopenharmony_ci APPSPAWN_CHECK(fdCount <= APP_MAX_FD_COUNT, return -1, 33469570cc8Sopenharmony_ci "failed to recv fd %{public}d %{public}d", connection->receiverCtx.fdCount, fdCount); 33569570cc8Sopenharmony_ci int ret = memcpy_s(connection->receiverCtx.fds, 33669570cc8Sopenharmony_ci fdCount * sizeof(int), fd, fdCount * sizeof(int)); 33769570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return -1, "memcpy_s fd ret %{public}d", ret); 33869570cc8Sopenharmony_ci connection->receiverCtx.fdCount = fdCount; 33969570cc8Sopenharmony_ci } 34069570cc8Sopenharmony_ci } 34169570cc8Sopenharmony_ci 34269570cc8Sopenharmony_ci return recvLen; 34369570cc8Sopenharmony_ci} 34469570cc8Sopenharmony_ci 34569570cc8Sopenharmony_ciAPPSPAWN_STATIC bool OnConnectionUserCheck(uid_t uid) 34669570cc8Sopenharmony_ci{ 34769570cc8Sopenharmony_ci const uid_t uids[APPSPAWN_MSG_USER_CHECK_COUNT] = { 34869570cc8Sopenharmony_ci 0, // root 0 34969570cc8Sopenharmony_ci 3350, // app_fwk_update 3350 35069570cc8Sopenharmony_ci 5523, // foundation 5523 35169570cc8Sopenharmony_ci }; 35269570cc8Sopenharmony_ci 35369570cc8Sopenharmony_ci for (int i = 0; i < APPSPAWN_MSG_USER_CHECK_COUNT; i++) { 35469570cc8Sopenharmony_ci if (uid == uids[i]) { 35569570cc8Sopenharmony_ci return true; 35669570cc8Sopenharmony_ci } 35769570cc8Sopenharmony_ci } 35869570cc8Sopenharmony_ci 35969570cc8Sopenharmony_ci // shell 2000 36069570cc8Sopenharmony_ci if (uid == 2000 && IsDeveloperModeOpen()) { 36169570cc8Sopenharmony_ci return true; 36269570cc8Sopenharmony_ci } 36369570cc8Sopenharmony_ci 36469570cc8Sopenharmony_ci return false; 36569570cc8Sopenharmony_ci} 36669570cc8Sopenharmony_ci 36769570cc8Sopenharmony_cistatic int OnConnection(const LoopHandle loopHandle, const TaskHandle server) 36869570cc8Sopenharmony_ci{ 36969570cc8Sopenharmony_ci APPSPAWN_CHECK(server != NULL && loopHandle != NULL, return -1, "Error server"); 37069570cc8Sopenharmony_ci static uint32_t connectionId = 0; 37169570cc8Sopenharmony_ci TaskHandle stream; 37269570cc8Sopenharmony_ci LE_StreamInfo info = {}; 37369570cc8Sopenharmony_ci info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT; 37469570cc8Sopenharmony_ci info.baseInfo.close = OnClose; 37569570cc8Sopenharmony_ci info.baseInfo.userDataSize = sizeof(AppSpawnConnection); 37669570cc8Sopenharmony_ci info.disConnectComplete = OnDisConnect; 37769570cc8Sopenharmony_ci info.sendMessageComplete = SendMessageComplete; 37869570cc8Sopenharmony_ci info.recvMessage = OnReceiveRequest; 37969570cc8Sopenharmony_ci info.handleRecvMsg = HandleRecvMessage; 38069570cc8Sopenharmony_ci LE_STATUS ret = LE_AcceptStreamClient(loopHandle, server, &stream, &info); 38169570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return -1, "Failed to alloc stream"); 38269570cc8Sopenharmony_ci 38369570cc8Sopenharmony_ci AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(stream); 38469570cc8Sopenharmony_ci APPSPAWN_CHECK(connection != NULL, return -1, "Failed to alloc stream"); 38569570cc8Sopenharmony_ci struct ucred cred = {-1, -1, -1}; 38669570cc8Sopenharmony_ci socklen_t credSize = sizeof(struct ucred); 38769570cc8Sopenharmony_ci if ((getsockopt(LE_GetSocketFd(stream), SOL_SOCKET, SO_PEERCRED, &cred, &credSize) < 0) || 38869570cc8Sopenharmony_ci !OnConnectionUserCheck(cred.uid)) { 38969570cc8Sopenharmony_ci APPSPAWN_LOGE("Invalid uid %{public}d from client", cred.uid); 39069570cc8Sopenharmony_ci LE_CloseStreamTask(LE_GetDefaultLoop(), stream); 39169570cc8Sopenharmony_ci return -1; 39269570cc8Sopenharmony_ci } 39369570cc8Sopenharmony_ci SetFdCtrl(LE_GetSocketFd(stream), FD_CLOEXEC); 39469570cc8Sopenharmony_ci 39569570cc8Sopenharmony_ci connection->connectionId = ++connectionId; 39669570cc8Sopenharmony_ci connection->stream = stream; 39769570cc8Sopenharmony_ci connection->receiverCtx.fdCount = 0; 39869570cc8Sopenharmony_ci connection->receiverCtx.incompleteMsg = NULL; 39969570cc8Sopenharmony_ci connection->receiverCtx.timer = NULL; 40069570cc8Sopenharmony_ci connection->receiverCtx.msgRecvLen = 0; 40169570cc8Sopenharmony_ci connection->receiverCtx.nextMsgId = 1; 40269570cc8Sopenharmony_ci APPSPAWN_LOGI("OnConnection connectionId: %{public}u fd %{public}d ", 40369570cc8Sopenharmony_ci connection->connectionId, LE_GetSocketFd(stream)); 40469570cc8Sopenharmony_ci return 0; 40569570cc8Sopenharmony_ci} 40669570cc8Sopenharmony_ci 40769570cc8Sopenharmony_ciAPPSPAWN_STATIC bool MsgDevicedebugCheck(TaskHandle stream, AppSpawnMsgNode *message) 40869570cc8Sopenharmony_ci{ 40969570cc8Sopenharmony_ci struct ucred cred = {0, 0, 0}; 41069570cc8Sopenharmony_ci socklen_t credSize = sizeof(cred); 41169570cc8Sopenharmony_ci if (getsockopt(LE_GetSocketFd(stream), SOL_SOCKET, SO_PEERCRED, &cred, &credSize) < 0) { 41269570cc8Sopenharmony_ci return false; 41369570cc8Sopenharmony_ci } 41469570cc8Sopenharmony_ci 41569570cc8Sopenharmony_ci if (cred.uid != DecodeUid("shell")) { 41669570cc8Sopenharmony_ci return true; 41769570cc8Sopenharmony_ci } 41869570cc8Sopenharmony_ci 41969570cc8Sopenharmony_ci AppSpawnMsg *msg = &message->msgHeader; 42069570cc8Sopenharmony_ci if (msg->msgType != MSG_DEVICE_DEBUG) { 42169570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug msg type is not devicedebug [%{public}d]", msg->msgType); 42269570cc8Sopenharmony_ci return false; 42369570cc8Sopenharmony_ci } 42469570cc8Sopenharmony_ci 42569570cc8Sopenharmony_ci return true; 42669570cc8Sopenharmony_ci} 42769570cc8Sopenharmony_ci 42869570cc8Sopenharmony_cistatic void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen) 42969570cc8Sopenharmony_ci{ 43069570cc8Sopenharmony_ci AppSpawnConnection *connection = (AppSpawnConnection *)LE_GetUserData(taskHandle); 43169570cc8Sopenharmony_ci APPSPAWN_CHECK(connection != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); 43269570cc8Sopenharmony_ci return, "Failed to get client form socket"); 43369570cc8Sopenharmony_ci APPSPAWN_CHECK(buffLen < MAX_MSG_TOTAL_LENGTH, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); 43469570cc8Sopenharmony_ci return, "Message too long %{public}u", buffLen); 43569570cc8Sopenharmony_ci 43669570cc8Sopenharmony_ci uint32_t reminder = 0; 43769570cc8Sopenharmony_ci uint32_t currLen = 0; 43869570cc8Sopenharmony_ci AppSpawnMsgNode *message = connection->receiverCtx.incompleteMsg; // incomplete msg 43969570cc8Sopenharmony_ci connection->receiverCtx.incompleteMsg = NULL; 44069570cc8Sopenharmony_ci int ret = 0; 44169570cc8Sopenharmony_ci do { 44269570cc8Sopenharmony_ci APPSPAWN_LOGI("OnReceiveRequest connectionId: %{public}u start: 0x%{public}x buffLen %{public}d", 44369570cc8Sopenharmony_ci connection->connectionId, *(uint32_t *)(buffer + currLen), buffLen - currLen); 44469570cc8Sopenharmony_ci 44569570cc8Sopenharmony_ci ret = GetAppSpawnMsgFromBuffer(buffer + currLen, buffLen - currLen, 44669570cc8Sopenharmony_ci &message, &connection->receiverCtx.msgRecvLen, &reminder); 44769570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); 44869570cc8Sopenharmony_ci 44969570cc8Sopenharmony_ci if (connection->receiverCtx.msgRecvLen != message->msgHeader.msgLen) { // recv complete msg 45069570cc8Sopenharmony_ci connection->receiverCtx.incompleteMsg = message; 45169570cc8Sopenharmony_ci message = NULL; 45269570cc8Sopenharmony_ci break; 45369570cc8Sopenharmony_ci } 45469570cc8Sopenharmony_ci connection->receiverCtx.msgRecvLen = 0; 45569570cc8Sopenharmony_ci if (connection->receiverCtx.timer) { 45669570cc8Sopenharmony_ci LE_StopTimer(LE_GetDefaultLoop(), connection->receiverCtx.timer); 45769570cc8Sopenharmony_ci connection->receiverCtx.timer = NULL; 45869570cc8Sopenharmony_ci } 45969570cc8Sopenharmony_ci 46069570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(MsgDevicedebugCheck(connection->stream, message), 46169570cc8Sopenharmony_ci LE_CloseTask(LE_GetDefaultLoop(), taskHandle); return); 46269570cc8Sopenharmony_ci 46369570cc8Sopenharmony_ci // decode msg 46469570cc8Sopenharmony_ci ret = DecodeAppSpawnMsg(message); 46569570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); 46669570cc8Sopenharmony_ci (void)ProcessRecvMsg(connection, message); 46769570cc8Sopenharmony_ci message = NULL; 46869570cc8Sopenharmony_ci currLen += buffLen - reminder; 46969570cc8Sopenharmony_ci } while (reminder > 0); 47069570cc8Sopenharmony_ci 47169570cc8Sopenharmony_ci if (message) { 47269570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 47369570cc8Sopenharmony_ci } 47469570cc8Sopenharmony_ci if (ret != 0) { 47569570cc8Sopenharmony_ci LE_CloseTask(LE_GetDefaultLoop(), taskHandle); 47669570cc8Sopenharmony_ci return; 47769570cc8Sopenharmony_ci } 47869570cc8Sopenharmony_ci if (connection->receiverCtx.incompleteMsg != NULL) { // Start the detection timer 47969570cc8Sopenharmony_ci ret = StartTimerForCheckMsg(connection); 48069570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, LE_CloseStreamTask(LE_GetDefaultLoop(), taskHandle); 48169570cc8Sopenharmony_ci return, "Failed to create time for connection"); 48269570cc8Sopenharmony_ci } 48369570cc8Sopenharmony_ci return; 48469570cc8Sopenharmony_ci} 48569570cc8Sopenharmony_ci 48669570cc8Sopenharmony_cistatic char *GetMapMem(uint32_t clientId, const char *processName, uint32_t size, bool readOnly, bool isNweb) 48769570cc8Sopenharmony_ci{ 48869570cc8Sopenharmony_ci char path[PATH_MAX] = {}; 48969570cc8Sopenharmony_ci int len = sprintf_s(path, sizeof(path), APPSPAWN_MSG_DIR "%s/%s_%u", 49069570cc8Sopenharmony_ci isNweb ? "nwebspawn" : "appspawn", processName, clientId); 49169570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 0, return NULL, "Failed to format path %{public}s", processName); 49269570cc8Sopenharmony_ci APPSPAWN_LOGV("GetMapMem for child %{public}s memSize %{public}u", path, size); 49369570cc8Sopenharmony_ci int prot = PROT_READ; 49469570cc8Sopenharmony_ci int mode = O_RDONLY; 49569570cc8Sopenharmony_ci if (!readOnly) { 49669570cc8Sopenharmony_ci mode = O_CREAT | O_RDWR | O_TRUNC; 49769570cc8Sopenharmony_ci prot = PROT_READ | PROT_WRITE; 49869570cc8Sopenharmony_ci } 49969570cc8Sopenharmony_ci int fd = open(path, mode, S_IRWXU); 50069570cc8Sopenharmony_ci APPSPAWN_CHECK(fd >= 0, return NULL, "Failed to open errno %{public}d path %{public}s", errno, path); 50169570cc8Sopenharmony_ci if (!readOnly) { 50269570cc8Sopenharmony_ci ftruncate(fd, size); 50369570cc8Sopenharmony_ci } 50469570cc8Sopenharmony_ci void *areaAddr = (void *)mmap(NULL, size, prot, MAP_SHARED, fd, 0); 50569570cc8Sopenharmony_ci close(fd); 50669570cc8Sopenharmony_ci APPSPAWN_CHECK(areaAddr != MAP_FAILED && areaAddr != NULL, 50769570cc8Sopenharmony_ci return NULL, "Failed to map memory error %{public}d fileName %{public}s ", errno, path); 50869570cc8Sopenharmony_ci return (char *)areaAddr; 50969570cc8Sopenharmony_ci} 51069570cc8Sopenharmony_ci 51169570cc8Sopenharmony_ciAPPSPAWN_STATIC int WriteMsgToChild(AppSpawningCtx *property, bool isNweb) 51269570cc8Sopenharmony_ci{ 51369570cc8Sopenharmony_ci APPSPAWN_CHECK(property != NULL && property->message != NULL, return APPSPAWN_MSG_INVALID, 51469570cc8Sopenharmony_ci "Failed to WriteMsgToChild property invalid"); 51569570cc8Sopenharmony_ci const uint32_t memSize = (property->message->msgHeader.msgLen / 4096 + 1) * 4096; // 4096 4K 51669570cc8Sopenharmony_ci char *buffer = GetMapMem(property->client.id, GetProcessName(property), memSize, false, isNweb); 51769570cc8Sopenharmony_ci APPSPAWN_CHECK(buffer != NULL, return APPSPAWN_SYSTEM_ERROR, 51869570cc8Sopenharmony_ci "Failed to map memory error %{public}d fileName %{public}s ", errno, GetProcessName(property)); 51969570cc8Sopenharmony_ci // copy msg header 52069570cc8Sopenharmony_ci int ret = memcpy_s(buffer, memSize, &property->message->msgHeader, sizeof(AppSpawnMsg)); 52169570cc8Sopenharmony_ci if (ret == 0) { 52269570cc8Sopenharmony_ci ret = memcpy_s((char *)buffer + sizeof(AppSpawnMsg), memSize - sizeof(AppSpawnMsg), 52369570cc8Sopenharmony_ci property->message->buffer, property->message->msgHeader.msgLen - sizeof(AppSpawnMsg)); 52469570cc8Sopenharmony_ci } 52569570cc8Sopenharmony_ci if (ret != 0) { 52669570cc8Sopenharmony_ci APPSPAWN_LOGE("Failed to copy msg fileName %{public}s ", GetProcessName(property)); 52769570cc8Sopenharmony_ci munmap((char *)buffer, memSize); 52869570cc8Sopenharmony_ci return APPSPAWN_SYSTEM_ERROR; 52969570cc8Sopenharmony_ci } 53069570cc8Sopenharmony_ci property->forkCtx.msgSize = memSize; 53169570cc8Sopenharmony_ci property->forkCtx.childMsg = buffer; 53269570cc8Sopenharmony_ci APPSPAWN_LOGV("Write msg to child: %{public}u success", property->client.id); 53369570cc8Sopenharmony_ci return 0; 53469570cc8Sopenharmony_ci} 53569570cc8Sopenharmony_ci 53669570cc8Sopenharmony_cistatic int InitForkContext(AppSpawningCtx *property) 53769570cc8Sopenharmony_ci{ 53869570cc8Sopenharmony_ci if (pipe(property->forkCtx.fd) == -1) { 53969570cc8Sopenharmony_ci APPSPAWN_LOGE("create pipe fail, errno: %{public}d", errno); 54069570cc8Sopenharmony_ci return errno; 54169570cc8Sopenharmony_ci } 54269570cc8Sopenharmony_ci int option = fcntl(property->forkCtx.fd[0], F_GETFD); 54369570cc8Sopenharmony_ci if (option > 0) { 54469570cc8Sopenharmony_ci (void)fcntl(property->forkCtx.fd[0], F_SETFD, (unsigned int)option | O_NONBLOCK); 54569570cc8Sopenharmony_ci } 54669570cc8Sopenharmony_ci return 0; 54769570cc8Sopenharmony_ci} 54869570cc8Sopenharmony_ci 54969570cc8Sopenharmony_cistatic void ClosePidfdWatcher(const TaskHandle taskHandle) 55069570cc8Sopenharmony_ci{ 55169570cc8Sopenharmony_ci int fd = LE_GetSocketFd(taskHandle); 55269570cc8Sopenharmony_ci if (fd >= 0) { 55369570cc8Sopenharmony_ci close(fd); 55469570cc8Sopenharmony_ci } 55569570cc8Sopenharmony_ci void *p = LE_GetUserData(taskHandle); 55669570cc8Sopenharmony_ci if (p != NULL) { 55769570cc8Sopenharmony_ci free(*(void **)p); 55869570cc8Sopenharmony_ci } 55969570cc8Sopenharmony_ci} 56069570cc8Sopenharmony_ci 56169570cc8Sopenharmony_cistatic void ProcessChildProcessFd(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context) 56269570cc8Sopenharmony_ci{ 56369570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return); 56469570cc8Sopenharmony_ci pid_t pid = *(pid_t *)context; 56569570cc8Sopenharmony_ci APPSPAWN_LOGI("Kill process group with process group id %{public}d, pidFd %{public}d", pid, fd); 56669570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = GetSpawnedProcess(pid); 56769570cc8Sopenharmony_ci if (appInfo == NULL) { 56869570cc8Sopenharmony_ci APPSPAWN_LOGW("Cannot get app info by bundle name: %{public}d", pid); 56969570cc8Sopenharmony_ci return; 57069570cc8Sopenharmony_ci } 57169570cc8Sopenharmony_ci ProcessMgrHookExecute(STAGE_SERVER_APP_DIED, GetAppSpawnContent(), appInfo); 57269570cc8Sopenharmony_ci LE_CloseTask(LE_GetDefaultLoop(), taskHandle); 57369570cc8Sopenharmony_ci} 57469570cc8Sopenharmony_ci 57569570cc8Sopenharmony_cistatic int OpenPidFd(pid_t pid, unsigned int flags) 57669570cc8Sopenharmony_ci{ 57769570cc8Sopenharmony_ci return syscall(SYS_pidfd_open, pid, flags); 57869570cc8Sopenharmony_ci} 57969570cc8Sopenharmony_ci 58069570cc8Sopenharmony_cistatic void WatchChildProcessFd(AppSpawningCtx *property) 58169570cc8Sopenharmony_ci{ 58269570cc8Sopenharmony_ci if (property->pid <= 0) { 58369570cc8Sopenharmony_ci APPSPAWN_LOGW("Invalid child process pid, skip watch"); 58469570cc8Sopenharmony_ci return; 58569570cc8Sopenharmony_ci } 58669570cc8Sopenharmony_ci if (IsNWebSpawnMode((AppSpawnMgr *)GetAppSpawnContent())) { 58769570cc8Sopenharmony_ci APPSPAWN_LOGV("Nwebspawn don't need add pidfd"); 58869570cc8Sopenharmony_ci return; 58969570cc8Sopenharmony_ci } 59069570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = GetSpawnedProcess(property->pid); 59169570cc8Sopenharmony_ci if (appInfo == NULL) { 59269570cc8Sopenharmony_ci APPSPAWN_LOGW("Cannot get app info of pid %{public}d", property->pid); 59369570cc8Sopenharmony_ci return; 59469570cc8Sopenharmony_ci } 59569570cc8Sopenharmony_ci int fd = OpenPidFd(property->pid, PIDFD_NONBLOCK); // PIDFD_NONBLOCK since Linux kernel 5.10 59669570cc8Sopenharmony_ci if (fd < 0) { 59769570cc8Sopenharmony_ci APPSPAWN_LOGW("Failed to open pid fd for app: %{public}s, err = %{public}d", 59869570cc8Sopenharmony_ci GetBundleName(property), errno); 59969570cc8Sopenharmony_ci return; 60069570cc8Sopenharmony_ci } 60169570cc8Sopenharmony_ci APPSPAWN_LOGI("watch app process pid %{public}d, pidFd %{public}d", property->pid, fd); 60269570cc8Sopenharmony_ci LE_WatchInfo watchInfo = {}; 60369570cc8Sopenharmony_ci watchInfo.fd = fd; 60469570cc8Sopenharmony_ci watchInfo.flags = WATCHER_ONCE; 60569570cc8Sopenharmony_ci watchInfo.events = EVENT_READ; 60669570cc8Sopenharmony_ci watchInfo.close = ClosePidfdWatcher; 60769570cc8Sopenharmony_ci watchInfo.processEvent = ProcessChildProcessFd; 60869570cc8Sopenharmony_ci 60969570cc8Sopenharmony_ci pid_t *appPid = (pid_t *)malloc(sizeof(pid_t)); 61069570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(appPid != NULL, return); 61169570cc8Sopenharmony_ci *appPid = property->pid; 61269570cc8Sopenharmony_ci LE_STATUS status = LE_StartWatcher(LE_GetDefaultLoop(), &property->forkCtx.pidFdWatcherHandle, &watchInfo, appPid); 61369570cc8Sopenharmony_ci if (status != LE_SUCCESS) { 61469570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST 61569570cc8Sopenharmony_ci close(fd); 61669570cc8Sopenharmony_ci#endif 61769570cc8Sopenharmony_ci APPSPAWN_LOGW("Failed to watch child pid fd, pid is %{public}d", property->pid); 61869570cc8Sopenharmony_ci } 61969570cc8Sopenharmony_ci} 62069570cc8Sopenharmony_ci 62169570cc8Sopenharmony_cistatic int IsChildColdRun(AppSpawningCtx *property) 62269570cc8Sopenharmony_ci{ 62369570cc8Sopenharmony_ci return CheckAppMsgFlagsSet(property, APP_FLAGS_UBSAN_ENABLED) 62469570cc8Sopenharmony_ci || CheckAppMsgFlagsSet(property, APP_FLAGS_ASANENABLED) 62569570cc8Sopenharmony_ci || CheckAppMsgFlagsSet(property, APP_FLAGS_TSAN_ENABLED) 62669570cc8Sopenharmony_ci || CheckAppMsgFlagsSet(property, APP_FLAGS_HWASAN_ENABLED) 62769570cc8Sopenharmony_ci || (property->client.flags & APP_COLD_START); 62869570cc8Sopenharmony_ci} 62969570cc8Sopenharmony_ci 63069570cc8Sopenharmony_cistatic int AddChildWatcher(AppSpawningCtx *property) 63169570cc8Sopenharmony_ci{ 63269570cc8Sopenharmony_ci uint32_t defTimeout = IsChildColdRun(property) ? COLD_CHILD_RESPONSE_TIMEOUT : WAIT_CHILD_RESPONSE_TIMEOUT; 63369570cc8Sopenharmony_ci uint32_t timeout = GetSpawnTimeout(defTimeout); 63469570cc8Sopenharmony_ci LE_WatchInfo watchInfo = {}; 63569570cc8Sopenharmony_ci watchInfo.fd = property->forkCtx.fd[0]; 63669570cc8Sopenharmony_ci watchInfo.flags = WATCHER_ONCE; 63769570cc8Sopenharmony_ci watchInfo.events = EVENT_READ; 63869570cc8Sopenharmony_ci watchInfo.processEvent = ProcessChildResponse; 63969570cc8Sopenharmony_ci LE_STATUS status = LE_StartWatcher(LE_GetDefaultLoop(), &property->forkCtx.watcherHandle, &watchInfo, property); 64069570cc8Sopenharmony_ci APPSPAWN_CHECK(status == LE_SUCCESS, 64169570cc8Sopenharmony_ci return APPSPAWN_SYSTEM_ERROR, "Failed to watch child %{public}d", property->pid); 64269570cc8Sopenharmony_ci status = LE_CreateTimer(LE_GetDefaultLoop(), &property->forkCtx.timer, WaitChildTimeout, property); 64369570cc8Sopenharmony_ci if (status == LE_SUCCESS) { 64469570cc8Sopenharmony_ci status = LE_StartTimer(LE_GetDefaultLoop(), property->forkCtx.timer, timeout * 1000, 0); // 1000 1s 64569570cc8Sopenharmony_ci } 64669570cc8Sopenharmony_ci if (status != LE_SUCCESS) { 64769570cc8Sopenharmony_ci if (property->forkCtx.timer != NULL) { 64869570cc8Sopenharmony_ci LE_StopTimer(LE_GetDefaultLoop(), property->forkCtx.timer); 64969570cc8Sopenharmony_ci } 65069570cc8Sopenharmony_ci property->forkCtx.timer = NULL; 65169570cc8Sopenharmony_ci LE_RemoveWatcher(LE_GetDefaultLoop(), property->forkCtx.watcherHandle); 65269570cc8Sopenharmony_ci property->forkCtx.watcherHandle = NULL; 65369570cc8Sopenharmony_ci APPSPAWN_LOGE("Failed to watch child %{public}d", property->pid); 65469570cc8Sopenharmony_ci return APPSPAWN_SYSTEM_ERROR; 65569570cc8Sopenharmony_ci } 65669570cc8Sopenharmony_ci return 0; 65769570cc8Sopenharmony_ci} 65869570cc8Sopenharmony_ci 65969570cc8Sopenharmony_cistatic bool IsSupportRunHnp() 66069570cc8Sopenharmony_ci{ 66169570cc8Sopenharmony_ci char buffer[PARAM_BUFFER_SIZE] = {0}; 66269570cc8Sopenharmony_ci int ret = GetParameter("const.startup.hnp.execute.enable", "false", buffer, PARAM_BUFFER_SIZE); 66369570cc8Sopenharmony_ci if (ret <= 0) { 66469570cc8Sopenharmony_ci APPSPAWN_LOGE("Get hnp execute enable param unsuccess! ret =%{public}d", ret); 66569570cc8Sopenharmony_ci return false; 66669570cc8Sopenharmony_ci } 66769570cc8Sopenharmony_ci 66869570cc8Sopenharmony_ci if (strcmp(buffer, "true") == 0) { 66969570cc8Sopenharmony_ci return true; 67069570cc8Sopenharmony_ci } 67169570cc8Sopenharmony_ci 67269570cc8Sopenharmony_ci return false; 67369570cc8Sopenharmony_ci} 67469570cc8Sopenharmony_ci 67569570cc8Sopenharmony_cistatic int WritePreforkMsg(AppSpawningCtx *property) 67669570cc8Sopenharmony_ci{ 67769570cc8Sopenharmony_ci AppSpawnContent *content = GetAppSpawnContent(); 67869570cc8Sopenharmony_ci if (content == NULL || content->propertyBuffer == NULL) { 67969570cc8Sopenharmony_ci APPSPAWN_LOGE("buffer is null can not write propery"); 68069570cc8Sopenharmony_ci return -1; 68169570cc8Sopenharmony_ci } 68269570cc8Sopenharmony_ci 68369570cc8Sopenharmony_ci int ret = memcpy_s(content->propertyBuffer, MAX_MEM_SIZE, &property->message->msgHeader, sizeof(AppSpawnMsg)); 68469570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, goto fail, "memcpys_s msgHeader failed"); 68569570cc8Sopenharmony_ci ret = memcpy_s((char *)content->propertyBuffer + sizeof(AppSpawnMsg), MAX_MEM_SIZE - sizeof(AppSpawnMsg), 68669570cc8Sopenharmony_ci property->message->buffer, property->message->msgHeader.msgLen - sizeof(AppSpawnMsg)); 68769570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, goto fail, "memcpys_s AppSpawnMsg failed"); 68869570cc8Sopenharmony_ci return ret; 68969570cc8Sopenharmony_ci 69069570cc8Sopenharmony_cifail: 69169570cc8Sopenharmony_ci munmap((char *)content->propertyBuffer, MAX_MEM_SIZE); 69269570cc8Sopenharmony_ci content->propertyBuffer = NULL; 69369570cc8Sopenharmony_ci return ret; 69469570cc8Sopenharmony_ci} 69569570cc8Sopenharmony_ci 69669570cc8Sopenharmony_cistatic int GetAppSpawnMsg(AppSpawningCtx *property) 69769570cc8Sopenharmony_ci{ 69869570cc8Sopenharmony_ci uint8_t *buffer = (uint8_t *)GetMapMem(property->client.id, "prefork", MAX_MEM_SIZE, true, false); 69969570cc8Sopenharmony_ci if (buffer == NULL) { 70069570cc8Sopenharmony_ci APPSPAWN_LOGE("prefork buffer is null can not write propery"); 70169570cc8Sopenharmony_ci return -1; 70269570cc8Sopenharmony_ci } 70369570cc8Sopenharmony_ci uint32_t msgRecvLen = 0; 70469570cc8Sopenharmony_ci uint32_t remainLen = 0; 70569570cc8Sopenharmony_ci property->forkCtx.childMsg = (char *)buffer; 70669570cc8Sopenharmony_ci property->forkCtx.msgSize = MAX_MEM_SIZE; 70769570cc8Sopenharmony_ci AppSpawnMsgNode *message = NULL; 70869570cc8Sopenharmony_ci int ret = GetAppSpawnMsgFromBuffer(buffer, ((AppSpawnMsg *)buffer)->msgLen, &message, &msgRecvLen, &remainLen); 70969570cc8Sopenharmony_ci // release map 71069570cc8Sopenharmony_ci APPSPAWN_LOGV("prefork GetAppSpawnMsg ret:%{public}d", ret); 71169570cc8Sopenharmony_ci if (ret == 0 && DecodeAppSpawnMsg(message) == 0 && CheckAppSpawnMsg(message) == 0) { 71269570cc8Sopenharmony_ci property->message = message; 71369570cc8Sopenharmony_ci message = NULL; 71469570cc8Sopenharmony_ci return 0; 71569570cc8Sopenharmony_ci } 71669570cc8Sopenharmony_ci return -1; 71769570cc8Sopenharmony_ci} 71869570cc8Sopenharmony_ci 71969570cc8Sopenharmony_cistatic void ClearMMAP(int clientId) 72069570cc8Sopenharmony_ci{ 72169570cc8Sopenharmony_ci char path[PATH_MAX] = {0}; 72269570cc8Sopenharmony_ci int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, APPSPAWN_MSG_DIR "appspawn/prefork_%d", clientId); 72369570cc8Sopenharmony_ci APPSPAWN_LOGV("prefork unlink %{public}s ret :%{public}d", path, ret); 72469570cc8Sopenharmony_ci if (ret > 0) { 72569570cc8Sopenharmony_ci errno = 0; 72669570cc8Sopenharmony_ci ret = unlink(path); 72769570cc8Sopenharmony_ci APPSPAWN_LOGV("prefork unlink result %{public}d %{public}d", ret, errno); 72869570cc8Sopenharmony_ci } 72969570cc8Sopenharmony_ci 73069570cc8Sopenharmony_ci AppSpawnContent *content = GetAppSpawnContent(); 73169570cc8Sopenharmony_ci if (content != NULL && content->propertyBuffer != NULL) { 73269570cc8Sopenharmony_ci ret = munmap(content->propertyBuffer, MAX_MEM_SIZE); 73369570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_LOG(ret == 0, "munmap failed %{public}d", ret); 73469570cc8Sopenharmony_ci content->propertyBuffer = NULL; 73569570cc8Sopenharmony_ci } 73669570cc8Sopenharmony_ci} 73769570cc8Sopenharmony_ci 73869570cc8Sopenharmony_cistatic int SetPreforkProcessName(AppSpawnContent *content) 73969570cc8Sopenharmony_ci{ 74069570cc8Sopenharmony_ci int ret = prctl(PR_SET_NAME, PREFORK_PROCESS); 74169570cc8Sopenharmony_ci if (ret == -1) { 74269570cc8Sopenharmony_ci return errno; 74369570cc8Sopenharmony_ci } 74469570cc8Sopenharmony_ci 74569570cc8Sopenharmony_ci ret = memset_s(content->longProcName, 74669570cc8Sopenharmony_ci (size_t)content->longProcNameLen, 0, (size_t)content->longProcNameLen); 74769570cc8Sopenharmony_ci if (ret != EOK) { 74869570cc8Sopenharmony_ci return EINVAL; 74969570cc8Sopenharmony_ci } 75069570cc8Sopenharmony_ci 75169570cc8Sopenharmony_ci ret = strncpy_s(content->longProcName, content->longProcNameLen, 75269570cc8Sopenharmony_ci PREFORK_PROCESS, strlen(PREFORK_PROCESS)); 75369570cc8Sopenharmony_ci if (ret != EOK) { 75469570cc8Sopenharmony_ci return EINVAL; 75569570cc8Sopenharmony_ci } 75669570cc8Sopenharmony_ci 75769570cc8Sopenharmony_ci return 0; 75869570cc8Sopenharmony_ci} 75969570cc8Sopenharmony_ci 76069570cc8Sopenharmony_cistatic void ProcessPreFork(AppSpawnContent *content, AppSpawningCtx *property) 76169570cc8Sopenharmony_ci{ 76269570cc8Sopenharmony_ci APPSPAWN_CHECK(pipe(content->preforkFd) == 0, return, "prefork with prefork pipe failed %{public}d", errno); 76369570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(content->parentToChildFd[0] <= 0, close(content->parentToChildFd[0]); 76469570cc8Sopenharmony_ci content->parentToChildFd[0] = -1); 76569570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(content->parentToChildFd[1] <= 0, close(content->parentToChildFd[1]); 76669570cc8Sopenharmony_ci content->parentToChildFd[1] = -1); 76769570cc8Sopenharmony_ci APPSPAWN_CHECK(pipe(content->parentToChildFd) == 0, return, "prefork with prefork pipe failed %{public}d", errno); 76869570cc8Sopenharmony_ci 76969570cc8Sopenharmony_ci content->reservedPid = fork(); 77069570cc8Sopenharmony_ci APPSPAWN_LOGV("prefork fork finish %{public}d,%{public}d,%{public}d,%{public}d,%{public}d", 77169570cc8Sopenharmony_ci content->reservedPid, content->preforkFd[0], content->preforkFd[1], content->parentToChildFd[0], 77269570cc8Sopenharmony_ci content->parentToChildFd[1]); 77369570cc8Sopenharmony_ci if (content->reservedPid == 0) { 77469570cc8Sopenharmony_ci (void)close(property->forkCtx.fd[0]); 77569570cc8Sopenharmony_ci (void)close(property->forkCtx.fd[1]); 77669570cc8Sopenharmony_ci int isRet = SetPreforkProcessName(content); 77769570cc8Sopenharmony_ci APPSPAWN_LOGI("prefork process start wait read msg with set processname %{public}d", isRet); 77869570cc8Sopenharmony_ci AppSpawnClient client = {0, 0}; 77969570cc8Sopenharmony_ci int infoSize = read(content->parentToChildFd[0], &client, sizeof(AppSpawnClient)); 78069570cc8Sopenharmony_ci if (infoSize != sizeof(AppSpawnClient)) { 78169570cc8Sopenharmony_ci APPSPAWN_LOGE("prefork process read msg failed %{public}d,%{public}d", infoSize, errno); 78269570cc8Sopenharmony_ci ProcessExit(0); 78369570cc8Sopenharmony_ci return; 78469570cc8Sopenharmony_ci } 78569570cc8Sopenharmony_ci property->client.id = client.id; 78669570cc8Sopenharmony_ci property->client.flags = client.flags; 78769570cc8Sopenharmony_ci property->isPrefork = true; 78869570cc8Sopenharmony_ci property->forkCtx.fd[0] = content->preforkFd[0]; 78969570cc8Sopenharmony_ci property->forkCtx.fd[1] = content->preforkFd[1]; 79069570cc8Sopenharmony_ci property->state = APP_STATE_SPAWNING; 79169570cc8Sopenharmony_ci if (GetAppSpawnMsg(property) == -1) { 79269570cc8Sopenharmony_ci APPSPAWN_LOGE("prefork child read GetAppSpawnMsg failed"); 79369570cc8Sopenharmony_ci ClearMMAP(property->client.id); 79469570cc8Sopenharmony_ci content->notifyResToParent(content, &property->client, APPSPAWN_MSG_INVALID); 79569570cc8Sopenharmony_ci ProcessExit(0); 79669570cc8Sopenharmony_ci return; 79769570cc8Sopenharmony_ci } 79869570cc8Sopenharmony_ci ClearMMAP(property->client.id); 79969570cc8Sopenharmony_ci ProcessExit(AppSpawnChild(content, &property->client)); 80069570cc8Sopenharmony_ci } else if (content->reservedPid < 0) { 80169570cc8Sopenharmony_ci APPSPAWN_LOGE("prefork fork child process failed %{public}d", content->reservedPid); 80269570cc8Sopenharmony_ci } 80369570cc8Sopenharmony_ci} 80469570cc8Sopenharmony_ci 80569570cc8Sopenharmony_cistatic int AppSpawnProcessMsgForPrefork(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid) 80669570cc8Sopenharmony_ci{ 80769570cc8Sopenharmony_ci int ret = 0; 80869570cc8Sopenharmony_ci AppSpawningCtx *property = (AppSpawningCtx *)client; 80969570cc8Sopenharmony_ci 81069570cc8Sopenharmony_ci if (content->reservedPid <= 0) { 81169570cc8Sopenharmony_ci APPSPAWN_CHECK(client != NULL, return ret, "client is null"); 81269570cc8Sopenharmony_ci ret = InitForkContext((AppSpawningCtx *)client); 81369570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return ret, "init fork context failed"); 81469570cc8Sopenharmony_ci ret = AppSpawnProcessMsg(content, client, childPid); 81569570cc8Sopenharmony_ci } else { 81669570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(content->propertyBuffer == NULL, ClearMMAP(client->id)); 81769570cc8Sopenharmony_ci content->propertyBuffer = GetMapMem(property->client.id, "prefork", MAX_MEM_SIZE, false, false); 81869570cc8Sopenharmony_ci APPSPAWN_CHECK(content->propertyBuffer != NULL, return -1, "GetPreforkMem failed"); 81969570cc8Sopenharmony_ci ret = WritePreforkMsg(property); 82069570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return ret, "WritePreforkMsg failed"); 82169570cc8Sopenharmony_ci 82269570cc8Sopenharmony_ci *childPid = content->reservedPid; 82369570cc8Sopenharmony_ci property->forkCtx.fd[0] = content->preforkFd[0]; 82469570cc8Sopenharmony_ci property->forkCtx.fd[1] = content->preforkFd[1]; 82569570cc8Sopenharmony_ci 82669570cc8Sopenharmony_ci int option = fcntl(property->forkCtx.fd[0], F_GETFD); 82769570cc8Sopenharmony_ci if (option > 0) { 82869570cc8Sopenharmony_ci ret = fcntl(property->forkCtx.fd[0], F_SETFD, (unsigned int)option | O_NONBLOCK); 82969570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_LOG(ret == 0, "fcntl failed %{public}d,%{public}d", ret, errno); 83069570cc8Sopenharmony_ci } 83169570cc8Sopenharmony_ci 83269570cc8Sopenharmony_ci ssize_t writesize = write(content->parentToChildFd[1], client, sizeof(AppSpawnClient)) ; 83369570cc8Sopenharmony_ci APPSPAWN_CHECK(writesize == sizeof(AppSpawnClient), kill(*childPid, SIGKILL); 83469570cc8Sopenharmony_ci *childPid = 0; 83569570cc8Sopenharmony_ci ret = -1, 83669570cc8Sopenharmony_ci "write msg to child failed %{public}d", errno); 83769570cc8Sopenharmony_ci } 83869570cc8Sopenharmony_ci ProcessPreFork(content, property); 83969570cc8Sopenharmony_ci return ret; 84069570cc8Sopenharmony_ci} 84169570cc8Sopenharmony_ci 84269570cc8Sopenharmony_cistatic bool IsSupportPrefork(AppSpawnContent *content, AppSpawnClient *client) 84369570cc8Sopenharmony_ci{ 84469570cc8Sopenharmony_ci#ifdef APPSPAWN_SUPPORT_PREFORK 84569570cc8Sopenharmony_ci if (client == NULL || content == NULL) { 84669570cc8Sopenharmony_ci return false; 84769570cc8Sopenharmony_ci } 84869570cc8Sopenharmony_ci if (!content->enablePerfork) { 84969570cc8Sopenharmony_ci return false; 85069570cc8Sopenharmony_ci } 85169570cc8Sopenharmony_ci AppSpawningCtx *property = (AppSpawningCtx *)client; 85269570cc8Sopenharmony_ci 85369570cc8Sopenharmony_ci if (content->mode == MODE_FOR_APP_SPAWN && !IsChildColdRun(property) 85469570cc8Sopenharmony_ci && !CheckAppMsgFlagsSet(property, APP_FLAGS_CHILDPROCESS)) { 85569570cc8Sopenharmony_ci return true; 85669570cc8Sopenharmony_ci } 85769570cc8Sopenharmony_ci#endif 85869570cc8Sopenharmony_ci return false; 85969570cc8Sopenharmony_ci} 86069570cc8Sopenharmony_ci 86169570cc8Sopenharmony_cistatic bool IsBootFinished() 86269570cc8Sopenharmony_ci{ 86369570cc8Sopenharmony_ci char buffer[32] = {0}; // 32 max 86469570cc8Sopenharmony_ci int ret = GetParameter("bootevent.boot.completed", "false", buffer, sizeof(buffer)); 86569570cc8Sopenharmony_ci bool isBootCompleted = (ret > 0 && strcmp(buffer, "true") == 0); 86669570cc8Sopenharmony_ci return isBootCompleted; 86769570cc8Sopenharmony_ci} 86869570cc8Sopenharmony_ci 86969570cc8Sopenharmony_cistatic int RunAppSpawnProcessMsg(AppSpawnContent *content, AppSpawnClient *client, pid_t *childPid) 87069570cc8Sopenharmony_ci{ 87169570cc8Sopenharmony_ci int ret = 0; 87269570cc8Sopenharmony_ci 87369570cc8Sopenharmony_ci if (IsBootFinished() && IsSupportPrefork(content, client)) { 87469570cc8Sopenharmony_ci ret = AppSpawnProcessMsgForPrefork(content, client, childPid); 87569570cc8Sopenharmony_ci } else { 87669570cc8Sopenharmony_ci APPSPAWN_CHECK(client != NULL, return ret, "client is null"); 87769570cc8Sopenharmony_ci ret = InitForkContext((AppSpawningCtx *)client); 87869570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return ret, "init fork context failed"); 87969570cc8Sopenharmony_ci ret = AppSpawnProcessMsg(content, client, childPid); 88069570cc8Sopenharmony_ci } 88169570cc8Sopenharmony_ci return ret; 88269570cc8Sopenharmony_ci} 88369570cc8Sopenharmony_ci 88469570cc8Sopenharmony_cistatic void ProcessSpawnReqMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) 88569570cc8Sopenharmony_ci{ 88669570cc8Sopenharmony_ci int ret = CheckAppSpawnMsg(message); 88769570cc8Sopenharmony_ci if (ret != 0) { 88869570cc8Sopenharmony_ci SendResponse(connection, &message->msgHeader, ret, 0); 88969570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 89069570cc8Sopenharmony_ci return; 89169570cc8Sopenharmony_ci } 89269570cc8Sopenharmony_ci 89369570cc8Sopenharmony_ci if (IsDeveloperModeOpen()) { 89469570cc8Sopenharmony_ci if (IsSupportRunHnp()) { 89569570cc8Sopenharmony_ci SetAppSpawnMsgFlag(message, TLV_MSG_FLAGS, APP_FLAGS_DEVELOPER_MODE); 89669570cc8Sopenharmony_ci } else { 89769570cc8Sopenharmony_ci APPSPAWN_LOGI("Not support execute hnp file!"); 89869570cc8Sopenharmony_ci } 89969570cc8Sopenharmony_ci } 90069570cc8Sopenharmony_ci 90169570cc8Sopenharmony_ci AppSpawningCtx *property = CreateAppSpawningCtx(); 90269570cc8Sopenharmony_ci if (property == NULL) { 90369570cc8Sopenharmony_ci SendResponse(connection, &message->msgHeader, APPSPAWN_SYSTEM_ERROR, 0); 90469570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 90569570cc8Sopenharmony_ci return; 90669570cc8Sopenharmony_ci } 90769570cc8Sopenharmony_ci 90869570cc8Sopenharmony_ci property->state = APP_STATE_SPAWNING; 90969570cc8Sopenharmony_ci property->message = message; 91069570cc8Sopenharmony_ci message->connection = connection; 91169570cc8Sopenharmony_ci // mount el2 dir 91269570cc8Sopenharmony_ci // getWrapBundleNameValue 91369570cc8Sopenharmony_ci AppSpawnHookExecute(STAGE_PARENT_PRE_FORK, 0, GetAppSpawnContent(), &property->client); 91469570cc8Sopenharmony_ci DumpAppSpawnMsg(property->message); 91569570cc8Sopenharmony_ci 91669570cc8Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &property->spawnStart); 91769570cc8Sopenharmony_ci ret = RunAppSpawnProcessMsg(GetAppSpawnContent(), &property->client, &property->pid); 91869570cc8Sopenharmony_ci AppSpawnHookExecute(STAGE_PARENT_POST_FORK, 0, GetAppSpawnContent(), &property->client); 91969570cc8Sopenharmony_ci if (ret != 0) { // wait child process result 92069570cc8Sopenharmony_ci SendResponse(connection, &message->msgHeader, ret, 0); 92169570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 92269570cc8Sopenharmony_ci return; 92369570cc8Sopenharmony_ci } 92469570cc8Sopenharmony_ci if (AddChildWatcher(property) != 0) { // wait child process result 92569570cc8Sopenharmony_ci kill(property->pid, SIGKILL); 92669570cc8Sopenharmony_ci SendResponse(connection, &message->msgHeader, ret, 0); 92769570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 92869570cc8Sopenharmony_ci return; 92969570cc8Sopenharmony_ci } 93069570cc8Sopenharmony_ci} 93169570cc8Sopenharmony_ci 93269570cc8Sopenharmony_cistatic uint32_t g_lastDiedAppId = 0; 93369570cc8Sopenharmony_cistatic uint32_t g_crashTimes = 0; 93469570cc8Sopenharmony_ci#define MAX_CRASH_TIME 5 93569570cc8Sopenharmony_cistatic void WaitChildDied(pid_t pid) 93669570cc8Sopenharmony_ci{ 93769570cc8Sopenharmony_ci AppSpawningCtx *property = GetAppSpawningCtxByPid(pid); 93869570cc8Sopenharmony_ci if (property != NULL && property->state == APP_STATE_SPAWNING) { 93969570cc8Sopenharmony_ci APPSPAWN_LOGI("Child process %{public}s fail \'child crash \'pid %{public}d appId: %{public}d", 94069570cc8Sopenharmony_ci GetProcessName(property), property->pid, property->client.id); 94169570cc8Sopenharmony_ci if (property->client.id == g_lastDiedAppId + 1) { 94269570cc8Sopenharmony_ci g_crashTimes++; 94369570cc8Sopenharmony_ci } else { 94469570cc8Sopenharmony_ci g_crashTimes = 1; 94569570cc8Sopenharmony_ci } 94669570cc8Sopenharmony_ci g_lastDiedAppId = property->client.id; 94769570cc8Sopenharmony_ci 94869570cc8Sopenharmony_ci SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_CHILD_CRASH, 0); 94969570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 95069570cc8Sopenharmony_ci 95169570cc8Sopenharmony_ci if (g_crashTimes >= MAX_CRASH_TIME) { 95269570cc8Sopenharmony_ci APPSPAWN_LOGW("Continuous failures in spawning the app, restart appspawn"); 95369570cc8Sopenharmony_ci StopAppSpawn(); 95469570cc8Sopenharmony_ci } 95569570cc8Sopenharmony_ci } 95669570cc8Sopenharmony_ci} 95769570cc8Sopenharmony_ci 95869570cc8Sopenharmony_cistatic void WaitChildTimeout(const TimerHandle taskHandle, void *context) 95969570cc8Sopenharmony_ci{ 96069570cc8Sopenharmony_ci AppSpawningCtx *property = (AppSpawningCtx *)context; 96169570cc8Sopenharmony_ci APPSPAWN_LOGI("Child process %{public}s fail \'wait child timeout \'pid %{public}d appId: %{public}d", 96269570cc8Sopenharmony_ci GetProcessName(property), property->pid, property->client.id); 96369570cc8Sopenharmony_ci if (property->pid > 0) { 96469570cc8Sopenharmony_ci#if (!defined(CJAPP_SPAWN) && !defined(NATIVE_SPAWN)) 96569570cc8Sopenharmony_ci DumpSpawnStack(property->pid); 96669570cc8Sopenharmony_ci#endif 96769570cc8Sopenharmony_ci kill(property->pid, SIGKILL); 96869570cc8Sopenharmony_ci } 96969570cc8Sopenharmony_ci SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_SPAWN_TIMEOUT, 0); 97069570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 97169570cc8Sopenharmony_ci} 97269570cc8Sopenharmony_ci 97369570cc8Sopenharmony_cistatic int ProcessChildFdCheck(int fd, AppSpawningCtx *property, int *pResult) 97469570cc8Sopenharmony_ci{ 97569570cc8Sopenharmony_ci int result = 0; 97669570cc8Sopenharmony_ci (void)read(fd, &result, sizeof(result)); 97769570cc8Sopenharmony_ci APPSPAWN_LOGI("Child process %{public}s success pid %{public}d appId: %{public}d result: %{public}d", 97869570cc8Sopenharmony_ci GetProcessName(property), property->pid, property->client.id, result); 97969570cc8Sopenharmony_ci APPSPAWN_CHECK(property->message != NULL, return -1, "Invalid message in ctx %{public}d", property->client.id); 98069570cc8Sopenharmony_ci 98169570cc8Sopenharmony_ci if (result != 0) { 98269570cc8Sopenharmony_ci SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid); 98369570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 98469570cc8Sopenharmony_ci return -1; 98569570cc8Sopenharmony_ci } 98669570cc8Sopenharmony_ci *pResult = result; 98769570cc8Sopenharmony_ci 98869570cc8Sopenharmony_ci return 0; 98969570cc8Sopenharmony_ci} 99069570cc8Sopenharmony_ci 99169570cc8Sopenharmony_ci#define MSG_EXT_NAME_MAX_DECIMAL 10 99269570cc8Sopenharmony_ci#define MSG_EXT_NAME 1 99369570cc8Sopenharmony_cistatic void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context) 99469570cc8Sopenharmony_ci{ 99569570cc8Sopenharmony_ci AppSpawningCtx *property = (AppSpawningCtx *)context; 99669570cc8Sopenharmony_ci property->forkCtx.watcherHandle = NULL; // delete watcher 99769570cc8Sopenharmony_ci LE_RemoveWatcher(LE_GetDefaultLoop(), (WatcherHandle)taskHandle); 99869570cc8Sopenharmony_ci 99969570cc8Sopenharmony_ci int result = 0; 100069570cc8Sopenharmony_ci if (ProcessChildFdCheck(fd, property, &result) != 0) { 100169570cc8Sopenharmony_ci return; 100269570cc8Sopenharmony_ci } 100369570cc8Sopenharmony_ci 100469570cc8Sopenharmony_ci // success 100569570cc8Sopenharmony_ci bool isDebuggable = CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE) == 1 ? true : false; 100669570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = AddSpawnedProcess(property->pid, GetBundleName(property), isDebuggable); 100769570cc8Sopenharmony_ci uint32_t len = 0; 100869570cc8Sopenharmony_ci char *pidMaxStr = NULL; 100969570cc8Sopenharmony_ci pidMaxStr = GetAppPropertyExt(property, MSG_EXT_NAME_MAX_CHILD_PROCCESS_MAX, &len); 101069570cc8Sopenharmony_ci uint32_t pidMax = 0; 101169570cc8Sopenharmony_ci if (pidMaxStr != NULL && len != 0) { 101269570cc8Sopenharmony_ci pidMax = strtoul(pidMaxStr, NULL, MSG_EXT_NAME_MAX_DECIMAL); 101369570cc8Sopenharmony_ci } 101469570cc8Sopenharmony_ci#if MSG_EXT_NAME != 0 101569570cc8Sopenharmony_ci pidMax = 0; 101669570cc8Sopenharmony_ci#endif 101769570cc8Sopenharmony_ci if (appInfo) { 101869570cc8Sopenharmony_ci AppSpawnMsgDacInfo *dacInfo = GetAppProperty(property, TLV_DAC_INFO); 101969570cc8Sopenharmony_ci appInfo->uid = dacInfo != NULL ? dacInfo->uid : 0; 102069570cc8Sopenharmony_ci appInfo->max = pidMax; 102169570cc8Sopenharmony_ci appInfo->spawnStart.tv_sec = property->spawnStart.tv_sec; 102269570cc8Sopenharmony_ci appInfo->spawnStart.tv_nsec = property->spawnStart.tv_nsec; 102369570cc8Sopenharmony_ci#ifdef DEBUG_BEGETCTL_BOOT 102469570cc8Sopenharmony_ci if (IsDeveloperModeOpen()) { 102569570cc8Sopenharmony_ci appInfo->message = property->message; 102669570cc8Sopenharmony_ci } 102769570cc8Sopenharmony_ci#endif 102869570cc8Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &appInfo->spawnEnd); 102969570cc8Sopenharmony_ci // add max info 103069570cc8Sopenharmony_ci } 103169570cc8Sopenharmony_ci WatchChildProcessFd(property); 103269570cc8Sopenharmony_ci ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, GetAppSpawnContent(), appInfo); 103369570cc8Sopenharmony_ci // response 103469570cc8Sopenharmony_ci AppSpawnHookExecute(STAGE_PARENT_PRE_RELY, 0, GetAppSpawnContent(), &property->client); 103569570cc8Sopenharmony_ci SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid); 103669570cc8Sopenharmony_ci AppSpawnHookExecute(STAGE_PARENT_POST_RELY, 0, GetAppSpawnContent(), &property->client); 103769570cc8Sopenharmony_ci#ifdef DEBUG_BEGETCTL_BOOT 103869570cc8Sopenharmony_ci if (IsDeveloperModeOpen()) { 103969570cc8Sopenharmony_ci property->message = NULL; 104069570cc8Sopenharmony_ci } 104169570cc8Sopenharmony_ci#endif 104269570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 104369570cc8Sopenharmony_ci} 104469570cc8Sopenharmony_ci 104569570cc8Sopenharmony_cistatic void NotifyResToParent(AppSpawnContent *content, AppSpawnClient *client, int result) 104669570cc8Sopenharmony_ci{ 104769570cc8Sopenharmony_ci AppSpawningCtx *property = (AppSpawningCtx *)client; 104869570cc8Sopenharmony_ci int fd = property->forkCtx.fd[1]; 104969570cc8Sopenharmony_ci if (fd >= 0) { 105069570cc8Sopenharmony_ci (void)write(fd, &result, sizeof(result)); 105169570cc8Sopenharmony_ci (void)close(fd); 105269570cc8Sopenharmony_ci property->forkCtx.fd[1] = -1; 105369570cc8Sopenharmony_ci } 105469570cc8Sopenharmony_ci APPSPAWN_LOGV("NotifyResToParent client id: %{public}u result: 0x%{public}x", client->id, result); 105569570cc8Sopenharmony_ci} 105669570cc8Sopenharmony_ci 105769570cc8Sopenharmony_cistatic int CreateAppSpawnServer(TaskHandle *server, const char *socketName) 105869570cc8Sopenharmony_ci{ 105969570cc8Sopenharmony_ci char path[128] = {0}; // 128 max path 106069570cc8Sopenharmony_ci int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", APPSPAWN_SOCKET_DIR, socketName); 106169570cc8Sopenharmony_ci APPSPAWN_CHECK(ret >= 0, return -1, "Failed to snprintf_s %{public}d", ret); 106269570cc8Sopenharmony_ci int socketId = GetControlSocket(socketName); 106369570cc8Sopenharmony_ci APPSPAWN_LOGI("get socket form env %{public}s socketId %{public}d", socketName, socketId); 106469570cc8Sopenharmony_ci 106569570cc8Sopenharmony_ci LE_StreamServerInfo info = {}; 106669570cc8Sopenharmony_ci info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER; 106769570cc8Sopenharmony_ci info.socketId = socketId; 106869570cc8Sopenharmony_ci info.server = path; 106969570cc8Sopenharmony_ci info.baseInfo.close = NULL; 107069570cc8Sopenharmony_ci info.incommingConnect = OnConnection; 107169570cc8Sopenharmony_ci 107269570cc8Sopenharmony_ci MakeDirRec(path, 0711, 0); // 0711 default mask 107369570cc8Sopenharmony_ci ret = LE_CreateStreamServer(LE_GetDefaultLoop(), server, &info); 107469570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return -1, "Failed to create socket for %{public}s errno: %{public}d", path, errno); 107569570cc8Sopenharmony_ci SetFdCtrl(LE_GetSocketFd(*server), FD_CLOEXEC); 107669570cc8Sopenharmony_ci 107769570cc8Sopenharmony_ci APPSPAWN_LOGI("CreateAppSpawnServer path %{public}s fd %{public}d", path, LE_GetSocketFd(*server)); 107869570cc8Sopenharmony_ci return 0; 107969570cc8Sopenharmony_ci} 108069570cc8Sopenharmony_ci 108169570cc8Sopenharmony_civoid AppSpawnDestroyContent(AppSpawnContent *content) 108269570cc8Sopenharmony_ci{ 108369570cc8Sopenharmony_ci if (content == NULL) { 108469570cc8Sopenharmony_ci return; 108569570cc8Sopenharmony_ci } 108669570cc8Sopenharmony_ci if (content->parentToChildFd[0] > 0) { 108769570cc8Sopenharmony_ci close(content->parentToChildFd[0]); 108869570cc8Sopenharmony_ci } 108969570cc8Sopenharmony_ci if (content->parentToChildFd[1] > 0) { 109069570cc8Sopenharmony_ci close(content->parentToChildFd[1]); 109169570cc8Sopenharmony_ci } 109269570cc8Sopenharmony_ci AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content; 109369570cc8Sopenharmony_ci#ifdef USE_ENCAPS 109469570cc8Sopenharmony_ci CloseDevEncaps(appSpawnContent->content.fdEncaps); 109569570cc8Sopenharmony_ci#endif 109669570cc8Sopenharmony_ci if (appSpawnContent->sigHandler != NULL && appSpawnContent->servicePid == getpid()) { 109769570cc8Sopenharmony_ci LE_CloseSignalTask(LE_GetDefaultLoop(), appSpawnContent->sigHandler); 109869570cc8Sopenharmony_ci } 109969570cc8Sopenharmony_ci 110069570cc8Sopenharmony_ci if (appSpawnContent->server != NULL && appSpawnContent->servicePid == getpid()) { // childProcess can't deal socket 110169570cc8Sopenharmony_ci LE_CloseStreamTask(LE_GetDefaultLoop(), appSpawnContent->server); 110269570cc8Sopenharmony_ci appSpawnContent->server = NULL; 110369570cc8Sopenharmony_ci } 110469570cc8Sopenharmony_ci LE_StopLoop(LE_GetDefaultLoop()); 110569570cc8Sopenharmony_ci LE_CloseLoop(LE_GetDefaultLoop()); 110669570cc8Sopenharmony_ci DeleteAppSpawnMgr(appSpawnContent); 110769570cc8Sopenharmony_ci} 110869570cc8Sopenharmony_ci 110969570cc8Sopenharmony_ciAPPSPAWN_STATIC int AppSpawnColdStartApp(struct AppSpawnContent *content, AppSpawnClient *client) 111069570cc8Sopenharmony_ci{ 111169570cc8Sopenharmony_ci AppSpawningCtx *property = (AppSpawningCtx *)client; 111269570cc8Sopenharmony_ci#ifdef CJAPP_SPAWN 111369570cc8Sopenharmony_ci char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/cjappspawn"; 111469570cc8Sopenharmony_ci#elif NATIVE_SPAWN 111569570cc8Sopenharmony_ci char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/nativespawn"; 111669570cc8Sopenharmony_ci#else 111769570cc8Sopenharmony_ci char *path = property->forkCtx.coldRunPath != NULL ? property->forkCtx.coldRunPath : "/system/bin/appspawn"; 111869570cc8Sopenharmony_ci#endif 111969570cc8Sopenharmony_ci APPSPAWN_LOGI("ColdStartApp::processName: %{public}s path: %{public}s", GetProcessName(property), path); 112069570cc8Sopenharmony_ci 112169570cc8Sopenharmony_ci // for cold run, use shared memory to exchange message 112269570cc8Sopenharmony_ci APPSPAWN_LOGV("Write msg to child %{public}s", GetProcessName(property)); 112369570cc8Sopenharmony_ci int ret = WriteMsgToChild(property, IsNWebSpawnMode((AppSpawnMgr *)content)); 112469570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return APPSPAWN_SYSTEM_ERROR, "Failed to write msg to child"); 112569570cc8Sopenharmony_ci 112669570cc8Sopenharmony_ci char buffer[4][32] = {0}; // 4 32 buffer for fd 112769570cc8Sopenharmony_ci int len = sprintf_s(buffer[0], sizeof(buffer[0]), " %d ", property->forkCtx.fd[1]); 112869570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format fd"); 112969570cc8Sopenharmony_ci len = sprintf_s(buffer[1], sizeof(buffer[1]), " %u ", property->client.flags); 113069570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format flags"); 113169570cc8Sopenharmony_ci len = sprintf_s(buffer[2], sizeof(buffer[2]), " %u ", property->forkCtx.msgSize); // 2 2 index for dest path 113269570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format shmId "); 113369570cc8Sopenharmony_ci len = sprintf_s(buffer[3], sizeof(buffer[3]), " %u ", property->client.id); // 3 3 index for client id 113469570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid to format shmId "); 113569570cc8Sopenharmony_ci 113669570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST 113769570cc8Sopenharmony_ci char *mode = IsNWebSpawnMode((AppSpawnMgr *)content) ? "nweb_cold" : "app_cold"; 113869570cc8Sopenharmony_ci // 2 2 index for dest path 113969570cc8Sopenharmony_ci const char *const formatCmds[] = { 114069570cc8Sopenharmony_ci path, "-mode", mode, "-fd", buffer[0], buffer[1], buffer[2], 114169570cc8Sopenharmony_ci "-param", GetProcessName(property), buffer[3], NULL 114269570cc8Sopenharmony_ci }; 114369570cc8Sopenharmony_ci 114469570cc8Sopenharmony_ci ret = execv(path, (char **)formatCmds); 114569570cc8Sopenharmony_ci if (ret != 0) { 114669570cc8Sopenharmony_ci APPSPAWN_LOGE("Failed to execv, errno: %{public}d", errno); 114769570cc8Sopenharmony_ci } 114869570cc8Sopenharmony_ci#endif 114969570cc8Sopenharmony_ci APPSPAWN_LOGV("ColdStartApp::processName: %{public}s end", GetProcessName(property)); 115069570cc8Sopenharmony_ci return 0; 115169570cc8Sopenharmony_ci} 115269570cc8Sopenharmony_ci 115369570cc8Sopenharmony_cistatic AppSpawningCtx *GetAppSpawningCtxFromArg(AppSpawnMgr *content, int argc, char *const argv[]) 115469570cc8Sopenharmony_ci{ 115569570cc8Sopenharmony_ci AppSpawningCtx *property = CreateAppSpawningCtx(); 115669570cc8Sopenharmony_ci APPSPAWN_CHECK(property != NULL, return NULL, "Create app spawning ctx fail"); 115769570cc8Sopenharmony_ci property->forkCtx.fd[1] = atoi(argv[FD_VALUE_INDEX]); 115869570cc8Sopenharmony_ci property->client.flags = (uint32_t)atoi(argv[FLAGS_VALUE_INDEX]); 115969570cc8Sopenharmony_ci property->client.flags &= ~APP_COLD_START; 116069570cc8Sopenharmony_ci 116169570cc8Sopenharmony_ci int isNweb = IsNWebSpawnMode(content); 116269570cc8Sopenharmony_ci uint32_t size = (uint32_t)atoi(argv[SHM_SIZE_INDEX]); 116369570cc8Sopenharmony_ci property->client.id = (uint32_t)atoi(argv[CLIENT_ID_INDEX]); 116469570cc8Sopenharmony_ci uint8_t *buffer = (uint8_t *)GetMapMem(property->client.id, 116569570cc8Sopenharmony_ci argv[PARAM_VALUE_INDEX], size, true, isNweb); 116669570cc8Sopenharmony_ci if (buffer == NULL) { 116769570cc8Sopenharmony_ci APPSPAWN_LOGE("Failed to map errno %{public}d %{public}s", property->client.id, argv[PARAM_VALUE_INDEX]); 116869570cc8Sopenharmony_ci NotifyResToParent(&content->content, &property->client, APPSPAWN_SYSTEM_ERROR); 116969570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 117069570cc8Sopenharmony_ci return NULL; 117169570cc8Sopenharmony_ci } 117269570cc8Sopenharmony_ci 117369570cc8Sopenharmony_ci uint32_t msgRecvLen = 0; 117469570cc8Sopenharmony_ci uint32_t remainLen = 0; 117569570cc8Sopenharmony_ci AppSpawnMsgNode *message = NULL; 117669570cc8Sopenharmony_ci int ret = GetAppSpawnMsgFromBuffer(buffer, ((AppSpawnMsg *)buffer)->msgLen, &message, &msgRecvLen, &remainLen); 117769570cc8Sopenharmony_ci // release map 117869570cc8Sopenharmony_ci munmap((char *)buffer, size); 117969570cc8Sopenharmony_ci //unlink 118069570cc8Sopenharmony_ci char path[PATH_MAX] = {0}; 118169570cc8Sopenharmony_ci int len = sprintf_s(path, sizeof(path), APPSPAWN_MSG_DIR "%s/%s_%u", 118269570cc8Sopenharmony_ci isNweb ? "nwebspawn" : "appspawn", argv[PARAM_VALUE_INDEX], property->client.id); 118369570cc8Sopenharmony_ci if (len > 0) { 118469570cc8Sopenharmony_ci unlink(path); 118569570cc8Sopenharmony_ci } 118669570cc8Sopenharmony_ci 118769570cc8Sopenharmony_ci if (ret == 0 && DecodeAppSpawnMsg(message) == 0 && CheckAppSpawnMsg(message) == 0) { 118869570cc8Sopenharmony_ci property->message = message; 118969570cc8Sopenharmony_ci message = NULL; 119069570cc8Sopenharmony_ci return property; 119169570cc8Sopenharmony_ci } 119269570cc8Sopenharmony_ci NotifyResToParent(&content->content, &property->client, APPSPAWN_MSG_INVALID); 119369570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 119469570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 119569570cc8Sopenharmony_ci return NULL; 119669570cc8Sopenharmony_ci} 119769570cc8Sopenharmony_ci 119869570cc8Sopenharmony_cistatic void AppSpawnColdRun(AppSpawnContent *content, int argc, char *const argv[]) 119969570cc8Sopenharmony_ci{ 120069570cc8Sopenharmony_ci APPSPAWN_CHECK(argc >= ARG_NULL, return, "Invalid arg for cold start %{public}d", argc); 120169570cc8Sopenharmony_ci AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content; 120269570cc8Sopenharmony_ci APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content"); 120369570cc8Sopenharmony_ci 120469570cc8Sopenharmony_ci AppSpawningCtx *property = GetAppSpawningCtxFromArg(appSpawnContent, argc, argv); 120569570cc8Sopenharmony_ci if (property == NULL) { 120669570cc8Sopenharmony_ci APPSPAWN_LOGE("Failed to get property from arg"); 120769570cc8Sopenharmony_ci return; 120869570cc8Sopenharmony_ci } 120969570cc8Sopenharmony_ci DumpAppSpawnMsg(property->message); 121069570cc8Sopenharmony_ci 121169570cc8Sopenharmony_ci int ret = AppSpawnExecuteSpawningHook(content, &property->client); 121269570cc8Sopenharmony_ci if (ret == 0) { 121369570cc8Sopenharmony_ci ret = AppSpawnExecutePreReplyHook(content, &property->client); 121469570cc8Sopenharmony_ci // success 121569570cc8Sopenharmony_ci NotifyResToParent(content, &property->client, ret); 121669570cc8Sopenharmony_ci 121769570cc8Sopenharmony_ci (void)AppSpawnExecutePostReplyHook(content, &property->client); 121869570cc8Sopenharmony_ci 121969570cc8Sopenharmony_ci ret = APPSPAWN_SYSTEM_ERROR; 122069570cc8Sopenharmony_ci if (content->runChildProcessor != NULL) { 122169570cc8Sopenharmony_ci ret = content->runChildProcessor(content, &property->client); 122269570cc8Sopenharmony_ci } 122369570cc8Sopenharmony_ci } else { 122469570cc8Sopenharmony_ci NotifyResToParent(content, &property->client, ret); 122569570cc8Sopenharmony_ci } 122669570cc8Sopenharmony_ci 122769570cc8Sopenharmony_ci if (ret != 0) { 122869570cc8Sopenharmony_ci AppSpawnEnvClear(content, &property->client); 122969570cc8Sopenharmony_ci } 123069570cc8Sopenharmony_ci APPSPAWN_LOGI("AppSpawnColdRun exit %{public}d.", getpid()); 123169570cc8Sopenharmony_ci} 123269570cc8Sopenharmony_ci 123369570cc8Sopenharmony_cistatic void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[]) 123469570cc8Sopenharmony_ci{ 123569570cc8Sopenharmony_ci APPSPAWN_LOGI("AppSpawnRun"); 123669570cc8Sopenharmony_ci AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content; 123769570cc8Sopenharmony_ci APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content"); 123869570cc8Sopenharmony_ci 123969570cc8Sopenharmony_ci LE_STATUS status = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, ProcessSignal); 124069570cc8Sopenharmony_ci if (status == 0) { 124169570cc8Sopenharmony_ci (void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGCHLD); 124269570cc8Sopenharmony_ci (void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGTERM); 124369570cc8Sopenharmony_ci } 124469570cc8Sopenharmony_ci 124569570cc8Sopenharmony_ci#ifdef USE_ENCAPS 124669570cc8Sopenharmony_ci appSpawnContent->content.fdEncaps = OpenDevEncaps(); 124769570cc8Sopenharmony_ci#endif 124869570cc8Sopenharmony_ci LE_RunLoop(LE_GetDefaultLoop()); 124969570cc8Sopenharmony_ci APPSPAWN_LOGI("AppSpawnRun exit mode: %{public}d ", content->mode); 125069570cc8Sopenharmony_ci 125169570cc8Sopenharmony_ci (void)ServerStageHookExecute(STAGE_SERVER_EXIT, content); // service exit,plugin can deal task 125269570cc8Sopenharmony_ci AppSpawnDestroyContent(content); 125369570cc8Sopenharmony_ci} 125469570cc8Sopenharmony_ci 125569570cc8Sopenharmony_ciAPPSPAWN_STATIC int AppSpawnClearEnv(AppSpawnMgr *content, AppSpawningCtx *property) 125669570cc8Sopenharmony_ci{ 125769570cc8Sopenharmony_ci APPSPAWN_CHECK(content != NULL, return 0, "Invalid appspawn content"); 125869570cc8Sopenharmony_ci DeleteAppSpawningCtx(property); 125969570cc8Sopenharmony_ci AppSpawnDestroyContent(&content->content); 126069570cc8Sopenharmony_ci APPSPAWN_LOGV("clear %{public}d end", getpid()); 126169570cc8Sopenharmony_ci return 0; 126269570cc8Sopenharmony_ci} 126369570cc8Sopenharmony_ci 126469570cc8Sopenharmony_cistatic int IsEnablePerfork() 126569570cc8Sopenharmony_ci{ 126669570cc8Sopenharmony_ci char buffer[32] = {0}; 126769570cc8Sopenharmony_ci int ret = GetParameter("persist.sys.prefork.enable", "true", buffer, sizeof(buffer)); 126869570cc8Sopenharmony_ci APPSPAWN_LOGV("IsEnablePerfork result %{public}d, %{public}s", ret, buffer); 126969570cc8Sopenharmony_ci return strcmp(buffer, "true") == 0; 127069570cc8Sopenharmony_ci} 127169570cc8Sopenharmony_ci 127269570cc8Sopenharmony_ciAppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t nameLen, int mode) 127369570cc8Sopenharmony_ci{ 127469570cc8Sopenharmony_ci APPSPAWN_CHECK(socketName != NULL && longProcName != NULL, return NULL, "Invalid name"); 127569570cc8Sopenharmony_ci APPSPAWN_LOGI("AppSpawnCreateContent %{public}s %{public}u mode %{public}d", socketName, nameLen, mode); 127669570cc8Sopenharmony_ci 127769570cc8Sopenharmony_ci AppSpawnMgr *appSpawnContent = CreateAppSpawnMgr(mode); 127869570cc8Sopenharmony_ci APPSPAWN_CHECK(appSpawnContent != NULL, return NULL, "Failed to alloc memory for appspawn"); 127969570cc8Sopenharmony_ci appSpawnContent->content.longProcName = longProcName; 128069570cc8Sopenharmony_ci appSpawnContent->content.longProcNameLen = nameLen; 128169570cc8Sopenharmony_ci appSpawnContent->content.notifyResToParent = NotifyResToParent; 128269570cc8Sopenharmony_ci if (IsColdRunMode(appSpawnContent)) { 128369570cc8Sopenharmony_ci appSpawnContent->content.runAppSpawn = AppSpawnColdRun; 128469570cc8Sopenharmony_ci } else { 128569570cc8Sopenharmony_ci appSpawnContent->content.runAppSpawn = AppSpawnRun; 128669570cc8Sopenharmony_ci appSpawnContent->content.coldStartApp = AppSpawnColdStartApp; 128769570cc8Sopenharmony_ci 128869570cc8Sopenharmony_ci int ret = CreateAppSpawnServer(&appSpawnContent->server, socketName); 128969570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, AppSpawnDestroyContent(&appSpawnContent->content); 129069570cc8Sopenharmony_ci return NULL, "Failed to create server"); 129169570cc8Sopenharmony_ci } 129269570cc8Sopenharmony_ci appSpawnContent->content.enablePerfork = IsEnablePerfork(); 129369570cc8Sopenharmony_ci return &appSpawnContent->content; 129469570cc8Sopenharmony_ci} 129569570cc8Sopenharmony_ci 129669570cc8Sopenharmony_ciAppSpawnContent *StartSpawnService(const AppSpawnStartArg *startArg, uint32_t argvSize, int argc, char *const argv[]) 129769570cc8Sopenharmony_ci{ 129869570cc8Sopenharmony_ci APPSPAWN_CHECK(startArg != NULL && argv != NULL, return NULL, "Invalid start arg"); 129969570cc8Sopenharmony_ci pid_t pid = 0; 130069570cc8Sopenharmony_ci AppSpawnStartArg *arg = (AppSpawnStartArg *)startArg; 130169570cc8Sopenharmony_ci APPSPAWN_LOGV("Start appspawn argvSize %{public}d mode %{public}d service %{public}s", 130269570cc8Sopenharmony_ci argvSize, arg->mode, arg->serviceName); 130369570cc8Sopenharmony_ci if (arg->mode == MODE_FOR_APP_SPAWN) { 130469570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST 130569570cc8Sopenharmony_ci pid = NWebSpawnLaunch(); 130669570cc8Sopenharmony_ci if (pid == 0) { 130769570cc8Sopenharmony_ci arg->socketName = NWEBSPAWN_SOCKET_NAME; 130869570cc8Sopenharmony_ci arg->serviceName = NWEBSPAWN_SERVER_NAME; 130969570cc8Sopenharmony_ci arg->moduleType = MODULE_NWEBSPAWN; 131069570cc8Sopenharmony_ci arg->mode = MODE_FOR_NWEB_SPAWN; 131169570cc8Sopenharmony_ci arg->initArg = 1; 131269570cc8Sopenharmony_ci } 131369570cc8Sopenharmony_ci#endif 131469570cc8Sopenharmony_ci } else if (arg->mode == MODE_FOR_NWEB_SPAWN && getuid() == 0) { 131569570cc8Sopenharmony_ci NWebSpawnInit(); 131669570cc8Sopenharmony_ci } 131769570cc8Sopenharmony_ci if (arg->initArg) { 131869570cc8Sopenharmony_ci int ret = memset_s(argv[0], argvSize, 0, (size_t)argvSize); 131969570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == EOK, return NULL, "Failed to memset argv[0]"); 132069570cc8Sopenharmony_ci ret = strncpy_s(argv[0], argvSize, arg->serviceName, strlen(arg->serviceName)); 132169570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == EOK, return NULL, "Failed to copy service name %{public}s", arg->serviceName); 132269570cc8Sopenharmony_ci } 132369570cc8Sopenharmony_ci 132469570cc8Sopenharmony_ci // load module appspawn/common 132569570cc8Sopenharmony_ci AppSpawnLoadAutoRunModules(MODULE_COMMON); 132669570cc8Sopenharmony_ci AppSpawnModuleMgrInstall(ASAN_MODULE_PATH); 132769570cc8Sopenharmony_ci 132869570cc8Sopenharmony_ci APPSPAWN_CHECK(LE_GetDefaultLoop() != NULL, return NULL, "Invalid default loop"); 132969570cc8Sopenharmony_ci AppSpawnContent *content = AppSpawnCreateContent(arg->socketName, argv[0], argvSize, arg->mode); 133069570cc8Sopenharmony_ci APPSPAWN_CHECK(content != NULL, return NULL, "Failed to create content for %{public}s", arg->socketName); 133169570cc8Sopenharmony_ci 133269570cc8Sopenharmony_ci AppSpawnLoadAutoRunModules(arg->moduleType); // load corresponding plugin according to startup mode 133369570cc8Sopenharmony_ci int ret = ServerStageHookExecute(STAGE_SERVER_PRELOAD, content); // Preload, prase the sandbox 133469570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, AppSpawnDestroyContent(content); 133569570cc8Sopenharmony_ci return NULL, "Failed to prepare load %{public}s result: %{public}d", arg->serviceName, ret); 133669570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST 133769570cc8Sopenharmony_ci APPSPAWN_CHECK(content->runChildProcessor != NULL, AppSpawnDestroyContent(content); 133869570cc8Sopenharmony_ci return NULL, "No child processor %{public}s result: %{public}d", arg->serviceName, ret); 133969570cc8Sopenharmony_ci#endif 134069570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_CHILD_PRE_RUN, HOOK_PRIO_LOWEST, AppSpawnClearEnv); 134169570cc8Sopenharmony_ci if (arg->mode == MODE_FOR_APP_SPAWN) { 134269570cc8Sopenharmony_ci AddSpawnedProcess(pid, NWEBSPAWN_SERVER_NAME, false); 134369570cc8Sopenharmony_ci SetParameter("bootevent.appspawn.started", "true"); 134469570cc8Sopenharmony_ci } 134569570cc8Sopenharmony_ci return content; 134669570cc8Sopenharmony_ci} 134769570cc8Sopenharmony_ci 134869570cc8Sopenharmony_cistatic AppSpawnMsgNode *ProcessSpawnBegetctlMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) 134969570cc8Sopenharmony_ci{ 135069570cc8Sopenharmony_ci uint32_t len = 0; 135169570cc8Sopenharmony_ci const char *cmdMsg = (const char *)GetAppSpawnMsgExtInfo(message, MSG_EXT_NAME_BEGET_PID, &len); 135269570cc8Sopenharmony_ci APPSPAWN_CHECK(cmdMsg != NULL, return NULL, "Failed to get extInfo"); 135369570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = GetSpawnedProcess(atoi(cmdMsg)); 135469570cc8Sopenharmony_ci APPSPAWN_CHECK(appInfo != NULL, return NULL, "Failed to get app info"); 135569570cc8Sopenharmony_ci AppSpawnMsgNode *msgNode = RebuildAppSpawnMsgNode(message, appInfo); 135669570cc8Sopenharmony_ci APPSPAWN_CHECK(msgNode != NULL, return NULL, "Failed to rebuild app message node"); 135769570cc8Sopenharmony_ci int ret = DecodeAppSpawnMsg(msgNode); 135869570cc8Sopenharmony_ci if (ret != 0) { 135969570cc8Sopenharmony_ci DeleteAppSpawnMsg(msgNode); 136069570cc8Sopenharmony_ci return NULL; 136169570cc8Sopenharmony_ci } 136269570cc8Sopenharmony_ci return msgNode; 136369570cc8Sopenharmony_ci} 136469570cc8Sopenharmony_ci 136569570cc8Sopenharmony_cistatic void ProcessBegetCmdMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) 136669570cc8Sopenharmony_ci{ 136769570cc8Sopenharmony_ci AppSpawnMsg *msg = &message->msgHeader; 136869570cc8Sopenharmony_ci if (!IsDeveloperModeOpen()) { 136969570cc8Sopenharmony_ci SendResponse(connection, msg, APPSPAWN_DEBUG_MODE_NOT_SUPPORT, 0); 137069570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 137169570cc8Sopenharmony_ci return; 137269570cc8Sopenharmony_ci } 137369570cc8Sopenharmony_ci AppSpawnMsgNode *msgNode = ProcessSpawnBegetctlMsg(connection, message); 137469570cc8Sopenharmony_ci if (msgNode == NULL) { 137569570cc8Sopenharmony_ci SendResponse(connection, msg, APPSPAWN_DEBUG_MODE_NOT_SUPPORT, 0); 137669570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 137769570cc8Sopenharmony_ci return; 137869570cc8Sopenharmony_ci } 137969570cc8Sopenharmony_ci ProcessSpawnReqMsg(connection, msgNode); 138069570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 138169570cc8Sopenharmony_ci DeleteAppSpawnMsg(msgNode); 138269570cc8Sopenharmony_ci} 138369570cc8Sopenharmony_ci 138469570cc8Sopenharmony_cistatic int GetArkWebInstallPath(const char *key, char *value) 138569570cc8Sopenharmony_ci{ 138669570cc8Sopenharmony_ci int len = GetParameter(key, "", value, PATH_SIZE); 138769570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 0, return -1, "Failed to get arkwebcore install path from param, len %{public}d", len); 138869570cc8Sopenharmony_ci for (int i = len - 1; i >= 0; i--) { 138969570cc8Sopenharmony_ci if (value[i] == '/') { 139069570cc8Sopenharmony_ci value[i] = '\0'; 139169570cc8Sopenharmony_ci return i; 139269570cc8Sopenharmony_ci } 139369570cc8Sopenharmony_ci value[i] = '\0'; 139469570cc8Sopenharmony_ci } 139569570cc8Sopenharmony_ci return -1; 139669570cc8Sopenharmony_ci} 139769570cc8Sopenharmony_ci 139869570cc8Sopenharmony_cistatic bool CheckAllDigit(char *userId) 139969570cc8Sopenharmony_ci{ 140069570cc8Sopenharmony_ci for (int i = 0; userId[i] != '\0'; i++) { 140169570cc8Sopenharmony_ci if (!isdigit(userId[i])) { 140269570cc8Sopenharmony_ci return false; 140369570cc8Sopenharmony_ci } 140469570cc8Sopenharmony_ci } 140569570cc8Sopenharmony_ci return true; 140669570cc8Sopenharmony_ci} 140769570cc8Sopenharmony_ci 140869570cc8Sopenharmony_ci#ifdef APPSPAWN_SANDBOX_NEW 140969570cc8Sopenharmony_cistatic int ProcessSpawnRemountMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) 141069570cc8Sopenharmony_ci{ 141169570cc8Sopenharmony_ci char srcPath[PATH_SIZE] = {0}; 141269570cc8Sopenharmony_ci int len = GetArkWebInstallPath("persist.arkwebcore.install_path", srcPath); 141369570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 0, return -1, "Failed to get arkwebcore install path"); 141469570cc8Sopenharmony_ci 141569570cc8Sopenharmony_ci char *rootPath = "/mnt/sandbox"; 141669570cc8Sopenharmony_ci DIR *rootDir = opendir(rootPath); 141769570cc8Sopenharmony_ci APPSPAWN_CHECK(rootDir != NULL, return -1, "Failed to opendir %{public}s, errno %{public}d", rootPath, errno); 141869570cc8Sopenharmony_ci 141969570cc8Sopenharmony_ci struct dirent *ent; 142069570cc8Sopenharmony_ci while ((ent = readdir(rootDir)) != NULL) { 142169570cc8Sopenharmony_ci char *userId = ent->d_name; 142269570cc8Sopenharmony_ci if (strcmp(userId, ".") == 0 || strcmp(userId, "..") == 0 || !CheckAllDigit(userId)) { 142369570cc8Sopenharmony_ci continue; 142469570cc8Sopenharmony_ci } 142569570cc8Sopenharmony_ci char destPath[PATH_SIZE] = {0}; 142669570cc8Sopenharmony_ci int ret = snprintf_s(destPath, sizeof(destPath), sizeof(destPath) - 1, 142769570cc8Sopenharmony_ci "%s/%s/app-root/mnt/nweb/tmp", rootPath, userId); 142869570cc8Sopenharmony_ci APPSPAWN_CHECK(ret > 0, continue, "Failed to snprintf_s, errno %{public}d", errno); 142969570cc8Sopenharmony_ci 143069570cc8Sopenharmony_ci ret = umount2(destPath, MNT_DETACH); 143169570cc8Sopenharmony_ci if (ret != 0) { 143269570cc8Sopenharmony_ci APPSPAWN_LOGW("Umount %{public}s failed, errno %{public}d", destPath, errno); 143369570cc8Sopenharmony_ci } 143469570cc8Sopenharmony_ci 143569570cc8Sopenharmony_ci ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL); 143669570cc8Sopenharmony_ci if (ret != 0 && errno == EBUSY) { 143769570cc8Sopenharmony_ci ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL); 143869570cc8Sopenharmony_ci APPSPAWN_LOGW("Bind mount again %{public}s to %{public}s, ret %{public}d", srcPath, destPath, ret); 143969570cc8Sopenharmony_ci } 144069570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, continue, 144169570cc8Sopenharmony_ci "Failed to bind mount %{public}s to %{public}s, errno %{public}d", srcPath, destPath, errno); 144269570cc8Sopenharmony_ci 144369570cc8Sopenharmony_ci ret = mount(NULL, destPath, NULL, MS_SHARED, NULL); 144469570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, continue, 144569570cc8Sopenharmony_ci "Failed to shared mount %{public}s, errno %{public}d", destPath, errno); 144669570cc8Sopenharmony_ci 144769570cc8Sopenharmony_ci APPSPAWN_LOGI("Remount %{public}s to %{public}s success", srcPath, destPath); 144869570cc8Sopenharmony_ci } 144969570cc8Sopenharmony_ci closedir(rootDir); 145069570cc8Sopenharmony_ci return 0; 145169570cc8Sopenharmony_ci} 145269570cc8Sopenharmony_ci#else 145369570cc8Sopenharmony_cistatic int ProcessSpawnRemountMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) 145469570cc8Sopenharmony_ci{ 145569570cc8Sopenharmony_ci char srcPath[PATH_SIZE] = {0}; 145669570cc8Sopenharmony_ci int len = GetArkWebInstallPath("persist.arkwebcore.install_path", srcPath); 145769570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 0, return -1, "Failed to get arkwebcore install path"); 145869570cc8Sopenharmony_ci 145969570cc8Sopenharmony_ci char *rootPath = "/mnt/sandbox"; 146069570cc8Sopenharmony_ci DIR *rootDir = opendir(rootPath); 146169570cc8Sopenharmony_ci APPSPAWN_CHECK(rootDir != NULL, return -1, "Failed to opendir %{public}s, errno %{public}d", rootPath, errno); 146269570cc8Sopenharmony_ci 146369570cc8Sopenharmony_ci struct dirent *ent; 146469570cc8Sopenharmony_ci while ((ent = readdir(rootDir)) != NULL) { 146569570cc8Sopenharmony_ci char *userId = ent->d_name; 146669570cc8Sopenharmony_ci if (strcmp(userId, ".") == 0 || strcmp(userId, "..") == 0 || !CheckAllDigit(userId)) { 146769570cc8Sopenharmony_ci continue; 146869570cc8Sopenharmony_ci } 146969570cc8Sopenharmony_ci 147069570cc8Sopenharmony_ci char userIdPath[PATH_SIZE] = {0}; 147169570cc8Sopenharmony_ci int ret = snprintf_s(userIdPath, sizeof(userIdPath), sizeof(userIdPath) - 1, "%s/%s", rootPath, userId); 147269570cc8Sopenharmony_ci APPSPAWN_CHECK(ret > 0, continue, "Failed to snprintf_s, errno %{public}d", errno); 147369570cc8Sopenharmony_ci 147469570cc8Sopenharmony_ci DIR *userIdDir = opendir(userIdPath); 147569570cc8Sopenharmony_ci APPSPAWN_CHECK(userIdDir != NULL, continue, "Failed to open %{public}s, errno %{public}d", userIdPath, errno); 147669570cc8Sopenharmony_ci 147769570cc8Sopenharmony_ci while ((ent = readdir(userIdDir)) != NULL) { 147869570cc8Sopenharmony_ci char *bundleName = ent->d_name; 147969570cc8Sopenharmony_ci if (strcmp(bundleName, ".") == 0 || strcmp(bundleName, "..") == 0) { 148069570cc8Sopenharmony_ci continue; 148169570cc8Sopenharmony_ci } 148269570cc8Sopenharmony_ci char destPath[PATH_SIZE] = {0}; 148369570cc8Sopenharmony_ci ret = snprintf_s(destPath, sizeof(destPath), sizeof(destPath) - 1, 148469570cc8Sopenharmony_ci "%s/%s/data/storage/el1/bundle/arkwebcore", userIdPath, bundleName); 148569570cc8Sopenharmony_ci APPSPAWN_CHECK(ret > 0, continue, "Failed to snprintf_s, errno %{public}d", errno); 148669570cc8Sopenharmony_ci 148769570cc8Sopenharmony_ci umount2(destPath, MNT_DETACH); 148869570cc8Sopenharmony_ci ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL); 148969570cc8Sopenharmony_ci if (ret != 0 && errno == EBUSY) { 149069570cc8Sopenharmony_ci ret = mount(srcPath, destPath, NULL, MS_BIND | MS_REC, NULL); 149169570cc8Sopenharmony_ci APPSPAWN_LOGV("mount again %{public}s to %{public}s, ret %{public}d", srcPath, destPath, ret); 149269570cc8Sopenharmony_ci } 149369570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, continue, 149469570cc8Sopenharmony_ci "Failed to bind mount %{public}s to %{public}s, errno %{public}d", srcPath, destPath, errno); 149569570cc8Sopenharmony_ci 149669570cc8Sopenharmony_ci ret = mount(NULL, destPath, NULL, MS_SHARED, NULL); 149769570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, continue, 149869570cc8Sopenharmony_ci "Failed to shared mount %{public}s to %{public}s, errno %{public}d", srcPath, destPath, errno); 149969570cc8Sopenharmony_ci 150069570cc8Sopenharmony_ci APPSPAWN_LOGV("Remount %{public}s to %{public}s success", srcPath, destPath); 150169570cc8Sopenharmony_ci } 150269570cc8Sopenharmony_ci closedir(userIdDir); 150369570cc8Sopenharmony_ci } 150469570cc8Sopenharmony_ci closedir(rootDir); 150569570cc8Sopenharmony_ci return 0; 150669570cc8Sopenharmony_ci} 150769570cc8Sopenharmony_ci#endif 150869570cc8Sopenharmony_ci 150969570cc8Sopenharmony_cistatic void ProcessSpawnRestartMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) 151069570cc8Sopenharmony_ci{ 151169570cc8Sopenharmony_ci AppSpawnContent *content = GetAppSpawnContent(); 151269570cc8Sopenharmony_ci if (!IsNWebSpawnMode((AppSpawnMgr *)content)) { 151369570cc8Sopenharmony_ci SendResponse(connection, &message->msgHeader, APPSPAWN_MSG_INVALID, 0); 151469570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 151569570cc8Sopenharmony_ci APPSPAWN_LOGE("Restart msg only support nwebspawn"); 151669570cc8Sopenharmony_ci return; 151769570cc8Sopenharmony_ci } 151869570cc8Sopenharmony_ci 151969570cc8Sopenharmony_ci TraversalSpawnedProcess(AppQueueDestroyProc, NULL); 152069570cc8Sopenharmony_ci SendResponse(connection, &message->msgHeader, 0, 0); 152169570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 152269570cc8Sopenharmony_ci (void) ServerStageHookExecute(STAGE_SERVER_EXIT, content); 152369570cc8Sopenharmony_ci 152469570cc8Sopenharmony_ci errno = 0; 152569570cc8Sopenharmony_ci int fd = GetControlSocket(NWEBSPAWN_SOCKET_NAME); 152669570cc8Sopenharmony_ci APPSPAWN_CHECK(fd >= 0, return, "Get fd failed %{public}d, errno %{public}d", fd, errno); 152769570cc8Sopenharmony_ci 152869570cc8Sopenharmony_ci int op = fcntl(fd, F_GETFD); 152969570cc8Sopenharmony_ci int ret = fcntl(fd, F_SETFD, (unsigned int)op & ~FD_CLOEXEC); 153069570cc8Sopenharmony_ci if (ret < 0) { 153169570cc8Sopenharmony_ci APPSPAWN_LOGE("Set fd failed %{public}d, %{public}d, ret %{public}d, errno %{public}d", fd, op, ret, errno); 153269570cc8Sopenharmony_ci } 153369570cc8Sopenharmony_ci 153469570cc8Sopenharmony_ci char *path = "/system/bin/appspawn"; 153569570cc8Sopenharmony_ci char *mode = NWEBSPAWN_RESTART; 153669570cc8Sopenharmony_ci const char *const formatCmds[] = {path, "-mode", mode, NULL}; 153769570cc8Sopenharmony_ci ret = execv(path, (char **)formatCmds); 153869570cc8Sopenharmony_ci APPSPAWN_LOGE("Failed to execv, ret %{public}d, errno %{public}d", ret, errno); 153969570cc8Sopenharmony_ci} 154069570cc8Sopenharmony_ci 154169570cc8Sopenharmony_ciAPPSPAWN_STATIC int AppspawpnDevicedebugKill(int pid, cJSON *args) 154269570cc8Sopenharmony_ci{ 154369570cc8Sopenharmony_ci cJSON *signal = cJSON_GetObjectItem(args, "signal"); 154469570cc8Sopenharmony_ci if (!cJSON_IsNumber(signal)) { 154569570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug json get signal fail"); 154669570cc8Sopenharmony_ci return -1; 154769570cc8Sopenharmony_ci } 154869570cc8Sopenharmony_ci 154969570cc8Sopenharmony_ci AppSpawnedProcess *appInfo = GetSpawnedProcess(pid); 155069570cc8Sopenharmony_ci if (appInfo == NULL) { 155169570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug get app info unsuccess, pid=%{public}d", pid); 155269570cc8Sopenharmony_ci return -1; 155369570cc8Sopenharmony_ci } 155469570cc8Sopenharmony_ci 155569570cc8Sopenharmony_ci if (!appInfo->isDebuggable) { 155669570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug process is not debuggable, pid=%{public}d", pid); 155769570cc8Sopenharmony_ci return -1; 155869570cc8Sopenharmony_ci } 155969570cc8Sopenharmony_ci 156069570cc8Sopenharmony_ci APPSPAWN_LOGI("appspawn devicedebug debugable=%{public}d, pid=%{public}d, signal=%{public}d", 156169570cc8Sopenharmony_ci appInfo->isDebuggable, pid, signal->valueint); 156269570cc8Sopenharmony_ci 156369570cc8Sopenharmony_ci if (kill(pid, signal->valueint) != 0) { 156469570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug unable to kill process, pid: %{public}d ret %{public}d", pid, errno); 156569570cc8Sopenharmony_ci return -1; 156669570cc8Sopenharmony_ci } 156769570cc8Sopenharmony_ci 156869570cc8Sopenharmony_ci return 0; 156969570cc8Sopenharmony_ci} 157069570cc8Sopenharmony_ci 157169570cc8Sopenharmony_ciAPPSPAWN_STATIC int AppspawnDevicedebugDeal(const char* op, int pid, cJSON *args) 157269570cc8Sopenharmony_ci{ 157369570cc8Sopenharmony_ci if (strcmp(op, "kill") == 0) { 157469570cc8Sopenharmony_ci return AppspawpnDevicedebugKill(pid, args); 157569570cc8Sopenharmony_ci } 157669570cc8Sopenharmony_ci 157769570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug op:%{public}s invaild", op); 157869570cc8Sopenharmony_ci 157969570cc8Sopenharmony_ci return -1; 158069570cc8Sopenharmony_ci} 158169570cc8Sopenharmony_ci 158269570cc8Sopenharmony_ciAPPSPAWN_STATIC int ProcessAppSpawnDeviceDebugMsg(AppSpawnMsgNode *message) 158369570cc8Sopenharmony_ci{ 158469570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(message != NULL, return -1); 158569570cc8Sopenharmony_ci uint32_t len = 0; 158669570cc8Sopenharmony_ci 158769570cc8Sopenharmony_ci const char* jsonString = (char *)GetAppSpawnMsgExtInfo(message, "devicedebug", &len); 158869570cc8Sopenharmony_ci if (jsonString == NULL || len == 0) { 158969570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug get devicedebug fail"); 159069570cc8Sopenharmony_ci return -1; 159169570cc8Sopenharmony_ci } 159269570cc8Sopenharmony_ci 159369570cc8Sopenharmony_ci cJSON *json = cJSON_Parse(jsonString); 159469570cc8Sopenharmony_ci if (json == NULL) { 159569570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug json parse fail"); 159669570cc8Sopenharmony_ci return -1; 159769570cc8Sopenharmony_ci } 159869570cc8Sopenharmony_ci 159969570cc8Sopenharmony_ci cJSON *app = cJSON_GetObjectItem(json, "app"); 160069570cc8Sopenharmony_ci if (!cJSON_IsNumber(app)) { 160169570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug json get app fail"); 160269570cc8Sopenharmony_ci return -1; 160369570cc8Sopenharmony_ci } 160469570cc8Sopenharmony_ci 160569570cc8Sopenharmony_ci cJSON *op = cJSON_GetObjectItem(json, "op"); 160669570cc8Sopenharmony_ci if (!cJSON_IsString(op) || op->valuestring == NULL) { 160769570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug json get op fail"); 160869570cc8Sopenharmony_ci return -1; 160969570cc8Sopenharmony_ci } 161069570cc8Sopenharmony_ci 161169570cc8Sopenharmony_ci cJSON *args = cJSON_GetObjectItem(json, "args"); 161269570cc8Sopenharmony_ci if (!cJSON_IsObject(args)) { 161369570cc8Sopenharmony_ci APPSPAWN_LOGE("appspawn devicedebug json get args fail"); 161469570cc8Sopenharmony_ci return -1; 161569570cc8Sopenharmony_ci } 161669570cc8Sopenharmony_ci 161769570cc8Sopenharmony_ci return AppspawnDevicedebugDeal(op->valuestring, app->valueint, args); 161869570cc8Sopenharmony_ci} 161969570cc8Sopenharmony_ci 162069570cc8Sopenharmony_cistatic void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message) 162169570cc8Sopenharmony_ci{ 162269570cc8Sopenharmony_ci AppSpawnMsg *msg = &message->msgHeader; 162369570cc8Sopenharmony_ci APPSPAWN_LOGI("Recv message header magic 0x%{public}x type %{public}u id %{public}u len %{public}u %{public}s", 162469570cc8Sopenharmony_ci msg->magic, msg->msgType, msg->msgId, msg->msgLen, msg->processName); 162569570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_LOG(connection->receiverCtx.nextMsgId == msg->msgId, 162669570cc8Sopenharmony_ci "Invalid msg id %{public}u %{public}u", connection->receiverCtx.nextMsgId, msg->msgId); 162769570cc8Sopenharmony_ci connection->receiverCtx.nextMsgId++; 162869570cc8Sopenharmony_ci 162969570cc8Sopenharmony_ci int ret; 163069570cc8Sopenharmony_ci switch (msg->msgType) { 163169570cc8Sopenharmony_ci case MSG_GET_RENDER_TERMINATION_STATUS: { // get status 163269570cc8Sopenharmony_ci AppSpawnResult result = {0}; 163369570cc8Sopenharmony_ci ret = ProcessTerminationStatusMsg(message, &result); 163469570cc8Sopenharmony_ci SendResponse(connection, msg, ret == 0 ? result.result : ret, result.pid); 163569570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 163669570cc8Sopenharmony_ci break; 163769570cc8Sopenharmony_ci } 163869570cc8Sopenharmony_ci case MSG_SPAWN_NATIVE_PROCESS: // spawn msg 163969570cc8Sopenharmony_ci case MSG_APP_SPAWN: { 164069570cc8Sopenharmony_ci ProcessSpawnReqMsg(connection, message); 164169570cc8Sopenharmony_ci break; 164269570cc8Sopenharmony_ci } 164369570cc8Sopenharmony_ci case MSG_DUMP: 164469570cc8Sopenharmony_ci ProcessAppSpawnDumpMsg(message); 164569570cc8Sopenharmony_ci SendResponse(connection, msg, 0, 0); 164669570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 164769570cc8Sopenharmony_ci break; 164869570cc8Sopenharmony_ci case MSG_BEGET_CMD: { 164969570cc8Sopenharmony_ci ProcessBegetCmdMsg(connection, message); 165069570cc8Sopenharmony_ci break; 165169570cc8Sopenharmony_ci } 165269570cc8Sopenharmony_ci case MSG_BEGET_SPAWNTIME: 165369570cc8Sopenharmony_ci SendResponse(connection, msg, GetAppSpawnMgr()->spawnTime.minAppspawnTime, 165469570cc8Sopenharmony_ci GetAppSpawnMgr()->spawnTime.maxAppspawnTime); 165569570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 165669570cc8Sopenharmony_ci break; 165769570cc8Sopenharmony_ci case MSG_UPDATE_MOUNT_POINTS: 165869570cc8Sopenharmony_ci ret = ProcessSpawnRemountMsg(connection, message); 165969570cc8Sopenharmony_ci SendResponse(connection, msg, ret, 0); 166069570cc8Sopenharmony_ci break; 166169570cc8Sopenharmony_ci case MSG_RESTART_SPAWNER: 166269570cc8Sopenharmony_ci ProcessSpawnRestartMsg(connection, message); 166369570cc8Sopenharmony_ci break; 166469570cc8Sopenharmony_ci case MSG_DEVICE_DEBUG: 166569570cc8Sopenharmony_ci ret = ProcessAppSpawnDeviceDebugMsg(message); 166669570cc8Sopenharmony_ci SendResponse(connection, msg, ret, 0); 166769570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 166869570cc8Sopenharmony_ci break; 166969570cc8Sopenharmony_ci default: 167069570cc8Sopenharmony_ci SendResponse(connection, msg, APPSPAWN_MSG_INVALID, 0); 167169570cc8Sopenharmony_ci DeleteAppSpawnMsg(message); 167269570cc8Sopenharmony_ci break; 167369570cc8Sopenharmony_ci } 167469570cc8Sopenharmony_ci}