• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 #include "appspawn_adapter.h"
18 #include "appspawn_server.h"
19 
20 #include <fcntl.h>
21 #include <sys/signalfd.h>
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <sys/wait.h>
25 #include <unistd.h>
26 #include <sched.h>
27 
28 #include "init_hashmap.h"
29 #include "init_socket.h"
30 #include "init_utils.h"
31 #include "parameter.h"
32 #include "securec.h"
33 
34 #ifdef REPORT_EVENT
35 #include "event_reporter.h"
36 #endif
37 #ifndef APPSPAWN_TEST
38 #define TV_SEC 60
39 #define APPSPAWN_EXIT_TIME 60000
40 #else
41 #define TV_SEC 2
42 #define APPSPAWN_EXIT_TIME 500
43 #endif
44 
45 static AppSpawnContentExt *g_appSpawnContent = NULL;
AppInfoHashNodeCompare(const HashNode * node1,const HashNode * node2)46 static int AppInfoHashNodeCompare(const HashNode *node1, const HashNode *node2)
47 {
48     AppInfo *testNode1 = HASHMAP_ENTRY(node1, AppInfo, node);
49     AppInfo *testNode2 = HASHMAP_ENTRY(node2, AppInfo, node);
50     return testNode1->pid - testNode2->pid;
51 }
52 
TestHashKeyCompare(const HashNode * node1,const void * key)53 static int TestHashKeyCompare(const HashNode *node1, const void *key)
54 {
55     AppInfo *testNode1 = HASHMAP_ENTRY(node1, AppInfo, node);
56     return testNode1->pid - *(pid_t *)key;
57 }
58 
AppInfoHashNodeFunction(const HashNode * node)59 static int AppInfoHashNodeFunction(const HashNode *node)
60 {
61     AppInfo *testNode = HASHMAP_ENTRY(node, AppInfo, node);
62     return testNode->pid % APP_HASH_BUTT;
63 }
64 
AppInfoHashKeyFunction(const void * key)65 static int AppInfoHashKeyFunction(const void *key)
66 {
67     pid_t code = *(pid_t *)key;
68     return code % APP_HASH_BUTT;
69 }
70 
AppInfoHashNodeFree(const HashNode * node,void * context)71 static void AppInfoHashNodeFree(const HashNode *node, void *context)
72 {
73     (void)context;
74     AppInfo *testNode = HASHMAP_ENTRY(node, AppInfo, node);
75     APPSPAWN_LOGI("AppInfoHashNodeFree %{public}s\n", testNode->name);
76     free(testNode);
77 }
78 
AddAppInfo(pid_t pid,const char * processName)79 APPSPAWN_STATIC void AddAppInfo(pid_t pid, const char *processName)
80 {
81     size_t len = strlen(processName) + 1;
82     AppInfo *node = (AppInfo *)malloc(sizeof(AppInfo) + len + 1);
83     APPSPAWN_CHECK(node != NULL, return, "Failed to malloc for appinfo");
84 
85     node->pid = pid;
86     int ret = strcpy_s(node->name, len, processName);
87     APPSPAWN_CHECK(ret == 0, free(node);
88         return, "Failed to strcpy process name");
89     HASHMAPInitNode(&node->node);
90     ret = OH_HashMapAdd(g_appSpawnContent->appMap, &node->node);
91     APPSPAWN_CHECK(ret == 0, free(node);
92         return, "Failed to add appinfo to hash");
93     APPSPAWN_LOGI("Add %{public}s, pid=%{public}d success", processName, pid);
94 }
95 
AddNwebInfo(pid_t pid,const char * processName)96 void AddNwebInfo(pid_t pid, const char *processName)
97 {
98     AddAppInfo(pid, processName);
99 }
100 
GetAppInfo(pid_t pid)101 static AppInfo *GetAppInfo(pid_t pid)
102 {
103     HashNode *node = OH_HashMapGet(g_appSpawnContent->appMap, (const void *)&pid);
104     APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL);
105     return HASHMAP_ENTRY(node, AppInfo, node);
106 }
107 
RemoveAppInfo(pid_t pid)108 static void RemoveAppInfo(pid_t pid)
109 {
110     AppInfo *appInfo = GetAppInfo(pid);
111     APPSPAWN_CHECK(appInfo != NULL, return, "Can not find app info for %{public}d", pid);
112     OH_HashMapRemove(g_appSpawnContent->appMap, (const void *)&pid);
113     free(appInfo);
114     if ((g_appSpawnContent->flags & FLAGS_ON_DEMAND) != FLAGS_ON_DEMAND) {
115         return;
116     }
117 }
118 
KillProcess(const HashNode * node,const void * context)119 static void KillProcess(const HashNode *node, const void *context)
120 {
121     AppInfo *hashNode = (AppInfo *)node;
122     kill(hashNode->pid, SIGKILL);
123     APPSPAWN_LOGI("kill app, pid = %{public}d, processName = %{public}s", hashNode->pid, hashNode->name);
124 }
125 
OnClose(const TaskHandle taskHandle)126 static void OnClose(const TaskHandle taskHandle)
127 {
128     AppSpawnClientExt *client = (AppSpawnClientExt *)LE_GetUserData(taskHandle);
129     APPSPAWN_CHECK(client != NULL, return, "Invalid client");
130     APPSPAWN_LOGI("OnClose %{public}d processName = %{public}s",
131         client->client.id, client->property.processName);
132     if (client->property.hspList.data != NULL) {
133         free(client->property.hspList.data);
134         client->property.hspList.totalLength = 0;
135         client->property.hspList.savedLength = 0;
136         client->property.hspList.data = NULL;
137     }
138     if (client->property.overlayInfo.data != NULL) {
139         free(client->property.overlayInfo.data);
140         client->property.overlayInfo.totalLength = 0;
141         client->property.overlayInfo.data = NULL;
142     }
143     if (client->property.dataGroupInfoList.data != NULL) {
144         free(client->property.dataGroupInfoList.data);
145         client->property.dataGroupInfoList.totalLength = 0;
146         client->property.dataGroupInfoList.data = NULL;
147     }
148 }
149 
SendMessageComplete(const TaskHandle taskHandle,BufferHandle handle)150 static void SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle)
151 {
152     AppSpawnClientExt *client = (AppSpawnClientExt *)LE_GetUserData(taskHandle);
153     APPSPAWN_CHECK(client != NULL, return, "Failed to get client");
154     APPSPAWN_LOGI("SendMessageComplete client.id %{public}d result %{public}d pid %{public}d",
155         client->client.id, LE_GetSendResult(handle), client->pid);
156     if (LE_GetSendResult(handle) != 0 && client->pid > 0) {
157         kill(client->pid, SIGKILL);
158         APPSPAWN_LOGI("Send message fail err:%{public}d kill app [ %{public}d %{public}s]",
159             LE_GetSendResult(handle), client->pid, client->property.bundleName);
160     }
161 }
162 
SendResponse(AppSpawnClientExt * client,const char * buff,size_t buffSize)163 static int SendResponse(AppSpawnClientExt *client, const char *buff, size_t buffSize)
164 {
165     uint32_t bufferSize = buffSize;
166     BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize);
167     char *buffer = (char *)LE_GetBufferInfo(handle, NULL, &bufferSize);
168     int ret = memcpy_s(buffer, bufferSize, buff, buffSize);
169     APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize");
170     return LE_Send(LE_GetDefaultLoop(), client->stream, handle, buffSize);
171 }
172 
HandleDiedPid(pid_t pid,uid_t uid,int status)173 static void HandleDiedPid(pid_t pid, uid_t uid, int status)
174 {
175     AppInfo *appInfo = GetAppInfo(pid);
176     APPSPAWN_CHECK(appInfo != NULL, return, "Can not find app info for %{public}d", pid);
177     if (WIFSIGNALED(status)) {
178         APPSPAWN_LOGW("%{public}s with pid %{public}d exit with signal:%{public}d",
179             appInfo->name, pid, WTERMSIG(status));
180     }
181     if (WIFEXITED(status)) {
182         APPSPAWN_LOGW("%{public}s with pid %{public}d exit with code:%{public}d",
183             appInfo->name, pid, WEXITSTATUS(status));
184     }
185 
186 #ifdef REPORT_EVENT
187     ReportProcessExitInfo(appInfo->name, pid, uid, status);
188 #endif
189 
190     // delete app info
191     RemoveAppInfo(pid);
192 }
193 
HandleDiedPidNweb(pid_t pid,uid_t uid,int status)194 static void HandleDiedPidNweb(pid_t pid, uid_t uid, int status)
195 {
196     AppInfo *appInfo = GetAppInfo(pid);
197     APPSPAWN_CHECK(appInfo != NULL, return, "Can not find app info for %{public}d", pid);
198     if (WIFSIGNALED(status)) {
199         APPSPAWN_LOGW("%{public}s with pid %{public}d exit with signal:%{public}d",
200             appInfo->name, pid, WTERMSIG(status));
201     }
202     if (WIFEXITED(status)) {
203         APPSPAWN_LOGW("%{public}s with pid %{public}d exit with code:%{public}d",
204             appInfo->name, pid, WEXITSTATUS(status));
205     }
206 
207 #ifdef REPORT_EVENT
208     ReportProcessExitInfo(appInfo->name, pid, uid, status);
209 #endif
210 
211     // nwebspawn will invoke waitpid and remove appinfo at GetProcessTerminationStatusInner when
212     // GetProcessTerminationStatusInner is called before the parent process receives the SIGCHLD signal.
213     RecordRenderProcessExitedStatus(pid, status);
214 
215     // delete app info
216     RemoveAppInfo(pid);
217 }
218 
SignalHandler(const struct signalfd_siginfo * siginfo)219 APPSPAWN_STATIC void SignalHandler(const struct signalfd_siginfo *siginfo)
220 {
221     APPSPAWN_LOGI("SignalHandler signum %{public}d", siginfo->ssi_signo);
222     switch (siginfo->ssi_signo) {
223         case SIGCHLD: {  // delete pid from app map
224             pid_t pid;
225             int status;
226             while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
227                 HandleDiedPid(pid, siginfo->ssi_uid, status);
228             }
229             break;
230         }
231         case SIGTERM: {  // appswapn killed, use kill without parameter
232             OH_HashMapTraverse(g_appSpawnContent->appMap, KillProcess, NULL);
233             LE_StopLoop(LE_GetDefaultLoop());
234             break;
235         }
236         default:
237             APPSPAWN_LOGI("SigHandler, unsupported signal %{public}d.", siginfo->ssi_signo);
238             break;
239     }
240 }
241 
SignalHandlerNweb(const struct signalfd_siginfo * siginfo)242 APPSPAWN_STATIC void SignalHandlerNweb(const struct signalfd_siginfo *siginfo)
243 {
244     APPSPAWN_LOGI("SignalHandler signum %{public}d", siginfo->ssi_signo);
245     switch (siginfo->ssi_signo) {
246         case SIGCHLD: {  // delete pid from app map
247             pid_t pid;
248             int status;
249             while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
250                 HandleDiedPidNweb(pid, siginfo->ssi_uid, status);
251             }
252             break;
253         }
254         case SIGTERM: {  // appswapn killed, use kill without parameter
255             OH_HashMapTraverse(g_appSpawnContent->appMap, KillProcess, NULL);
256             LE_StopLoop(LE_GetDefaultLoop());
257             break;
258         }
259         default:
260             APPSPAWN_LOGI("SigHandler, unsupported signal %{public}d.", siginfo->ssi_signo);
261             break;
262     }
263 }
264 
HandleSpecial(AppSpawnClientExt * appProperty)265 static void HandleSpecial(AppSpawnClientExt *appProperty)
266 {
267     // special handle bundle name medialibrary and scanner
268     const char *specialBundleNames[] = {
269         "com.ohos.medialibrary.medialibrarydata"
270     };
271 
272     for (size_t i = 0; i < sizeof(specialBundleNames) / sizeof(specialBundleNames[0]); i++) {
273         if (strcmp(appProperty->property.bundleName, specialBundleNames[i]) == 0) {
274             if (appProperty->property.gidCount < APP_MAX_GIDS) {
275                 appProperty->property.gidTable[appProperty->property.gidCount++] = GID_USER_DATA_RW;
276                 appProperty->property.gidTable[appProperty->property.gidCount++] = GID_FILE_ACCESS;
277             }
278             break;
279         }
280     }
281 }
282 
WaitChild(int fd,int pid,const AppSpawnClientExt * appProperty)283 static int WaitChild(int fd, int pid, const AppSpawnClientExt *appProperty)
284 {
285     int result = 0;
286     fd_set rd;
287     struct timeval tv;
288     FD_ZERO(&rd);
289     FD_SET(fd, &rd);
290     tv.tv_sec = TV_SEC;
291     tv.tv_usec = 0;
292 
293     int ret = select(fd + 1, &rd, NULL, NULL, &tv);
294     if (ret == 0) {  // timeout
295         APPSPAWN_LOGI("Time out for child %{public}s %{public}d fd %{public}d",
296             appProperty->property.processName, pid, fd);
297         result = 0;
298     } else if (ret == -1) {
299         APPSPAWN_LOGI("Error for child %{public}s %{public}d", appProperty->property.processName, pid);
300         result = 0;
301     } else {
302         (void)read(fd, &result, sizeof(result));
303     }
304 
305     return result;
306 }
307 
CheckColdAppEnabled(AppSpawnClientExt * appProperty)308 static void CheckColdAppEnabled(AppSpawnClientExt *appProperty)
309 {
310     if ((appProperty->property.flags & 0x01) != 0) {
311         char cold[10] = {0};  // 10 cold
312         (void)GetParameter("startup.appspawn.cold.boot", "0", cold, sizeof(cold));
313         APPSPAWN_LOGV("appspawn.cold.boot %{public}s", cold);
314         if (strcmp(cold, "1") == 0) {
315             appProperty->client.flags |= APP_COLD_START;
316         }
317     }
318 }
319 
ReceiveRequestDataToDataGroup(const TaskHandle taskHandle,AppSpawnClientExt * client,const uint8_t * buffer,uint32_t buffLen)320 static bool ReceiveRequestDataToDataGroup(const TaskHandle taskHandle, AppSpawnClientExt *client,
321     const uint8_t *buffer, uint32_t buffLen)
322 {
323     if (client->property.dataGroupInfoList.totalLength) {
324         DataGroupInfoList *dataGroupInfoList = &client->property.dataGroupInfoList;
325         dataGroupInfoList->data = (char *)malloc(dataGroupInfoList->totalLength);
326         APPSPAWN_CHECK(dataGroupInfoList->data != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
327             return false, "ReceiveRequestDataToDataGroup: malloc data group failed %{public}u",
328                 dataGroupInfoList->totalLength);
329         char *data = dataGroupInfoList->data;
330 
331         APPSPAWN_CHECK(dataGroupInfoList->totalLength >= buffLen, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
332             return false, "ReceiveRequestDataToDataGroup: too many data for data group %{public}u ", buffLen);
333 
334         int ret = memcpy_s(data, buffLen, buffer, buffLen);
335         APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
336             return false, "ReceiveRequestDataToDataGroup: memcpy data group failed");
337         dataGroupInfoList->data[dataGroupInfoList->totalLength - 1] = 0;
338     }
339     return true;
340 }
341 
ReceiveRequestDataToOverlay(const TaskHandle taskHandle,AppSpawnClientExt * client,const uint8_t * buffer,uint32_t buffLen)342 static bool ReceiveRequestDataToOverlay(const TaskHandle taskHandle, AppSpawnClientExt *client,
343     const uint8_t *buffer, uint32_t buffLen)
344 {
345     if (client->property.overlayInfo.totalLength) {
346         OverlayInfo *overlayInfo = &client->property.overlayInfo;
347         overlayInfo->data = (char *)malloc(overlayInfo->totalLength);
348         APPSPAWN_CHECK(overlayInfo->data != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
349             return false, "ReceiveRequestData: malloc overlay failed %{public}u", overlayInfo->totalLength);
350         char *data = overlayInfo->data;
351 
352         uint32_t groupTotal = client->property.dataGroupInfoList.totalLength;
353         APPSPAWN_CHECK(overlayInfo->totalLength >= (buffLen - groupTotal),
354             LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
355             return false, "ReceiveRequestData: too many data for overlay %{public}u ", buffLen);
356 
357         int ret = memcpy_s(data, (buffLen - groupTotal), buffer, (buffLen - groupTotal));
358         APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
359             return false, "ReceiveRequestData: memcpy overlay failed");
360         overlayInfo->data[overlayInfo->totalLength - 1] = 0;
361         buffer += overlayInfo->totalLength;
362         buffLen -= overlayInfo->totalLength;
363     }
364     return ReceiveRequestDataToDataGroup(taskHandle, client, buffer, buffLen);
365 }
366 
ReceiveRequestDataToHspList(const TaskHandle taskHandle,AppSpawnClientExt * client,const uint8_t * buffer,uint32_t buffLen)367 static bool ReceiveRequestDataToHspList(const TaskHandle taskHandle, AppSpawnClientExt *client,
368     const uint8_t *buffer, uint32_t buffLen)
369 {
370     if (client->property.hspList.totalLength) {
371         HspList *hspList = &client->property.hspList;
372         if (hspList->savedLength == 0) {
373             hspList->data = (char *)malloc(hspList->totalLength);
374             APPSPAWN_CHECK(hspList->data != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
375                 return false, "ReceiveRequestData: malloc hspList failed %{public}u", hspList->totalLength);
376         }
377 
378         uint32_t saved = hspList->savedLength;
379         uint32_t total = hspList->totalLength;
380         char *data = hspList->data;
381 
382         uint32_t overlayTotal = client->property.overlayInfo.totalLength;
383         uint32_t groupTotal = client->property.dataGroupInfoList.totalLength;
384         APPSPAWN_LOGV("Receiving hspList: (%{public}u saved + %{public}u incoming) / %{public}u total",
385             saved, buffLen, total);
386 
387         APPSPAWN_CHECK((total - saved) >= (buffLen - overlayTotal - groupTotal),
388             LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
389             return false, "ReceiveRequestData: too many data for hspList %{public}u ", buffLen);
390 
391         int ret = memcpy_s(data + saved, (buffLen - overlayTotal - groupTotal),
392             buffer, (buffLen - overlayTotal - groupTotal));
393         APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
394             return false, "ReceiveRequestData: memcpy hspList failed");
395 
396         hspList->savedLength += (buffLen - overlayTotal - groupTotal);
397         if (hspList->savedLength < hspList->totalLength) {
398             return false;
399         }
400 
401         hspList->data[hspList->totalLength - 1] = 0;
402         buffer += hspList->totalLength;
403         buffLen -= hspList->totalLength;
404     }
405     return ReceiveRequestDataToOverlay(taskHandle, client, buffer, buffLen);
406 }
407 
ReceiveRequestData(const TaskHandle taskHandle,AppSpawnClientExt * client,const uint8_t * buffer,uint32_t buffLen)408 APPSPAWN_STATIC bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *client,
409     const uint8_t *buffer, uint32_t buffLen)
410 {
411     APPSPAWN_LOGI("ReceiveRequestData: buffLen=%{public}u", buffLen);
412     APPSPAWN_CHECK(buffer != NULL && buffLen > 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
413         return false, "ReceiveRequestData: Invalid buff");
414 
415     // 1. receive AppParamter
416     if (client->property.hspList.totalLength == 0) {
417         APPSPAWN_CHECK(buffLen >= sizeof(client->property), LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
418             return false, "ReceiveRequestData: Invalid buffLen %{public}u", buffLen);
419 
420         int ret = memcpy_s(&client->property, sizeof(client->property), buffer, sizeof(client->property));
421         APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
422             return false, "ReceiveRequestData: memcpy failed %{public}d:%{public}u", ret, buffLen);
423 
424         // reset hspList
425         client->property.hspList.savedLength = 0;
426         client->property.hspList.data = NULL;
427 
428         // update buffer
429         buffer += sizeof(client->property);
430         buffLen -= sizeof(client->property);
431     }
432 
433     // 2. check whether hspList exist
434     if (client->property.hspList.totalLength == 0 && client->property.overlayInfo.totalLength == 0
435         && client->property.dataGroupInfoList.totalLength == 0) { // no hspList
436         APPSPAWN_LOGV("ReceiveRequestData: no hspList");
437         return true;
438     } else if (buffLen == 0) {
439         APPSPAWN_LOGV("ReceiveRequestData: waiting for hspList");
440         return false;
441     }
442     return ReceiveRequestDataToHspList(taskHandle, client, buffer, buffLen);
443 }
444 
HandleMessage(AppSpawnClientExt * appProperty)445 static int HandleMessage(AppSpawnClientExt *appProperty)
446 {
447     // create pipe
448     if (pipe(appProperty->fd) == -1) {
449         APPSPAWN_LOGE("create pipe fail, errno = %{public}d", errno);
450         return -1;
451     }
452     fcntl(appProperty->fd[0], F_SETFL, O_NONBLOCK);
453     /* Clone support only one parameter, so need to package application parameters */
454     AppSandboxArg sandboxArg = { 0 };
455     sandboxArg.content = &g_appSpawnContent->content;
456     sandboxArg.client = &appProperty->client;
457     sandboxArg.client->cloneFlags = GetAppNamespaceFlags(appProperty->property.bundleName);
458 
459     SHOW_CLIENT("Receive client message ", appProperty);
460     int result = AppSpawnProcessMsg(&sandboxArg, &appProperty->pid);
461     if (result == 0) {  // wait child process result
462         result = WaitChild(appProperty->fd[0], appProperty->pid, appProperty);
463     }
464     close(appProperty->fd[0]);
465     close(appProperty->fd[1]);
466     APPSPAWN_LOGI("child process %{public}s %{public}s pid %{public}d",
467         appProperty->property.processName, (result == 0) ? "success" : "fail", appProperty->pid);
468     if (result == 0) {
469         AddAppInfo(appProperty->pid, appProperty->property.processName);
470         SendResponse(appProperty, (char *)&appProperty->pid, sizeof(appProperty->pid));
471     } else {
472         SendResponse(appProperty, (char *)&result, sizeof(result));
473     }
474     return 0;
475 }
476 
OnReceiveRequest(const TaskHandle taskHandle,const uint8_t * buffer,uint32_t buffLen)477 static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen)
478 {
479     AppSpawnClientExt *appProperty = (AppSpawnClientExt *)LE_GetUserData(taskHandle);
480     APPSPAWN_CHECK(appProperty != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
481         return, "alloc client Failed");
482 
483     if (!ReceiveRequestData(taskHandle, appProperty, buffer, buffLen)) {
484         return;
485     }
486 
487     if (g_appSpawnContent->content.isNweb) {
488         // get render process termination status, only nwebspawn need this logic.
489         if (appProperty->property.code == GET_RENDER_TERMINATION_STATUS) {
490             int ret = GetProcessTerminationStatus(&appProperty->client);
491             RemoveAppInfo(appProperty->property.pid);
492             SendResponse(appProperty, (char *)&ret, sizeof(ret));
493             return;
494         }
495     }
496     APPSPAWN_CHECK(appProperty->property.gidCount <= APP_MAX_GIDS && strlen(appProperty->property.processName) > 0,
497         LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
498         return, "Invalid property %{public}u", appProperty->property.gidCount);
499 
500     // special handle bundle name medialibrary and scanner
501     HandleSpecial(appProperty);
502     if (g_appSpawnContent->timer != NULL) {
503         LE_StopTimer(LE_GetDefaultLoop(), g_appSpawnContent->timer);
504         g_appSpawnContent->timer = NULL;
505     }
506     appProperty->pid = 0;
507     CheckColdAppEnabled(appProperty);
508     int ret = HandleMessage(appProperty);
509     if (ret != 0) {
510         LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
511     }
512 }
513 
AcceptClient(const LoopHandle loopHandle,const TaskHandle server,uint32_t flags)514 APPSPAWN_STATIC TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskHandle server, uint32_t flags)
515 {
516     static uint32_t clientId = 0;
517     TaskHandle stream;
518     LE_StreamInfo info = {};
519     info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
520     info.baseInfo.flags |= flags;
521     info.baseInfo.close = OnClose;
522     info.baseInfo.userDataSize = sizeof(AppSpawnClientExt);
523     info.disConnectComplete = NULL;
524     info.sendMessageComplete = SendMessageComplete;
525     info.recvMessage = OnReceiveRequest;
526 
527     LE_STATUS ret = LE_AcceptStreamClient(loopHandle, server, &stream, &info);
528     APPSPAWN_CHECK(ret == 0, return NULL, "Failed to alloc stream");
529     AppSpawnClientExt *client = (AppSpawnClientExt *)LE_GetUserData(stream);
530     APPSPAWN_CHECK(client != NULL, return NULL, "Failed to alloc stream");
531 #ifndef APPSPAWN_CHECK_GID_UID
532     struct ucred cred = {-1, -1, -1};
533     socklen_t credSize  = sizeof(struct ucred);
534     if ((getsockopt(LE_GetSocketFd(stream), SOL_SOCKET, SO_PEERCRED, &cred, &credSize) < 0) ||
535         (cred.uid != DecodeUid("foundation")  && cred.uid != DecodeUid("root"))) {
536         APPSPAWN_LOGE("Failed to check uid %{public}d", cred.uid);
537         LE_CloseStreamTask(LE_GetDefaultLoop(), stream);
538         return NULL;
539     }
540 #endif
541 
542     client->stream = stream;
543     client->client.id = ++clientId;
544     client->client.flags = 0;
545     client->property.hspList.totalLength = 0;
546     client->property.hspList.savedLength = 0;
547     client->property.hspList.data = NULL;
548     client->property.overlayInfo.totalLength = 0;
549     client->property.overlayInfo.data = NULL;
550     client->property.dataGroupInfoList.totalLength = 0;
551     client->property.dataGroupInfoList.data = NULL;
552     APPSPAWN_LOGI("OnConnection client fd %{public}d Id %{public}d", LE_GetSocketFd(stream), client->client.id);
553     return stream;
554 }
555 
OnConnection(const LoopHandle loopHandle,const TaskHandle server)556 static int OnConnection(const LoopHandle loopHandle, const TaskHandle server)
557 {
558     APPSPAWN_CHECK(server != NULL && loopHandle != NULL, return -1, "Error server");
559     (void)AcceptClient(loopHandle, server, 0);
560     return 0;
561 }
562 
NotifyResToParent(struct AppSpawnContent_ * content,AppSpawnClient * client,int result)563 static void NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result)
564 {
565     AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
566     int fd = appProperty->fd[1];
567     APPSPAWN_LOGI("NotifyResToParent %{public}s fd %{public}d result %{public}d",
568         appProperty->property.processName, fd, result);
569     write(appProperty->fd[1], &result, sizeof(result));
570     // close write
571     close(fd);
572 }
573 
AppSpawnInit(AppSpawnContent * content)574 static void AppSpawnInit(AppSpawnContent *content)
575 {
576     AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content;
577     APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content");
578 
579     APPSPAWN_LOGI("AppSpawnInit");
580     if (content->loadExtendLib) {
581         content->loadExtendLib(content);
582     }
583 
584     content->notifyResToParent = NotifyResToParent;
585     // set private function
586     SetContentFunction(content);
587 
588     // set uid gid filetr
589     if (content->setUidGidFilter) {
590         content->setUidGidFilter(content);
591     }
592 
593     // load app sandbox config
594     LoadAppSandboxConfig();
595 }
596 
AppSpawnColdRun(AppSpawnContent * content,int argc,char * const argv[])597 void AppSpawnColdRun(AppSpawnContent *content, int argc, char *const argv[])
598 {
599     AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content;
600     APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content");
601 
602     AppSpawnClientExt *client = (AppSpawnClientExt *)malloc(sizeof(AppSpawnClientExt));
603     APPSPAWN_CHECK(client != NULL, return, "Failed to alloc memory for client");
604     (void)memset_s(client, sizeof(AppSpawnClientExt), 0, sizeof(AppSpawnClientExt));
605     int ret = GetAppSpawnClientFromArg(argc, argv, client);
606     APPSPAWN_CHECK(ret == 0, free(client);
607         return, "Failed to get client from arg");
608     client->client.flags &= ~ APP_COLD_START;
609     SHOW_CLIENT("Cold running", client);
610     ret = DoStartApp(content, &client->client, content->longProcName, content->longProcNameLen);
611     if (ret == 0 && content->runChildProcessor != NULL) {
612         content->runChildProcessor(content, &client->client);
613     }
614 
615     APPSPAWN_LOGI("App exit %{public}d.", getpid());
616     free(client);
617     free(appSpawnContent);
618     g_appSpawnContent = NULL;
619 }
620 
AppSpawnRun(AppSpawnContent * content,int argc,char * const argv[])621 static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[])
622 {
623     APPSPAWN_LOGI("AppSpawnRun");
624     AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content;
625     APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content");
626 
627     LE_STATUS status;
628 
629     if (content->isNweb) {
630         status = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, SignalHandlerNweb);
631     } else {
632         status = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, SignalHandler);
633     }
634 
635     if (status == 0) {
636         (void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGCHLD);
637         (void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGTERM);
638     }
639 
640     LE_RunLoop(LE_GetDefaultLoop());
641     APPSPAWN_LOGI("AppSpawnRun exit ");
642     if (appSpawnContent->timer != NULL) {
643         LE_StopTimer(LE_GetDefaultLoop(), appSpawnContent->timer);
644         appSpawnContent->timer = NULL;
645     }
646     LE_CloseSignalTask(LE_GetDefaultLoop(), appSpawnContent->sigHandler);
647     // release resource
648     OH_HashMapDestory(appSpawnContent->appMap, NULL);
649     LE_CloseStreamTask(LE_GetDefaultLoop(), appSpawnContent->server);
650     LE_CloseLoop(LE_GetDefaultLoop());
651     free(content);
652     g_appSpawnContent = NULL;
653 }
654 
CreateHashForApp(AppSpawnContentExt * appSpawnContent)655 static int CreateHashForApp(AppSpawnContentExt *appSpawnContent)
656 {
657     HashInfo hashInfo = {
658         AppInfoHashNodeCompare,
659         TestHashKeyCompare,
660         AppInfoHashNodeFunction,
661         AppInfoHashKeyFunction,
662         AppInfoHashNodeFree,
663         APP_HASH_BUTT
664     };
665     int ret = OH_HashMapCreate(&appSpawnContent->appMap, &hashInfo);
666     APPSPAWN_CHECK(ret == 0, free(appSpawnContent); return -1, "Failed to create hash for app");
667     return 0;
668 }
669 
CreateAppSpawnServer(AppSpawnContentExt * appSpawnContent,const char * socketName)670 static int CreateAppSpawnServer(AppSpawnContentExt *appSpawnContent, const char *socketName)
671 {
672     char path[128] = {0};  // 128 max path
673     int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", SOCKET_DIR, socketName);
674     APPSPAWN_CHECK(ret >= 0, return -1, "Failed to snprintf_s %{public}d", ret);
675     int socketId = GetControlSocket(socketName);
676     APPSPAWN_LOGI("get socket form env %{public}s socketId %{public}d", socketName, socketId);
677     APPSPAWN_CHECK_ONLY_EXPER(socketId <= 0, appSpawnContent->flags |= FLAGS_ON_DEMAND);
678 
679     LE_StreamServerInfo info = {};
680     info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER;
681     info.socketId = socketId;
682     info.server = path;
683     info.baseInfo.close = NULL;
684     info.incommingConnect = OnConnection;
685 
686     ret = LE_CreateStreamServer(LE_GetDefaultLoop(), &appSpawnContent->server, &info);
687     APPSPAWN_CHECK(ret == 0, return -1, "Failed to create socket for %{public}s", path);
688     // create socket
689     ret = chmod(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
690     APPSPAWN_CHECK(ret == 0, return -1, "Failed to chmod %{public}s, err %{public}d. ", path, errno);
691 #ifndef APPSPAWN_CHECK_GID_UID
692     if (appSpawnContent->content.isNweb) {
693         ret = lchown(path, 3081, 3081); // 3081 is appspawn gid
694     } else {
695         ret = lchown(path, 0, 4000); // 4000 is appspawn gid
696     }
697     APPSPAWN_CHECK(ret == 0, return -1, "Failed to lchown %{public}s, err %{public}d. ", path, errno);
698 #endif
699     APPSPAWN_LOGI("CreateAppSpawnServer path %{public}s fd %{public}d",
700         path, LE_GetSocketFd(appSpawnContent->server));
701     return 0;
702 }
703 
AppSpawnCreateContent(const char * socketName,char * longProcName,uint32_t longProcNameLen,int mode)704 AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int mode)
705 {
706     APPSPAWN_CHECK(LE_GetDefaultLoop() != NULL, return NULL, "Invalid default loop");
707     APPSPAWN_CHECK(socketName != NULL && longProcName != NULL, return NULL, "Invalid name");
708     APPSPAWN_LOGI("AppSpawnCreateContent %{public}s %{public}u mode %{public}d", socketName, longProcNameLen, mode);
709 
710     AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)malloc(sizeof(AppSpawnContentExt));
711     APPSPAWN_CHECK(appSpawnContent != NULL, return NULL, "Failed to alloc memory for appspawn");
712     (void)memset_s(&appSpawnContent->content, sizeof(appSpawnContent->content), 0, sizeof(appSpawnContent->content));
713     appSpawnContent->content.longProcName = longProcName;
714     appSpawnContent->content.longProcNameLen = longProcNameLen;
715     if (strcmp(longProcName, NWEBSPAWN_SERVER_NAME) == 0) {
716         appSpawnContent->content.isNweb = true;
717     } else {
718         appSpawnContent->content.isNweb = false;
719     }
720     appSpawnContent->timer = NULL;
721     appSpawnContent->flags = 0;
722     appSpawnContent->server = NULL;
723     appSpawnContent->sigHandler = NULL;
724     appSpawnContent->content.initAppSpawn = AppSpawnInit;
725 
726     if (mode) {
727         appSpawnContent->flags |= FLAGS_MODE_COLD;
728         appSpawnContent->content.runAppSpawn = AppSpawnColdRun;
729     } else {
730         appSpawnContent->content.runAppSpawn = AppSpawnRun;
731 
732         // create hash for app
733         int ret = CreateHashForApp(appSpawnContent);
734         APPSPAWN_CHECK(ret == 0, free(appSpawnContent); return NULL, "Failed to create app");
735         ret = CreateAppSpawnServer(appSpawnContent, socketName);
736         APPSPAWN_CHECK(ret == 0, free(appSpawnContent); return NULL, "Failed to create server");
737     }
738     g_appSpawnContent = appSpawnContent;
739     return &g_appSpawnContent->content;
740 }
741