• 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 
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