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