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