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
19 #include <fcntl.h>
20 #include <inttypes.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/capability.h>
25 #include <sys/mount.h>
26 #include <sys/prctl.h>
27 #include <sys/signalfd.h>
28 #include <sys/syscall.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 #include <unistd.h>
32 #include <sched.h>
33
34 #include "securec.h"
35 #include "parameter.h"
36 #include "limits.h"
37 #include "string.h"
38 #include "init_param.h"
39 #define DEVICE_NULL_STR "/dev/null"
40
41 struct XpmRegionInfo {
42 uint64_t addr;
43 uint64_t length;
44 };
45
46 #define XPM_DEV_PATH "/dev/xpm"
47 #define XPM_REGION_LEN 0x10000000
48 #define SET_XPM_REGION _IOW('x', 0x01, struct XpmRegionInfo)
49
50 // ide-asan
SetAsanEnabledEnv(struct AppSpawnContent_ * content,AppSpawnClient * client)51 static int SetAsanEnabledEnv(struct AppSpawnContent_ *content, AppSpawnClient *client)
52 {
53 AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
54 char *bundleName = appProperty->bundleName;
55
56 if ((appProperty->flags & APP_ASANENABLED) != 0) {
57 char *devPath = "/dev/asanlog";
58 char logPath[PATH_MAX] = {0};
59 int ret = snprintf_s(logPath, sizeof(logPath), sizeof(logPath) - 1,
60 "/data/app/el1/100/base/%s/log", bundleName);
61 APPSPAWN_CHECK(ret > 0, return -1, "Invalid snprintf_s");
62 char asanOptions[PATH_MAX] = {0};
63 ret = snprintf_s(asanOptions, sizeof(asanOptions), sizeof(asanOptions) - 1,
64 "log_path=%s/asan.log:include=/system/etc/asan.options", devPath);
65 APPSPAWN_CHECK(ret > 0, return -1, "Invalid snprintf_s");
66
67 #if defined (__aarch64__) || defined (__x86_64__)
68 setenv("LD_PRELOAD", "/system/lib64/libclang_rt.asan.so", 1);
69 #else
70 setenv("LD_PRELOAD", "/system/lib/libclang_rt.asan.so", 1);
71 #endif
72 setenv("UBSAN_OPTIONS", asanOptions, 1);
73 client->flags |= APP_COLD_START;
74 }
75 return 0;
76 }
77
SetProcessName(struct AppSpawnContent_ * content,AppSpawnClient * client,char * longProcName,uint32_t longProcNameLen)78 static int SetProcessName(struct AppSpawnContent_ *content, AppSpawnClient *client,
79 char *longProcName, uint32_t longProcNameLen)
80 {
81 AppSpawnClientExt *appPropertyExt = (AppSpawnClientExt *)client;
82 AppParameter *appProperty = &appPropertyExt->property;
83 size_t len = strlen(appProperty->processName);
84 bool isRet = longProcName == NULL || len <= 0;
85 APPSPAWN_CHECK(!isRet, return -EINVAL, "process name is nullptr or length error");
86
87 char shortName[MAX_LEN_SHORT_NAME] = {0};
88 // process short name max length 16 bytes.
89 size_t copyLen = len;
90 const char *pos = appProperty->processName;
91 if (len >= MAX_LEN_SHORT_NAME) {
92 copyLen = MAX_LEN_SHORT_NAME - 1;
93 pos += (len - copyLen);
94 }
95 isRet = strncpy_s(shortName, MAX_LEN_SHORT_NAME, pos, copyLen) != EOK;
96 APPSPAWN_CHECK(!isRet, return -EINVAL, "strncpy_s short name error: %{public}d", errno);
97
98 // set short name
99 isRet = prctl(PR_SET_NAME, shortName) == -1;
100 APPSPAWN_CHECK(!isRet, return -errno, "prctl(PR_SET_NAME) error: %{public}d", errno);
101
102 // reset longProcName
103 isRet = memset_s(longProcName, (size_t)longProcNameLen, 0, (size_t)longProcNameLen) != EOK;
104 APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset long process name");
105
106 // set long process name
107 isRet = strncpy_s(longProcName, longProcNameLen, appProperty->processName, len) != EOK;
108 APPSPAWN_CHECK(!isRet, return -EINVAL,
109 "strncpy_s long name error: %{public}d longProcNameLen %{public}u", errno, longProcNameLen);
110
111 return 0;
112 }
113
SetKeepCapabilities(struct AppSpawnContent_ * content,AppSpawnClient * client)114 static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client)
115 {
116 AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
117 // set keep capabilities when user not root.
118 if (appProperty->property.uid != 0) {
119 bool isRet = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1;
120 APPSPAWN_CHECK(!isRet, return -errno, "set keepcaps failed: %{public}d", errno);
121 }
122 return 0;
123 }
124
SetCapabilities(struct AppSpawnContent_ * content,AppSpawnClient * client)125 static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client)
126 {
127 // init cap
128 struct __user_cap_header_struct cap_header;
129
130 bool isRet = memset_s(&cap_header, sizeof(cap_header), 0, sizeof(cap_header)) != EOK;
131 APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap header");
132
133 cap_header.version = _LINUX_CAPABILITY_VERSION_3;
134 cap_header.pid = 0;
135
136 struct __user_cap_data_struct cap_data[2];
137 isRet = memset_s(&cap_data, sizeof(cap_data), 0, sizeof(cap_data)) != EOK;
138 APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap data");
139
140 // init inheritable permitted effective zero
141 #ifdef GRAPHIC_PERMISSION_CHECK
142 const uint64_t inheriTable = 0;
143 const uint64_t permitted = 0;
144 const uint64_t effective = 0;
145 #else
146 const uint64_t inheriTable = 0x3fffffffff;
147 const uint64_t permitted = 0x3fffffffff;
148 const uint64_t effective = 0x3fffffffff;
149 #endif
150
151 cap_data[0].inheritable = (__u32)(inheriTable);
152 cap_data[1].inheritable = (__u32)(inheriTable >> BITLEN32);
153 cap_data[0].permitted = (__u32)(permitted);
154 cap_data[1].permitted = (__u32)(permitted >> BITLEN32);
155 cap_data[0].effective = (__u32)(effective);
156 cap_data[1].effective = (__u32)(effective >> BITLEN32);
157
158 // set capabilities
159 isRet = capset(&cap_header, &cap_data[0]) == -1;
160 APPSPAWN_CHECK(!isRet, return -errno, "capset failed: %{public}d", errno);
161 isRet = SetSelinuxCon(content, client) == -1;
162 APPSPAWN_CHECK(!isRet, return -EPERM, "Failed to set selinux context");
163 return 0;
164 }
165
InitDebugParams(struct AppSpawnContent_ * content,AppSpawnClient * client)166 static void InitDebugParams(struct AppSpawnContent_ *content, AppSpawnClient *client)
167 {
168 #ifndef APPSPAWN_TEST
169 AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
170 #if defined (__aarch64__) || defined (__x86_64__)
171 const char *debugSoPath = "/system/lib64/libhidebug.so";
172 #else
173 const char *debugSoPath = "/system/lib/libhidebug.so";
174 #endif
175 bool isRet = access(debugSoPath, F_OK) != 0;
176 APPSPAWN_CHECK(!isRet, return, "access failed, errno = %{public}d", errno);
177
178 void *handle = dlopen(debugSoPath, RTLD_LAZY);
179 APPSPAWN_CHECK(handle != NULL, return, "Failed to dlopen libhidebug.so, %{public}s", dlerror());
180
181 bool (*initParam)(const char *name);
182 initParam = (bool (*)(const char *name))dlsym(handle, "InitEnvironmentParam");
183 APPSPAWN_CHECK(initParam != NULL, dlclose(handle);
184 return, "Failed to dlsym InitEnvironmentParam, %{public}s", dlerror());
185 (*initParam)(appProperty->property.processName);
186 dlclose(handle);
187 #endif
188 }
189
ClearEnvironment(AppSpawnContent * content,AppSpawnClient * client)190 static void ClearEnvironment(AppSpawnContent *content, AppSpawnClient *client)
191 {
192 APPSPAWN_LOGI("ClearEnvironment id %{public}d", client->id);
193 sigset_t mask;
194 sigemptyset(&mask);
195 sigaddset(&mask, SIGCHLD);
196 sigaddset(&mask, SIGTERM);
197 sigprocmask(SIG_UNBLOCK, &mask, NULL);
198 // close child fd
199 AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
200 close(appProperty->fd[0]);
201 SetAsanEnabledEnv(content, client);
202
203 ResetParamSecurityLabel();
204 return;
205 }
206
SetXpmRegion(struct AppSpawnContent_ * content)207 int SetXpmRegion(struct AppSpawnContent_ *content)
208 {
209 struct XpmRegionInfo info = { 0, XPM_REGION_LEN };
210
211 // 32-bit system no xpm dev file
212 int fd = open(XPM_DEV_PATH, O_RDWR);
213 APPSPAWN_CHECK(fd != -1, return 0, "open xpm device file failed: %s", strerror(errno));
214
215 int ret = ioctl(fd, SET_XPM_REGION, &info);
216 APPSPAWN_CHECK_ONLY_LOG(ret != -1, "set xpm region failed: %s", strerror(errno));
217
218 close(fd);
219 return 0;
220 }
221
SetUidGid(struct AppSpawnContent_ * content,AppSpawnClient * client)222 static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client)
223 {
224 #ifdef GRAPHIC_PERMISSION_CHECK
225 AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
226 // set gids
227 bool isRet = setgroups(appProperty->property.gidCount, (const gid_t *)(&appProperty->property.gidTable[0])) == -1;
228 APPSPAWN_CHECK(!isRet, return -errno,
229 "setgroups failed: %{public}d, gids.size=%{public}u", errno, appProperty->property.gidCount);
230
231 if (client->cloneFlags & CLONE_NEWPID) {
232 /* setresuid and setresgid have multi-thread synchronous operations.
233 * after clone, the C library has not cleaned up the multi-thread information, so need to call syscall.
234 */
235 // set gid
236 long ret = syscall(SYS_setresgid, appProperty->property.gid,
237 appProperty->property.gid, appProperty->property.gid);
238 APPSPAWN_CHECK(ret == 0, return -errno,
239 "setgid(%{public}u) failed: %{public}d", appProperty->property.gid, errno);
240
241 if (content->setSeccompFilter) {
242 ret = content->setSeccompFilter(content, client);
243 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set setSeccompFilter");
244 }
245
246 /* If the effective user ID is changed from 0 to nonzero,
247 * then all capabilities are cleared from the effective set
248 */
249 ret = syscall(SYS_setresuid, appProperty->property.uid, appProperty->property.uid, appProperty->property.uid);
250 APPSPAWN_CHECK(ret == 0, return -errno,
251 "setuid(%{public}u) failed: %{public}d", appProperty->property.uid, errno);
252 } else {
253 // set gid
254 isRet = setresgid(appProperty->property.gid, appProperty->property.gid, appProperty->property.gid) == -1;
255 APPSPAWN_CHECK(!isRet, return -errno,
256 "setgid(%{public}u) failed: %{public}d", appProperty->property.gid, errno);
257
258 if (content->setSeccompFilter) {
259 long ret = content->setSeccompFilter(content, client);
260 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set setSeccompFilter");
261 }
262
263 /* If the effective user ID is changed from 0 to nonzero,
264 * then all capabilities are cleared from the effective set
265 */
266 isRet = setresuid(appProperty->property.uid, appProperty->property.uid, appProperty->property.uid) == -1;
267 APPSPAWN_CHECK(!isRet, return -errno,
268 "setuid(%{public}u) failed: %{public}d", appProperty->property.uid, errno);
269 }
270 #endif
271 if ((appProperty->property.flags & APP_DEBUGGABLE) != 0) {
272 APPSPAWN_LOGV("Debuggable app");
273 setenv("HAP_DEBUGGABLE", "true", 1);
274 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
275 APPSPAWN_LOGE("Failed to set app dumpable: %{public}s", strerror(errno));
276 }
277 }
278 return 0;
279 }
280
SetFileDescriptors(struct AppSpawnContent_ * content,AppSpawnClient * client)281 static int32_t SetFileDescriptors(struct AppSpawnContent_ *content, AppSpawnClient *client)
282 {
283 #ifndef APPSPAWN_TEST
284 // close stdin stdout stderr
285 close(STDIN_FILENO);
286 close(STDOUT_FILENO);
287 close(STDERR_FILENO);
288
289 // redirect to /dev/null
290 int dev_null_fd = open(DEVICE_NULL_STR, O_RDWR);
291 if (dev_null_fd == -1) {
292 APPSPAWN_LOGE("open dev_null error: %{public}d", errno);
293 return (-errno);
294 }
295
296 // stdin
297 if (dup2(dev_null_fd, STDIN_FILENO) == -1) {
298 APPSPAWN_LOGE("dup2 STDIN error: %{public}d", errno);
299 return (-errno);
300 };
301
302 // stdout
303 if (dup2(dev_null_fd, STDOUT_FILENO) == -1) {
304 APPSPAWN_LOGE("dup2 STDOUT error: %{public}d", errno);
305 return (-errno);
306 };
307
308 // stderr
309 if (dup2(dev_null_fd, STDERR_FILENO) == -1) {
310 APPSPAWN_LOGE("dup2 STDERR error: %{public}d", errno);
311 return (-errno);
312 };
313 #endif
314 return 0;
315 }
316
CheckTraceStatus(void)317 static int32_t CheckTraceStatus(void)
318 {
319 int fd = open("/proc/self/status", O_RDONLY);
320 if (fd == -1) {
321 APPSPAWN_LOGE("open /proc/self/status error: %{public}d", errno);
322 return (-errno);
323 }
324
325 char data[1024] = { 0 }; // 1024 is data length
326 ssize_t dataNum = read(fd, data, sizeof(data));
327 if (close(fd) < 0) {
328 APPSPAWN_LOGE("close fd error: %{public}d", errno);
329 return (-errno);
330 }
331
332 if (dataNum <= 0) {
333 APPSPAWN_LOGE("fail to read data");
334 return -1;
335 }
336 data[1023] = '\0'; // 1023 is data last element
337
338 const char* tracerPid = "TracerPid:\t";
339 char *traceStr = strstr(data, tracerPid);
340 if (traceStr == NULL) {
341 APPSPAWN_LOGE("fail to find %{public}s", tracerPid);
342 return -1;
343 }
344 char *separator = strchr(traceStr, '\n');
345 if (separator == NULL) {
346 APPSPAWN_LOGE("fail to find line break");
347 return -1;
348 }
349
350 int len = separator - traceStr - strlen(tracerPid);
351 char pid = *(traceStr + strlen(tracerPid));
352 if (len > 1 || pid != '0') {
353 return 0;
354 }
355 return -1;
356 }
357
WaitForDebugger(AppSpawnClient * client)358 static int32_t WaitForDebugger(AppSpawnClient *client)
359 {
360 AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
361
362 // wait for debugger only debugging is required and process is debuggable
363 if ((appProperty->property.flags & APP_NATIVEDEBUG) != 0 &&
364 (appProperty->property.flags & APP_DEBUGGABLE) != 0) {
365 uint32_t count = 0;
366 while (CheckTraceStatus() != 0) {
367 usleep(1000 * 100); // sleep 1000 * 100 microsecond
368 count++;
369 // remind users to connect to the debugger every 60 * 10 times
370 if (count % (10 * 60) == 0) {
371 count = 0;
372 APPSPAWN_LOGI("wait for debugger, please attach the process");
373 }
374 }
375 }
376 return 0;
377 }
378
Free(char ** argv,HspList * hspList,OverlayInfo * overlayInfo,DataGroupInfoList * dataGroupInfoList)379 static void Free(char **argv, HspList *hspList, OverlayInfo *overlayInfo, DataGroupInfoList *dataGroupInfoList)
380 {
381 argv[0] = NULL;
382 for (int i = 0; i < NULL_INDEX; i++) {
383 if (argv[i] != NULL) {
384 free(argv[i]);
385 argv[i] = NULL;
386 }
387 }
388 free(argv);
389
390 if (hspList != NULL) {
391 hspList->totalLength = 0;
392 hspList->savedLength = 0;
393 free(hspList->data);
394 hspList->data = NULL;
395 }
396
397 if (overlayInfo != NULL) {
398 overlayInfo->totalLength = 0;
399 free(overlayInfo->data);
400 overlayInfo->data = NULL;
401 }
402
403 if (dataGroupInfoList != NULL) {
404 dataGroupInfoList->totalLength = 0;
405 free(dataGroupInfoList->data);
406 dataGroupInfoList->data = NULL;
407 }
408 }
409
410 #ifdef ASAN_DETECTOR
411 #define WRAP_VALUE_MAX_LENGTH 96
GetWrapBundleNameValue(struct AppSpawnContent_ * content,AppSpawnClient * client)412 static int GetWrapBundleNameValue(struct AppSpawnContent_ *content, AppSpawnClient *client)
413 {
414 AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
415 char wrapBundleNameKey[WRAP_VALUE_MAX_LENGTH] = {0};
416 char wrapBundleNameValue[WRAP_VALUE_MAX_LENGTH] = {0};
417
418 int len = sprintf_s(wrapBundleNameKey, WRAP_VALUE_MAX_LENGTH, "wrap.%s", appProperty->bundleName);
419 APPSPAWN_CHECK(len > 0 && (len < WRAP_VALUE_MAX_LENGTH), return -1, "Invalid to format wrapBundleNameKey");
420
421 int ret = GetParameter(wrapBundleNameKey, "", wrapBundleNameValue, WRAP_VALUE_MAX_LENGTH);
422 APPSPAWN_CHECK(ret > 0 && (!strcmp(wrapBundleNameValue, "asan_wrapper")), return -1,
423 "Not wrap %{public}s.", appProperty->bundleName);
424 APPSPAWN_LOGI("Asan: GetParameter %{public}s the value is %{public}s.", wrapBundleNameKey, wrapBundleNameValue);
425 return 0;
426 }
427 #endif
428
EncodeAppClient(AppSpawnClient * client,char * param,int32_t originLen)429 static int EncodeAppClient(AppSpawnClient *client, char *param, int32_t originLen)
430 {
431 AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
432 int32_t startLen = 0;
433 int32_t len = sprintf_s(param + startLen, originLen - startLen, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u",
434 client->id, client->flags, client->cloneFlags, appProperty->code,
435 appProperty->flags, appProperty->uid, appProperty->gid,
436 appProperty->setAllowInternet, appProperty->allowInternet, appProperty->gidCount);
437 APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), return -1, "Invalid to format");
438 startLen += len;
439 for (uint32_t i = 0; i < appProperty->gidCount; i++) {
440 len = sprintf_s(param + startLen, originLen - startLen, ":%u", appProperty->gidTable[i]);
441 APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), return -1, "Invalid to format gid");
442 startLen += len;
443 }
444 // processName
445 if (appProperty->soPath[0] == '\0') {
446 strcpy_s(appProperty->soPath, sizeof(appProperty->soPath), "NULL");
447 }
448 len = sprintf_s(param + startLen, originLen - startLen, ":%s:%s:%s:%u:%s:%s:%u:%" PRIu64 "",
449 appProperty->processName, appProperty->bundleName, appProperty->soPath,
450 appProperty->accessTokenId, appProperty->apl, appProperty->renderCmd,
451 appProperty->hapFlags, appProperty->accessTokenIdEx);
452 APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), return -1, "Invalid to format processName");
453 return 0;
454 }
455
ColdStartApp(struct AppSpawnContent_ * content,AppSpawnClient * client)456 static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client)
457 {
458 AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
459 APPSPAWN_LOGI("ColdStartApp::appName %{public}s", appProperty->processName);
460 char buffer[32] = {0}; // 32 buffer for fd
461 int len = sprintf_s(buffer, sizeof(buffer), "%d", ((AppSpawnClientExt *)client)->fd[1]);
462 APPSPAWN_CHECK(len > 0, return -1, "Invalid to format fd");
463 char **argv = calloc(1, (NULL_INDEX + 1) * sizeof(char *));
464 APPSPAWN_CHECK(argv != NULL, return -1, "Failed to get argv");
465 int ret = -1;
466 do {
467 const int32_t originLen = sizeof(AppParameter) + PARAM_BUFFER_LEN;
468 char *param = malloc(originLen + APP_LEN_PROC_NAME);
469 APPSPAWN_CHECK(param != NULL, break, "Failed to malloc for param");
470 argv[PARAM_INDEX] = param;
471 argv[0] = param + originLen;
472 const char *appSpawnPath = "/system/bin/appspawn";
473 #ifdef ASAN_DETECTOR
474 if (GetWrapBundleNameValue(content, client) == 0) {
475 appSpawnPath = "/system/asan/bin/appspawn";
476 }
477 #endif
478 ret = strcpy_s(argv[0], APP_LEN_PROC_NAME, appSpawnPath);
479 APPSPAWN_CHECK(ret >= 0, break, "Invalid strcpy");
480 ret = -1;
481 argv[START_INDEX] = strdup("cold-start");
482 APPSPAWN_CHECK(argv[START_INDEX] != NULL, break, "Invalid strdup");
483 argv[FD_INDEX] = strdup(buffer);
484 APPSPAWN_CHECK(argv[FD_INDEX] != NULL, break, "Invalid strdup");
485 ret = EncodeAppClient(client, param, originLen);
486 APPSPAWN_CHECK(ret == 0, break, "Failed to encode client");
487
488 len = sprintf_s(buffer, sizeof(buffer), "%u", appProperty->hspList.totalLength);
489 APPSPAWN_CHECK(len > 0 && len < (int)sizeof(buffer), break, "Invalid hspList.totalLength");
490 argv[HSP_LIST_LEN_INDEX] = strdup(buffer);
491 argv[HSP_LIST_INDEX] = appProperty->hspList.data;
492
493 if (appProperty->hspList.totalLength == 0 && (appProperty->overlayInfo.totalLength > 0
494 || appProperty->dataGroupInfoList.totalLength > 0)) {
495 argv[HSP_LIST_INDEX] = strdup("0");
496 } else {
497 argv[HSP_LIST_INDEX] = appProperty->hspList.data;
498 }
499 len = sprintf_s(buffer, sizeof(buffer), "%u", appProperty->overlayInfo.totalLength);
500 APPSPAWN_CHECK(len > 0 && len < (int)sizeof(buffer), break, "Invalid overlayInfo.totalLength");
501 argv[OVERLAY_LEN_INDEX] = strdup(buffer);
502 argv[OVERLAY_INDEX] = appProperty->overlayInfo.data;
503
504 if (appProperty->overlayInfo.totalLength == 0 && appProperty->dataGroupInfoList.totalLength) {
505 argv[OVERLAY_INDEX] = strdup("0");
506 } else {
507 argv[OVERLAY_INDEX] = appProperty->overlayInfo.data;
508 }
509 len = sprintf_s(buffer, sizeof(buffer), "%u", appProperty->dataGroupInfoList.totalLength);
510 APPSPAWN_CHECK(len > 0 && len < (int)sizeof(buffer), break, "Invalid dataGroupInfoList.totalLength");
511 argv[DIR_LIST_LEN_INDEX] = strdup(buffer);
512 argv[DIR_LIST_INDEX] = appProperty->dataGroupInfoList.data;
513 ret = 0;
514 } while (0);
515
516 if (ret == 0) {
517 argv[NULL_INDEX] = NULL;
518 #ifndef APPSPAWN_TEST
519 ret = execv(argv[0], argv);
520 #else
521 ret = -1;
522 #endif
523 if (ret) {
524 APPSPAWN_LOGE("Failed to execv, errno = %{public}d", errno);
525 }
526 }
527 argv[0] = NULL;
528 Free(argv, &appProperty->hspList, &appProperty->overlayInfo, &appProperty->dataGroupInfoList);
529 return ret;
530 }
531
GetUInt32FromArg(char * begin,char ** end,uint32_t * value)532 static int GetUInt32FromArg(char *begin, char **end, uint32_t *value)
533 {
534 char *start = strtok_r(begin, ":", end);
535 APPSPAWN_CHECK(start != NULL, return -1, "Failed to get uint32 value");
536 *value = atoi(start);
537 return 0;
538 }
539
GetUInt64FromArg(char * begin,char ** end,uint64_t * value)540 static int GetUInt64FromArg(char *begin, char **end, uint64_t *value)
541 {
542 char *start = strtok_r(begin, ":", end);
543 APPSPAWN_CHECK(start != NULL, return -1, "Failed to get uint64 value");
544 APPSPAWN_LOGV("GetUInt64FromArg %{public}s ", start);
545 *value = atoll(start);
546 return 0;
547 }
548
GetStringFromArg(char * begin,char ** end,char * value,uint32_t valueLen)549 static int GetStringFromArg(char *begin, char **end, char *value, uint32_t valueLen)
550 {
551 char *start = strtok_r(NULL, ":", end);
552 APPSPAWN_CHECK(start != NULL, return -1, "Failed to get string");
553 if (strcmp(start, "NULL")) {
554 return strcpy_s(value, valueLen, start);
555 } else {
556 value[0] = '\0';
557 }
558 return 0;
559 }
560
GetOverlayInfoFromArg(int argc,char * const argv[],AppSpawnClientExt * client)561 static int GetOverlayInfoFromArg(int argc, char *const argv[], AppSpawnClientExt *client)
562 {
563 client->property.overlayInfo.totalLength = 0;
564 client->property.overlayInfo.data = NULL;
565 int ret = 0;
566 if (argc > OVERLAY_LEN_INDEX && argv[OVERLAY_LEN_INDEX] != NULL) {
567 client->property.overlayInfo.totalLength = atoi(argv[OVERLAY_LEN_INDEX]);
568 APPSPAWN_CHECK_ONLY_EXPER(client->property.overlayInfo.totalLength != 0, return 0);
569 APPSPAWN_CHECK(argc > OVERLAY_INDEX && argv[OVERLAY_INDEX] != NULL, return -1, "Invalid overlayInfo.data");
570 client->property.overlayInfo.data = malloc(client->property.overlayInfo.totalLength);
571 APPSPAWN_CHECK(client->property.overlayInfo.data != NULL, return -1, "Failed to malloc overlayInfo.data");
572 ret = strcpy_s(client->property.overlayInfo.data,
573 client->property.overlayInfo.totalLength,
574 argv[OVERLAY_INDEX]);
575 APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy overlayInfo.data");
576 }
577 return ret;
578 }
579
GetDataGroupListInfoFromArg(int argc,char * const argv[],AppSpawnClientExt * client)580 static int GetDataGroupListInfoFromArg(int argc, char *const argv[], AppSpawnClientExt *client)
581 {
582 client->property.dataGroupInfoList.totalLength = 0;
583 client->property.dataGroupInfoList.data = NULL;
584 int ret = 0;
585 if (argc > DIR_LIST_LEN_INDEX && argv[DIR_LIST_LEN_INDEX] != NULL) {
586 client->property.dataGroupInfoList.totalLength = atoi(argv[DIR_LIST_LEN_INDEX]);
587 APPSPAWN_CHECK_ONLY_EXPER(client->property.dataGroupInfoList.totalLength != 0, return 0);
588 APPSPAWN_CHECK(argc > DIR_LIST_INDEX && argv[DIR_LIST_INDEX] != NULL, return -1,
589 "Invalid dataGroupInfoList.data");
590 client->property.dataGroupInfoList.data = malloc(client->property.dataGroupInfoList.totalLength);
591 APPSPAWN_CHECK(client->property.dataGroupInfoList.data != NULL, return -1,
592 "Failed to malloc dataGroupInfoList.data");
593 ret = strcpy_s(client->property.dataGroupInfoList.data,
594 client->property.dataGroupInfoList.totalLength, argv[DIR_LIST_INDEX]);
595 APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy dataGroupInfoList.data");
596 }
597 return ret;
598 }
599
GetHspListInfoFromArg(int argc,char * const argv[],AppSpawnClientExt * client)600 static int GetHspListInfoFromArg(int argc, char *const argv[], AppSpawnClientExt *client)
601 {
602 client->property.hspList.totalLength = 0;
603 client->property.hspList.data = NULL;
604 int ret = 0;
605 if (argc > HSP_LIST_LEN_INDEX && argv[HSP_LIST_LEN_INDEX] != NULL) {
606 client->property.hspList.totalLength = atoi(argv[HSP_LIST_LEN_INDEX]);
607 APPSPAWN_CHECK_ONLY_EXPER(client->property.hspList.totalLength != 0, return 0);
608 APPSPAWN_CHECK(argc > HSP_LIST_INDEX && argv[HSP_LIST_INDEX] != NULL, return -1, "Invalid hspList.data");
609 client->property.hspList.data = malloc(client->property.hspList.totalLength);
610 APPSPAWN_CHECK(client->property.hspList.data != NULL, return -1, "Failed to malloc hspList.data");
611 ret = strcpy_s(client->property.hspList.data, client->property.hspList.totalLength, argv[HSP_LIST_INDEX]);
612 APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy hspList.data");
613 }
614 return ret;
615 }
616
GetAppSpawnClientFromArg(int argc,char * const argv[],AppSpawnClientExt * client)617 int GetAppSpawnClientFromArg(int argc, char *const argv[], AppSpawnClientExt *client)
618 {
619 APPSPAWN_CHECK(argv != NULL && argc > PARAM_INDEX, return -1, "Invalid argv argc %{public}d", argc);
620 client->fd[1] = atoi(argv[FD_INDEX]);
621 APPSPAWN_LOGV("GetAppSpawnClientFromArg %{public}s ", argv[PARAM_INDEX]);
622 // clientid
623 char *end = NULL;
624 int ret = GetUInt32FromArg(argv[PARAM_INDEX], &end, &client->client.id);
625 ret += GetUInt32FromArg(NULL, &end, &client->client.flags);
626 ret += GetUInt32FromArg(NULL, &end, &client->client.cloneFlags);
627 ret += GetUInt32FromArg(NULL, &end, &client->property.code);
628 ret += GetUInt32FromArg(NULL, &end, &client->property.flags);
629 ret += GetUInt32FromArg(NULL, &end, &client->property.uid);
630 ret += GetUInt32FromArg(NULL, &end, &client->property.gid);
631 uint32_t value = 0;
632 ret += GetUInt32FromArg(NULL, &end, &value);
633 client->property.setAllowInternet = (uint8_t)value;
634 ret += GetUInt32FromArg(NULL, &end, &value);
635 client->property.allowInternet = (uint8_t)value;
636 ret += GetUInt32FromArg(NULL, &end, &client->property.gidCount);
637 APPSPAWN_CHECK(ret == 0, return -1, "Failed to get client info");
638 for (uint32_t i = 0; i < client->property.gidCount; i++) {
639 ret = GetUInt32FromArg(NULL, &end, &client->property.gidTable[i]);
640 APPSPAWN_CHECK(ret == 0, return -1, "Failed to get gidTable");
641 }
642
643 // processname
644 ret = GetStringFromArg(NULL, &end, client->property.processName, sizeof(client->property.processName));
645 ret += GetStringFromArg(NULL, &end, client->property.bundleName, sizeof(client->property.bundleName));
646 ret += GetStringFromArg(NULL, &end, client->property.soPath, sizeof(client->property.soPath));
647 APPSPAWN_CHECK(ret == 0, return -1, "Failed to get process name");
648
649 // access token
650 ret = GetUInt32FromArg(NULL, &end, &client->property.accessTokenId);
651 ret += GetStringFromArg(NULL, &end, client->property.apl, sizeof(client->property.apl));
652 ret += GetStringFromArg(NULL, &end, client->property.renderCmd, sizeof(client->property.renderCmd));
653 ret += GetUInt32FromArg(NULL, &end, &value);
654 client->property.hapFlags = value;
655 ret += GetUInt64FromArg(NULL, &end, &client->property.accessTokenIdEx);
656 APPSPAWN_CHECK(ret == 0, return -1, "Failed to access token info");
657
658 ret = GetDataGroupListInfoFromArg(argc, argv, client);
659 APPSPAWN_CHECK(ret == 0, return -1, "Failed to get data group list info");
660
661 ret = GetOverlayInfoFromArg(argc, argv, client);
662 APPSPAWN_CHECK(ret == 0, return -1, "Failed to overlay info");
663
664 return GetHspListInfoFromArg(argc, argv, client);
665 }
666
SetContentFunction(AppSpawnContent * content)667 void SetContentFunction(AppSpawnContent *content)
668 {
669 APPSPAWN_LOGI("SetContentFunction");
670 content->clearEnvironment = ClearEnvironment;
671 content->initDebugParams = InitDebugParams;
672 content->setProcessName = SetProcessName;
673 content->setKeepCapabilities = SetKeepCapabilities;
674 content->setUidGid = SetUidGid;
675 content->setXpmRegion = SetXpmRegion;
676 content->setFileDescriptors = SetFileDescriptors;
677 content->coldStartApp = ColdStartApp;
678 content->setAsanEnabledEnv = SetAsanEnabledEnv;
679 #ifdef ASAN_DETECTOR
680 content->getWrapBundleNameValue = GetWrapBundleNameValue;
681 #endif
682 content->setAppSandbox = SetAppSandboxProperty;
683 content->setCapabilities = SetCapabilities;
684 content->setUidGidFilter = SetUidGidFilter;
685 content->setSeccompFilter = SetSeccompFilter;
686 content->setAppAccessToken = SetAppAccessToken;
687 content->handleInternetPermission = HandleInternetPermission;
688 content->waitForDebugger = WaitForDebugger;
689 }
690