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