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