• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "appspawn_service.h"
17 #include "appspawn_adapter.h"
18 #include "param_helper.h"
19 
20 #include <fcntl.h>
21 #include <inttypes.h>
22 #include <stdbool.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/capability.h>
26 #include <sys/mount.h>
27 #include <sys/prctl.h>
28 #include <sys/signalfd.h>
29 #include <sys/syscall.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33 #include <sched.h>
34 
35 #include "securec.h"
36 #include "parameter.h"
37 #include "limits.h"
38 #include "string.h"
39 #include "init_param.h"
40 #ifdef CODE_SIGNATURE_ENABLE
41 #include "code_sign_attr_utils.h"
42 #endif
43 
44 #define DEVICE_NULL_STR "/dev/null"
45 
46 // ide-asan
SetAsanEnabledEnv(struct AppSpawnContent_ * content,AppSpawnClient * client)47 static int SetAsanEnabledEnv(struct AppSpawnContent_ *content, AppSpawnClient *client)
48 {
49     if (content->isNweb) {
50         return 0;
51     }
52     AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
53     char *bundleName = appProperty->bundleName;
54 
55     if ((appProperty->flags & APP_ASANENABLED) != 0) {
56         char *devPath = "/dev/asanlog";
57         char logPath[PATH_MAX] = {0};
58         int ret = snprintf_s(logPath, sizeof(logPath), sizeof(logPath) - 1,
59                 "/data/app/el1/100/base/%s/log", bundleName);
60         APPSPAWN_CHECK(ret > 0, return -1, "Invalid snprintf_s");
61         char asanOptions[PATH_MAX] = {0};
62         ret = snprintf_s(asanOptions, sizeof(asanOptions), sizeof(asanOptions) - 1,
63                 "log_path=%s/asan.log:include=/system/etc/asan.options", devPath);
64         APPSPAWN_CHECK(ret > 0, return -1, "Invalid snprintf_s");
65 
66 #if defined (__aarch64__) || defined (__x86_64__)
67         setenv("LD_PRELOAD", "/system/lib64/libclang_rt.asan.so", 1);
68 #else
69         setenv("LD_PRELOAD", "/system/lib/libclang_rt.asan.so", 1);
70 #endif
71         unsetenv("UBSAN_OPTIONS");
72         setenv("ASAN_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 -ECANCELED, "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 
SetXpmConfig(struct AppSpawnContent_ * content,AppSpawnClient * client)207 int SetXpmConfig(struct AppSpawnContent_ *content, AppSpawnClient *client)
208 {
209 #ifdef CODE_SIGNATURE_ENABLE
210     // nwebspawn no permission set xpm config
211     if (content->isNweb) {
212         return 0;
213     }
214 
215     int ret = InitXpmRegion();
216     APPSPAWN_CHECK(ret == 0, return ret, "init xpm region failed: %{public}d", ret);
217 
218     AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
219     if (appProperty->property.flags & APP_DEBUGGABLE) {
220         ret = SetXpmOwnerId(PROCESS_OWNERID_DEBUG, NULL);
221     } else if ((appProperty->property.ownerId[0] == '\0') ||
222         (strcmp(appProperty->property.ownerId, "NULL") == 0)) {
223         ret = SetXpmOwnerId(PROCESS_OWNERID_COMPAT, NULL);
224     } else {
225         ret = SetXpmOwnerId(PROCESS_OWNERID_APP, appProperty->property.ownerId);
226     }
227     APPSPAWN_CHECK(ret == 0, return ret, "set xpm region failed: %{public}d", ret);
228 #endif
229 
230     return 0;
231 }
232 
SetUidGid(struct AppSpawnContent_ * content,AppSpawnClient * client)233 static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client)
234 {
235 #ifdef GRAPHIC_PERMISSION_CHECK
236     AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
237     // set gids
238     bool isRet = setgroups(appProperty->property.gidCount, (const gid_t *)(&appProperty->property.gidTable[0])) == -1;
239     APPSPAWN_CHECK(!isRet, return -errno,
240         "setgroups failed: %{public}d, gids.size=%{public}u", errno, appProperty->property.gidCount);
241 
242     // set gid
243     isRet = setresgid(appProperty->property.gid, appProperty->property.gid, appProperty->property.gid) == -1;
244     APPSPAWN_CHECK(!isRet, return -errno,
245         "setgid(%{public}u) failed: %{public}d", appProperty->property.gid, errno);
246 
247     if (content->setSeccompFilter) {
248         long ret = content->setSeccompFilter(content, client);
249         APPSPAWN_CHECK(ret == 0, return ret, "Failed to set setSeccompFilter");
250     }
251 
252     /* If the effective user ID is changed from 0 to nonzero,
253      * then all capabilities are cleared from the effective set
254      */
255     isRet = setresuid(appProperty->property.uid, appProperty->property.uid, appProperty->property.uid) == -1;
256     APPSPAWN_CHECK(!isRet, return -errno,
257             "setuid(%{public}u) failed: %{public}d", appProperty->property.uid, errno);
258 #endif
259     if ((appProperty->property.flags & APP_DEBUGGABLE) != 0) {
260         APPSPAWN_LOGV("Debuggable app");
261         setenv("HAP_DEBUGGABLE", "true", 1);
262         if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
263             APPSPAWN_LOGE("Failed to set app dumpable: %{public}s", strerror(errno));
264         }
265     }
266     return 0;
267 }
268 
SetFileDescriptors(struct AppSpawnContent_ * content,AppSpawnClient * client)269 static int32_t SetFileDescriptors(struct AppSpawnContent_ *content, AppSpawnClient *client)
270 {
271 #ifndef APPSPAWN_TEST
272     // close stdin stdout stderr
273     close(STDIN_FILENO);
274     close(STDOUT_FILENO);
275     close(STDERR_FILENO);
276 
277     // redirect to /dev/null
278     int dev_null_fd = open(DEVICE_NULL_STR, O_RDWR);
279     if (dev_null_fd == -1) {
280         APPSPAWN_LOGE("open dev_null error: %{public}d", errno);
281         return (-errno);
282     }
283 
284     // stdin
285     if (dup2(dev_null_fd, STDIN_FILENO) == -1) {
286         APPSPAWN_LOGE("dup2 STDIN error: %{public}d", errno);
287         return (-errno);
288     };
289 
290     // stdout
291     if (dup2(dev_null_fd, STDOUT_FILENO) == -1) {
292         APPSPAWN_LOGE("dup2 STDOUT error: %{public}d", errno);
293         return (-errno);
294     };
295 
296     // stderr
297     if (dup2(dev_null_fd, STDERR_FILENO) == -1) {
298         APPSPAWN_LOGE("dup2 STDERR error: %{public}d", errno);
299         return (-errno);
300     };
301 #endif
302     return 0;
303 }
304 
CheckTraceStatus(void)305 static int32_t CheckTraceStatus(void)
306 {
307     int fd = open("/proc/self/status", O_RDONLY);
308     if (fd == -1) {
309         APPSPAWN_LOGE("open /proc/self/status error: %{public}d", errno);
310         return (-errno);
311     }
312 
313     char data[1024] = { 0 }; // 1024 is data length
314     ssize_t dataNum = read(fd, data, sizeof(data));
315     if (close(fd) < 0) {
316         APPSPAWN_LOGE("close fd error: %{public}d", errno);
317         return (-errno);
318     }
319 
320     if (dataNum <= 0) {
321         APPSPAWN_LOGE("fail to read data");
322         return -1;
323     }
324     data[1023] = '\0'; // 1023 is data last element
325 
326     const char* tracerPid = "TracerPid:\t";
327     char *traceStr = strstr(data, tracerPid);
328     if (traceStr == NULL) {
329         APPSPAWN_LOGE("fail to find %{public}s", tracerPid);
330         return -1;
331     }
332     char *separator = strchr(traceStr, '\n');
333     if (separator == NULL) {
334         APPSPAWN_LOGE("fail to find line break");
335         return -1;
336     }
337 
338     int len = separator - traceStr - strlen(tracerPid);
339     char pid = *(traceStr + strlen(tracerPid));
340     if (len > 1 || pid != '0') {
341         return 0;
342     }
343     return -1;
344 }
345 
WaitForDebugger(AppSpawnClient * client)346 static int32_t WaitForDebugger(AppSpawnClient *client)
347 {
348     AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
349 
350     // wait for debugger only debugging is required and process is debuggable
351     if ((appProperty->property.flags & APP_NATIVEDEBUG) != 0 &&
352         (appProperty->property.flags & APP_DEBUGGABLE) != 0) {
353         uint32_t count = 0;
354         while (CheckTraceStatus() != 0) {
355             usleep(1000 * 100); // sleep 1000 * 100 microsecond
356             count++;
357             // remind users to connect to the debugger every 60 * 10 times
358             if (count % (10 * 60) == 0) {
359                 count = 0;
360                 APPSPAWN_LOGI("wait for debugger, please attach the process");
361             }
362         }
363     }
364     return 0;
365 }
366 
Free(char ** argv,ExtraInfo * extraInfo)367 static void Free(char **argv, ExtraInfo *extraInfo)
368 {
369     argv[0] = NULL;
370     for (int i = 0; i < NULL_INDEX; i++) {
371         if (argv[i] != NULL) {
372             free(argv[i]);
373             argv[i] = NULL;
374         }
375     }
376     free(argv);
377 
378     if (extraInfo != NULL) {
379         extraInfo->totalLength = 0;
380         extraInfo->savedLength = 0;
381         free(extraInfo->data);
382         extraInfo->data = NULL;
383     }
384 }
385 
386 #ifdef ASAN_DETECTOR
387 #define WRAP_VALUE_MAX_LENGTH 96
GetWrapBundleNameValue(struct AppSpawnContent_ * content,AppSpawnClient * client)388 static int GetWrapBundleNameValue(struct AppSpawnContent_ *content, AppSpawnClient *client)
389 {
390     AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
391     char wrapBundleNameKey[WRAP_VALUE_MAX_LENGTH] = {0};
392     char wrapBundleNameValue[WRAP_VALUE_MAX_LENGTH] = {0};
393 
394     int len = sprintf_s(wrapBundleNameKey, WRAP_VALUE_MAX_LENGTH, "wrap.%s", appProperty->bundleName);
395     APPSPAWN_CHECK(len > 0 && (len < WRAP_VALUE_MAX_LENGTH), return -1, "Invalid to format wrapBundleNameKey");
396 
397     int ret = GetParameter(wrapBundleNameKey, "", wrapBundleNameValue, WRAP_VALUE_MAX_LENGTH);
398     APPSPAWN_CHECK(ret > 0 && (!strcmp(wrapBundleNameValue, "asan_wrapper")), return -1,
399                    "Not wrap %{public}s.", appProperty->bundleName);
400     APPSPAWN_LOGI("Asan: GetParameter %{public}s the value is %{public}s.", wrapBundleNameKey, wrapBundleNameValue);
401     return 0;
402 }
403 #endif
404 
EncodeAppClient(AppSpawnClient * client,char * param,int32_t originLen)405 static int EncodeAppClient(AppSpawnClient *client, char *param, int32_t originLen)
406 {
407     AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
408     int32_t startLen = 0;
409     int32_t len = sprintf_s(param + startLen, originLen - startLen, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u",
410         client->id, client->flags, client->cloneFlags, appProperty->code,
411         appProperty->flags, appProperty->uid, appProperty->gid,
412         appProperty->setAllowInternet, appProperty->allowInternet, appProperty->gidCount);
413     APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), return -1, "Invalid to format");
414     startLen += len;
415     for (uint32_t i = 0; i < appProperty->gidCount; i++) {
416         len = sprintf_s(param + startLen, originLen - startLen, ":%u", appProperty->gidTable[i]);
417         APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), return -1, "Invalid to format gid");
418         startLen += len;
419     }
420     // processName
421     if (appProperty->soPath[0] == '\0') {
422         strcpy_s(appProperty->soPath, sizeof(appProperty->soPath), "NULL");
423     }
424     // ownerId
425     if (appProperty->ownerId[0] == '\0') {
426         strcpy_s(appProperty->ownerId, sizeof(appProperty->ownerId), "NULL");
427     }
428     len = sprintf_s(param + startLen, originLen - startLen, ":%s:%s:%s:%u:%s:%s:%s:%u:%" PRIu64 "",
429         appProperty->processName, appProperty->bundleName, appProperty->soPath,
430         appProperty->accessTokenId, appProperty->apl, appProperty->renderCmd, appProperty->ownerId,
431         appProperty->hapFlags, appProperty->accessTokenIdEx);
432     APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), return -1, "Invalid to format processName");
433     return 0;
434 }
435 
ColdStartApp(struct AppSpawnContent_ * content,AppSpawnClient * client)436 static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client)
437 {
438     AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
439     APPSPAWN_LOGI("ColdStartApp::appName %{public}s", appProperty->processName);
440     char buffer[32] = {0};  // 32 buffer for fd
441     int len = sprintf_s(buffer, sizeof(buffer), "%d", ((AppSpawnClientExt *)client)->fd[1]);
442     APPSPAWN_CHECK(len > 0, return -1, "Invalid to format fd");
443     char **argv = calloc(1, (NULL_INDEX + 1) * sizeof(char *));
444     APPSPAWN_CHECK(argv != NULL, return -1, "Failed to get argv");
445     int ret = -1;
446     do {
447         const int32_t originLen = sizeof(AppParameter) + PARAM_BUFFER_LEN;
448         char *param = malloc(originLen + APP_LEN_PROC_NAME);
449         APPSPAWN_CHECK(param != NULL, break, "Failed to malloc for param");
450         argv[PARAM_INDEX] = param;
451         argv[0] = param + originLen;
452         const char *appSpawnPath = "/system/bin/appspawn";
453 #ifdef ASAN_DETECTOR
454         if (GetWrapBundleNameValue(content, client) == 0) {
455             appSpawnPath = "/system/asan/bin/appspawn";
456         }
457 #endif
458         ret = strcpy_s(argv[0], APP_LEN_PROC_NAME, appSpawnPath);
459         APPSPAWN_CHECK(ret >= 0, break, "Invalid strcpy");
460         ret = -1;
461         argv[START_INDEX] = strdup("cold-start");
462         APPSPAWN_CHECK(argv[START_INDEX] != NULL, break, "Invalid strdup");
463         argv[FD_INDEX] = strdup(buffer);
464         APPSPAWN_CHECK(argv[FD_INDEX] != NULL, break, "Invalid strdup");
465         ret = EncodeAppClient(client, param, originLen);
466         APPSPAWN_CHECK(ret == 0, break, "Failed to encode client");
467 
468         len = sprintf_s(buffer, sizeof(buffer), "%u", appProperty->extraInfo.totalLength);
469         APPSPAWN_CHECK(len > 0 && len < (int)sizeof(buffer), break, "Invalid extraInfo.totalLength");
470         argv[EXTRA_INFO_LEN_INDEX] = strdup(buffer);
471         argv[EXTRA_INFO_INDEX] = appProperty->extraInfo.data;
472         ret = 0;
473     } while (0);
474 
475     if (ret == 0) {
476         argv[NULL_INDEX] = NULL;
477 #ifndef APPSPAWN_TEST
478         ret = execv(argv[0], argv);
479 #else
480         ret = -1;
481 #endif
482         if (ret) {
483             APPSPAWN_LOGE("Failed to execv, errno = %{public}d", errno);
484         }
485     }
486     argv[0] = NULL;
487     Free(argv, &appProperty->extraInfo);
488     return ret;
489 }
490 
GetUInt32FromArg(char * begin,char ** end,uint32_t * value)491 static int GetUInt32FromArg(char *begin, char **end, uint32_t *value)
492 {
493     char *start = strtok_r(begin, ":", end);
494     APPSPAWN_CHECK(start != NULL, return -1, "Failed to get uint32 value");
495     *value = atoi(start);
496     return 0;
497 }
498 
GetUInt64FromArg(char * begin,char ** end,uint64_t * value)499 static int GetUInt64FromArg(char *begin, char **end, uint64_t *value)
500 {
501     char *start = strtok_r(begin, ":", end);
502     APPSPAWN_CHECK(start != NULL, return -1, "Failed to get uint64 value");
503     APPSPAWN_LOGV("GetUInt64FromArg %{public}s ", start);
504     *value = atoll(start);
505     return 0;
506 }
507 
GetStringFromArg(char * begin,char ** end,char * value,uint32_t valueLen)508 static int GetStringFromArg(char *begin, char **end, char *value, uint32_t valueLen)
509 {
510     char *start = strtok_r(NULL, ":", end);
511     APPSPAWN_CHECK(start != NULL, return -1, "Failed to get string");
512     if (strcmp(start, "NULL")) {
513         return strcpy_s(value, valueLen, start);
514     } else {
515         value[0] = '\0';
516     }
517     return 0;
518 }
519 
GetAppSpawnClientFromArg(int argc,char * const argv[],AppSpawnClientExt * client)520 int GetAppSpawnClientFromArg(int argc, char *const argv[], AppSpawnClientExt *client)
521 {
522     APPSPAWN_CHECK(argv != NULL && argc > PARAM_INDEX, return -1, "Invalid argv argc %{public}d", argc);
523     client->fd[1] = atoi(argv[FD_INDEX]);
524     APPSPAWN_LOGV("GetAppSpawnClientFromArg %{public}s ", argv[PARAM_INDEX]);
525     // clientid
526     char *end = NULL;
527     int ret = GetUInt32FromArg(argv[PARAM_INDEX], &end, &client->client.id);
528     ret += GetUInt32FromArg(NULL, &end, &client->client.flags);
529     ret += GetUInt32FromArg(NULL, &end, &client->client.cloneFlags);
530     ret += GetUInt32FromArg(NULL, &end, &client->property.code);
531     ret += GetUInt32FromArg(NULL, &end, &client->property.flags);
532     ret += GetUInt32FromArg(NULL, &end, &client->property.uid);
533     ret += GetUInt32FromArg(NULL, &end, &client->property.gid);
534     uint32_t value = 0;
535     ret += GetUInt32FromArg(NULL, &end, &value);
536     client->property.setAllowInternet = (uint8_t)value;
537     ret += GetUInt32FromArg(NULL, &end, &value);
538     client->property.allowInternet = (uint8_t)value;
539     ret += GetUInt32FromArg(NULL, &end, &client->property.gidCount);
540     APPSPAWN_CHECK(ret == 0, return -1, "Failed to get client info");
541     for (uint32_t i = 0; i < client->property.gidCount; i++) {
542         ret = GetUInt32FromArg(NULL, &end, &client->property.gidTable[i]);
543         APPSPAWN_CHECK(ret == 0, return -1, "Failed to get gidTable");
544     }
545 
546     // processname
547     ret = GetStringFromArg(NULL, &end, client->property.processName, sizeof(client->property.processName));
548     ret += GetStringFromArg(NULL, &end, client->property.bundleName, sizeof(client->property.bundleName));
549     ret += GetStringFromArg(NULL, &end, client->property.soPath, sizeof(client->property.soPath));
550     APPSPAWN_CHECK(ret == 0, return -1, "Failed to get process name");
551 
552     // access token
553     ret = GetUInt32FromArg(NULL, &end, &client->property.accessTokenId);
554     ret += GetStringFromArg(NULL, &end, client->property.apl, sizeof(client->property.apl));
555     ret += GetStringFromArg(NULL, &end, client->property.renderCmd, sizeof(client->property.renderCmd));
556     ret += GetStringFromArg(NULL, &end, client->property.ownerId, sizeof(client->property.ownerId));
557     ret += GetUInt32FromArg(NULL, &end, &value);
558     client->property.hapFlags = value;
559     ret += GetUInt64FromArg(NULL, &end, &client->property.accessTokenIdEx);
560     APPSPAWN_CHECK(ret == 0, return -1, "Failed to access token info");
561 
562     client->property.extraInfo.totalLength = 0;
563     client->property.extraInfo.data = NULL;
564     ret = 0;
565     if (argc > EXTRA_INFO_LEN_INDEX && argv[EXTRA_INFO_LEN_INDEX] != NULL) {
566         client->property.extraInfo.totalLength = atoi(argv[EXTRA_INFO_LEN_INDEX]);
567         APPSPAWN_CHECK_ONLY_EXPER(client->property.extraInfo.totalLength != 0, return 0);
568         APPSPAWN_CHECK(argc > EXTRA_INFO_INDEX && argv[EXTRA_INFO_INDEX] != NULL, return -1, "Invalid extraInfo.data");
569         client->property.extraInfo.data = malloc(client->property.extraInfo.totalLength);
570         APPSPAWN_CHECK(client->property.extraInfo.data != NULL, return -1, "Failed to malloc extraInfo.data");
571         ret = strcpy_s(client->property.extraInfo.data, client->property.extraInfo.totalLength, argv[EXTRA_INFO_INDEX]);
572         APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy extraInfo.data");
573     }
574     return ret;
575 }
576 
EnablePidNs(AppSpawnContent * content)577 static int EnablePidNs(AppSpawnContent *content)
578 {
579     AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content;
580     if (appSpawnContent->flags & FLAGS_MODE_COLD) {
581         return 0;
582     }
583 
584     if (!(content->sandboxNsFlags & CLONE_NEWPID)) {
585         return 0;
586     }
587 
588     int ret = unshare(CLONE_NEWPID);
589     APPSPAWN_CHECK(ret == 0, return -1, "unshare CLONE_NWEPID failed, errno=%{public}d", errno);
590 
591     APPSPAWN_LOGI("Enable pid namespace success.");
592     return 0;
593 }
594 
SetContentFunction(AppSpawnContent * content)595 void SetContentFunction(AppSpawnContent *content)
596 {
597     APPSPAWN_LOGI("SetContentFunction");
598     content->clearEnvironment = ClearEnvironment;
599     content->initDebugParams = InitDebugParams;
600     content->setProcessName = SetProcessName;
601     content->setKeepCapabilities = SetKeepCapabilities;
602     content->setUidGid = SetUidGid;
603     content->setXpmConfig = SetXpmConfig;
604     content->setFileDescriptors = SetFileDescriptors;
605     content->coldStartApp = ColdStartApp;
606     content->setAsanEnabledEnv = SetAsanEnabledEnv;
607     if (content->isNweb) {
608         content->getWrapBundleNameValue = NULL;
609     } else {
610 #ifdef ASAN_DETECTOR
611         content->getWrapBundleNameValue = GetWrapBundleNameValue;
612 #endif
613         content->enablePidNs = EnablePidNs;
614     }
615     content->setAppSandbox = SetAppSandboxProperty;
616     content->setCapabilities = SetCapabilities;
617     content->setUidGidFilter = SetUidGidFilter;
618     content->setSeccompFilter = SetSeccompFilter;
619     content->setAppAccessToken = SetAppAccessToken;
620     content->handleInternetPermission = HandleInternetPermission;
621     content->waitForDebugger = WaitForDebugger;
622 }
623