1 /*
2 * Copyright (c) 2024 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 #include <fcntl.h>
16 #include <grp.h>
17 #include <inttypes.h>
18 #include <limits.h>
19 #include <sys/capability.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/ioctl.h>
25 #include <sys/mount.h>
26 #include <sys/prctl.h>
27 #include <sys/signalfd.h>
28 #include <sys/stat.h>
29 #include <sys/syscall.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33
34 #undef _GNU_SOURCE
35 #define _GNU_SOURCE
36 #include <dlfcn.h>
37 #include <malloc.h>
38 #include <sched.h>
39
40 #include "appspawn_adapter.h"
41 #include "appspawn_hook.h"
42 #include "appspawn_service.h"
43 #include "appspawn_msg.h"
44 #include "appspawn_manager.h"
45 #include "appspawn_silk.h"
46 #include "init_param.h"
47 #include "parameter.h"
48 #include "securec.h"
49
50 #ifdef CODE_SIGNATURE_ENABLE // for xpm
51 #include "code_sign_attr_utils.h"
52 #endif
53 #ifdef SECURITY_COMPONENT_ENABLE
54 #include "sec_comp_enhance_kit_c.h"
55 #endif
56 #ifdef WITH_SELINUX
57 #include "selinux/selinux.h"
58 #endif
59
60 #define PROVISION_TYPE_DEBUG "debug"
61 #define DEVICE_NULL_STR "/dev/null"
62 #define PROCESS_START_TIME_ENV "PROCESS_START_TIME"
63 #define BITLEN32 32
64 #define PID_NS_INIT_UID 100000 // reserved for pid_ns_init process, avoid app, render proc, etc.
65 #define PID_NS_INIT_GID 100000
66
SetProcessName(const AppSpawnMgr * content,const AppSpawningCtx * property)67 static int SetProcessName(const AppSpawnMgr *content, const AppSpawningCtx *property)
68 {
69 const char *processName = GetProcessName(property);
70 APPSPAWN_CHECK(processName != NULL, return -EINVAL, "Can not get process name");
71 // 解析时已经检查
72 size_t len = strlen(processName);
73 char shortName[MAX_LEN_SHORT_NAME] = {0};
74 // process short name max length 16 bytes.
75 size_t copyLen = len;
76 const char *pos = processName;
77 if (len >= MAX_LEN_SHORT_NAME) {
78 copyLen = MAX_LEN_SHORT_NAME - 1;
79 pos += (len - copyLen);
80 }
81 bool isRet = strncpy_s(shortName, MAX_LEN_SHORT_NAME, pos, copyLen) != EOK;
82 APPSPAWN_CHECK(!isRet, return EINVAL, "strncpy_s short name error: %{public}d", errno);
83
84 // set short name
85 isRet = prctl(PR_SET_NAME, shortName) == -1;
86 APPSPAWN_CHECK(!isRet, return errno, "prctl(PR_SET_NAME) error: %{public}d", errno);
87
88 // reset longProcName
89 isRet = memset_s(content->content.longProcName,
90 (size_t)content->content.longProcNameLen, 0, (size_t)content->content.longProcNameLen) != EOK;
91 APPSPAWN_CHECK(!isRet, return EINVAL, "Failed to memset long process name");
92
93 // set long process name
94 isRet = strncpy_s(content->content.longProcName, content->content.longProcNameLen, processName, len) != EOK;
95 APPSPAWN_CHECK(!isRet, return EINVAL,
96 "strncpy_s long name error: %{public}d longProcNameLen %{public}u", errno, content->content.longProcNameLen);
97 return 0;
98 }
99
SetKeepCapabilities(const AppSpawnMgr * content,const AppSpawningCtx * property)100 static int SetKeepCapabilities(const AppSpawnMgr *content, const AppSpawningCtx *property)
101 {
102 AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO);
103 APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE,
104 "No tlv %{public}d in msg %{public}s", TLV_DOMAIN_INFO, GetProcessName(property));
105
106 // set keep capabilities when user not root.
107 if (dacInfo->uid != 0) {
108 bool isRet = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1;
109 APPSPAWN_CHECK(!isRet, return errno, "set keepcaps failed: %{public}d", errno);
110 }
111 return 0;
112 }
113
SetCapabilities(const AppSpawnMgr * content,const AppSpawningCtx * property)114 static int SetCapabilities(const AppSpawnMgr *content, const AppSpawningCtx *property)
115 {
116 // init cap
117 struct __user_cap_header_struct capHeader;
118
119 bool isRet = memset_s(&capHeader, sizeof(capHeader), 0, sizeof(capHeader)) != EOK;
120 APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap header");
121
122 capHeader.version = _LINUX_CAPABILITY_VERSION_3;
123 capHeader.pid = 0;
124
125 struct __user_cap_data_struct capData[2]; // 2 is data number
126 isRet = memset_s(&capData, sizeof(capData), 0, sizeof(capData)) != EOK;
127 APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap data");
128
129 // init inheritable permitted effective zero
130 #ifdef GRAPHIC_PERMISSION_CHECK
131 const uint64_t inheriTable = 0;
132 const uint64_t permitted = 0;
133 const uint64_t effective = 0;
134 #else
135 const uint64_t inheriTable = 0x3fffffffff;
136 const uint64_t permitted = 0x3fffffffff;
137 const uint64_t effective = 0x3fffffffff;
138 #endif
139
140 capData[0].inheritable = (__u32)(inheriTable);
141 capData[1].inheritable = (__u32)(inheriTable >> BITLEN32);
142 capData[0].permitted = (__u32)(permitted);
143 capData[1].permitted = (__u32)(permitted >> BITLEN32);
144 capData[0].effective = (__u32)(effective);
145 capData[1].effective = (__u32)(effective >> BITLEN32);
146
147 // set capabilities
148 isRet = capset(&capHeader, &capData[0]) != 0;
149 APPSPAWN_CHECK(!isRet, return -errno, "Failed to capset errno: %{public}d", errno);
150 return 0;
151 }
152
InitDebugParams(const AppSpawnMgr * content,const AppSpawningCtx * property)153 static void InitDebugParams(const AppSpawnMgr *content, const AppSpawningCtx *property)
154 {
155 #if defined(__aarch64__) || defined(__x86_64__)
156 const char *debugSoPath = "/system/lib64/libhidebug.so";
157 #else
158 const char *debugSoPath = "/system/lib/libhidebug.so";
159 #endif
160 const char *processName = GetProcessName(property);
161 APPSPAWN_CHECK(processName != NULL, return, "Can not get process name");
162
163 bool isRet = access(debugSoPath, F_OK) != 0;
164 APPSPAWN_CHECK(!isRet, return,
165 "access failed, errno: %{public}d debugSoPath: %{public}s", errno, debugSoPath);
166
167 void *handle = dlopen(debugSoPath, RTLD_LAZY);
168 APPSPAWN_CHECK(handle != NULL, return, "Failed to dlopen libhidebug.so errno: %{public}s", dlerror());
169
170 bool (*initParam)(const char *name);
171 initParam = (bool (*)(const char *name))dlsym(handle, "InitEnvironmentParam");
172 APPSPAWN_CHECK(initParam != NULL, dlclose(handle);
173 return, "Failed to dlsym errno: %{public}s", dlerror());
174 (*initParam)(processName);
175 dlclose(handle);
176 }
177
ClearEnvironment(const AppSpawnMgr * content,const AppSpawningCtx * property)178 static void ClearEnvironment(const AppSpawnMgr *content, const AppSpawningCtx *property)
179 {
180 sigset_t mask;
181 sigemptyset(&mask);
182 sigaddset(&mask, SIGCHLD);
183 sigaddset(&mask, SIGTERM);
184 sigprocmask(SIG_UNBLOCK, &mask, NULL);
185 // close child fd
186 AppSpawningCtx *ctx = (AppSpawningCtx *)property;
187 close(ctx->forkCtx.fd[0]);
188 ctx->forkCtx.fd[0] = -1;
189 return;
190 }
191
SetXpmConfig(const AppSpawnMgr * content,const AppSpawningCtx * property)192 static int SetXpmConfig(const AppSpawnMgr *content, const AppSpawningCtx *property)
193 {
194 #ifdef CODE_SIGNATURE_ENABLE
195 // nwebspawn no permission set xpm config
196 if (IsNWebSpawnMode(content)) {
197 return 0;
198 }
199
200 uint32_t len = 0;
201 char *provisionType = GetAppPropertyExt(property, MSG_EXT_NAME_PROVISION_TYPE, &len);
202 if (provisionType == NULL || len == 0) {
203 APPSPAWN_LOGE("get provision type failed, defaut is %{public}s", PROVISION_TYPE_DEBUG);
204 provisionType = PROVISION_TYPE_DEBUG;
205 }
206
207 AppSpawnMsgOwnerId *ownerInfo = (AppSpawnMsgOwnerId *)GetAppProperty(property, TLV_OWNER_INFO);
208 int jitfortEnable = IsJitFortModeOn(property) ? 1 : 0;
209 int idType = PROCESS_OWNERID_UNINIT;
210 const char *ownerId = NULL;
211 if (strcmp(provisionType, PROVISION_TYPE_DEBUG) == 0) {
212 idType = PROCESS_OWNERID_DEBUG;
213 } else if (ownerInfo == NULL) {
214 idType = PROCESS_OWNERID_COMPAT;
215 } else if (CheckAppMsgFlagsSet(property, APP_FLAGS_TEMP_JIT)) {
216 idType = PROCESS_OWNERID_APP_TEMP_ALLOW;
217 ownerId = ownerInfo->ownerId;
218 } else {
219 idType = PROCESS_OWNERID_APP;
220 ownerId = ownerInfo->ownerId;
221 }
222 int ret = InitXpm(jitfortEnable, idType, ownerId);
223 APPSPAWN_CHECK(ret == 0, return ret, "set xpm region failed: %{public}d", ret);
224 #endif
225 return 0;
226 }
227
SetUidGid(const AppSpawnMgr * content,const AppSpawningCtx * property)228 static int SetUidGid(const AppSpawnMgr *content, const AppSpawningCtx *property)
229 {
230 if (IsAppSpawnMode(content)) {
231 struct sched_param param = { 0 };
232 param.sched_priority = 0;
233 int ret = sched_setscheduler(0, SCHED_OTHER, ¶m);
234 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "UpdateSchedPrio failed ret: %{public}d, %{public}d", ret, errno);
235 }
236 AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO);
237 APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE,
238 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, GetProcessName(property));
239
240 // set gids
241 int ret = setgroups(dacInfo->gidCount, (const gid_t *)(&dacInfo->gidTable[0]));
242 APPSPAWN_CHECK(ret == 0, return errno,
243 "setgroups failed: %{public}d, gids.size=%{public}u", errno, dacInfo->gidCount);
244
245 // set gid
246 if (IsNWebSpawnMode(content)) {
247 gid_t gid = dacInfo->gid / UID_BASE;
248 if (gid >= 100) { // 100
249 APPSPAWN_LOGE("SetUidGid invalid uid for nwebspawn %{public}d", dacInfo->gid);
250 return 0;
251 }
252 ret = setresgid(dacInfo->gid, dacInfo->gid, dacInfo->gid);
253 } else {
254 ret = setresgid(dacInfo->gid, dacInfo->gid, dacInfo->gid);
255 }
256 APPSPAWN_CHECK(ret == 0, return errno,
257 "setgid(%{public}u) failed: %{public}d", dacInfo->gid, errno);
258
259 ret = SetSeccompFilter(content, property);
260 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set setSeccompFilter");
261
262 /* If the effective user ID is changed from 0 to nonzero,
263 * then all capabilities are cleared from the effective set
264 */
265 ret = setresuid(dacInfo->uid, dacInfo->uid, dacInfo->uid);
266 APPSPAWN_CHECK(ret == 0, return errno,
267 "setuid(%{public}u) failed: %{public}d", dacInfo->uid, errno);
268
269 if (CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE) && IsDeveloperModeOn(property)) {
270 setenv("HAP_DEBUGGABLE", "true", 1);
271 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
272 APPSPAWN_LOGE("Failed to set app dumpable: %{public}s", strerror(errno));
273 }
274 } else {
275 setenv("HAP_DEBUGGABLE", "false", 1);
276 }
277 return 0;
278 }
279
SetFileDescriptors(const AppSpawnMgr * content,const AppSpawningCtx * property)280 static int32_t SetFileDescriptors(const AppSpawnMgr *content, const AppSpawningCtx *property)
281 {
282 #ifndef APPSPAWN_TEST
283 // redirect stdin stdout stderr to /dev/null
284 int devNullFd = open(DEVICE_NULL_STR, O_RDWR);
285 if (devNullFd == -1) {
286 APPSPAWN_LOGE("open dev_null error: %{public}d", errno);
287 return (-errno);
288 }
289
290 // stdin
291 if (dup2(devNullFd, STDIN_FILENO) == -1) {
292 APPSPAWN_LOGE("dup2 STDIN error: %{public}d", errno);
293 return (-errno);
294 }
295 // stdout
296 if (dup2(devNullFd, STDOUT_FILENO) == -1) {
297 APPSPAWN_LOGE("dup2 STDOUT error: %{public}d", errno);
298 return (-errno);
299 }
300 // stderr
301 if (dup2(devNullFd, STDERR_FILENO) == -1) {
302 APPSPAWN_LOGE("dup2 STDERR error: %{public}d", errno);
303 return (-errno);
304 }
305
306 if (devNullFd > STDERR_FILENO) {
307 close(devNullFd);
308 }
309 #endif
310 return 0;
311 }
312
CheckTraceStatus(void)313 static int32_t CheckTraceStatus(void)
314 {
315 int fd = open("/proc/self/status", O_RDONLY);
316 APPSPAWN_CHECK(fd >= 0, return errno, "Failed to open /proc/self/status error: %{public}d", errno);
317
318 char data[1024] = {0}; // 1024 is data length
319 ssize_t dataNum = read(fd, data, sizeof(data) - 1);
320 (void)close(fd);
321 APPSPAWN_CHECK(dataNum > 0, return -1, "Failed to read file /proc/self/status error: %{public}d", errno);
322
323 const char *tracerPid = "TracerPid:\t";
324 data[dataNum] = '\0';
325 char *traceStr = strstr(data, tracerPid);
326 APPSPAWN_CHECK(traceStr != NULL, return -1, "Not found %{public}s", tracerPid);
327
328 char *separator = strchr(traceStr, '\n');
329 APPSPAWN_CHECK(separator != NULL, return -1, "Not found %{public}s", "\n");
330
331 int len = separator - traceStr - strlen(tracerPid);
332 char pid = *(traceStr + strlen(tracerPid));
333 if (len > 1 || pid != '0') {
334 return 0;
335 }
336 return -1;
337 }
338
WaitForDebugger(const AppSpawningCtx * property)339 static int32_t WaitForDebugger(const AppSpawningCtx *property)
340 {
341 // wait for debugger only debugging is required and process is debuggable
342 if (CheckAppMsgFlagsSet(property, APP_FLAGS_NATIVEDEBUG) && CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE)) {
343 uint32_t count = 0;
344 while (CheckTraceStatus() != 0) {
345 #ifndef APPSPAWN_TEST
346 usleep(1000 * 100); // sleep 1000 * 100 microsecond
347 #else
348 if (count > 0) {
349 break;
350 }
351 #endif
352 count++;
353 // remind users to connect to the debugger every 60 * 10 times
354 if (count % (10 * 60) == 0) {
355 count = 0;
356 APPSPAWN_LOGI("wait for debugger, please attach the process");
357 }
358 }
359 }
360 return 0;
361 }
362
SpawnInitSpawningEnv(AppSpawnMgr * content,AppSpawningCtx * property)363 static int SpawnInitSpawningEnv(AppSpawnMgr *content, AppSpawningCtx *property)
364 {
365 APPSPAWN_LOGV("Spawning: clear env");
366 int ret = SetProcessName(content, property);
367 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
368 // close socket id and signal for child
369 ClearEnvironment(content, property);
370
371 ResetParamSecurityLabel();
372
373 ret = SetAppAccessToken(content, property);
374 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
375 return 0;
376 }
377
SpawnSetAppEnv(AppSpawnMgr * content,AppSpawningCtx * property)378 static int SpawnSetAppEnv(AppSpawnMgr *content, AppSpawningCtx *property)
379 {
380 APPSPAWN_LOGV("Spawning: set appEnv");
381 int ret = SetEnvInfo(content, property);
382 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
383 return 0;
384 }
385
SpawnEnableCache(AppSpawnMgr * content,AppSpawningCtx * property)386 static int SpawnEnableCache(AppSpawnMgr *content, AppSpawningCtx *property)
387 {
388 APPSPAWN_LOGV("Spawning: enable cache for app process");
389 // enable cache for app process
390 mallopt(M_OHOS_CONFIG, M_TCACHE_PERFORMANCE_MODE);
391 mallopt(M_OHOS_CONFIG, M_ENABLE_OPT_TCACHE);
392 mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_ENABLE);
393 mallopt(M_DELAYED_FREE, M_DELAYED_FREE_ENABLE);
394
395 int ret = SetInternetPermission(property);
396 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
397 return ret;
398 }
399
SpawnLoadSilk(const AppSpawnMgr * content,const AppSpawningCtx * property)400 static void SpawnLoadSilk(const AppSpawnMgr *content, const AppSpawningCtx *property)
401 {
402 const char *processName = GetBundleName(property);
403 APPSPAWN_CHECK(processName != NULL, return, "Can not get bundle name");
404 LoadSilkLibrary(processName);
405 }
406
SpawnSetProperties(AppSpawnMgr * content,AppSpawningCtx * property)407 static int SpawnSetProperties(AppSpawnMgr *content, AppSpawningCtx *property)
408 {
409 APPSPAWN_LOGV("Spawning: set child property");
410 SpawnLoadSilk(content, property);
411 (void)umask(DEFAULT_UMASK);
412 int ret = SetKeepCapabilities(content, property);
413 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
414 ret = SetXpmConfig(content, property);
415 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
416
417 ret = SetProcessName(content, property);
418 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
419
420 ret = SetUidGid(content, property);
421 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
422
423 ret = SetFileDescriptors(content, property);
424 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
425
426 ret = SetCapabilities(content, property);
427 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
428
429 ret = SetSelinuxCon(content, property) == -1;
430 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
431
432 ret = WaitForDebugger(property);
433 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
434
435 APPSPAWN_ONLY_EXPER(GetAppSpawnMsgType(property) == MSG_SPAWN_NATIVE_PROCESS, return 0);
436 #ifdef SECURITY_COMPONENT_ENABLE
437 InitSecCompClientEnhance();
438 #endif
439 return 0;
440 }
441
PreLoadSetSeccompFilter(AppSpawnMgr * content)442 static int PreLoadSetSeccompFilter(AppSpawnMgr *content)
443 {
444 // set uid gid filetr
445 int ret = SetUidGidFilter(content);
446 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
447 return ret;
448 }
449
SpawnComplete(AppSpawnMgr * content,AppSpawningCtx * property)450 static int SpawnComplete(AppSpawnMgr *content, AppSpawningCtx *property)
451 {
452 InitDebugParams(content, property);
453 return 0;
454 }
455
CheckEnabled(const char * param,const char * value)456 static int CheckEnabled(const char *param, const char *value)
457 {
458 char tmp[32] = {0}; // 32 max
459 int ret = GetParameter(param, "", tmp, sizeof(tmp));
460 APPSPAWN_LOGV("CheckEnabled key %{public}s ret %{public}d result: %{public}s", param, ret, tmp);
461 int enabled = (ret > 0 && strcmp(tmp, value) == 0);
462 return enabled;
463 }
464
SpawnGetSpawningFlag(AppSpawnMgr * content,AppSpawningCtx * property)465 static int SpawnGetSpawningFlag(AppSpawnMgr *content, AppSpawningCtx *property)
466 {
467 APPSPAWN_LOGV("Spawning: prepare app %{public}s", GetProcessName(property));
468 if (CheckAppMsgFlagsSet(property, APP_FLAGS_COLD_BOOT)) {
469 // check cold start
470 property->client.flags |= CheckEnabled("startup.appspawn.cold.boot", "true") ? APP_COLD_START : 0;
471 }
472 if (CheckAppMsgFlagsSet(property, APP_FLAGS_BEGETCTL_BOOT)) {
473 // Start app from begetctl for debugging.
474 property->client.flags |= APP_BEGETCTL_BOOT;
475 APPSPAWN_LOGI("Spawning: prepare app %{public}s, start from begetctl", GetProcessName(property));
476 }
477 property->client.flags |= content->flags;
478 return 0;
479 }
480
SpawnLoadConfig(AppSpawnMgr * content)481 static int SpawnLoadConfig(AppSpawnMgr *content)
482 {
483 LoadSilkConfig();
484 // init flags that will not change until next reboot
485 content->flags |= CheckEnabled("const.security.developermode.state", "true") ? APP_DEVELOPER_MODE : 0;
486 content->flags |= CheckEnabled("persist.security.jitfort.disabled", "true") ? 0 : APP_JITFORT_MODE;
487 return 0;
488 }
489
CloseFdArgs(AppSpawnMgr * content,AppSpawningCtx * property)490 static int CloseFdArgs(AppSpawnMgr *content, AppSpawningCtx *property)
491 {
492 APPSPAWN_CHECK(property != NULL && property->message != NULL
493 && property->message->connection != NULL,
494 return -1, "Get connection info failed");
495 int fdCount = property->message->connection->receiverCtx.fdCount;
496 int *fds = property->message->connection->receiverCtx.fds;
497 if (fds != NULL && fdCount > 0) {
498 for (int i = 0; i < fdCount; i++) {
499 if (fds[i] > 0) {
500 close(fds[i]);
501 }
502 }
503 }
504 property->message->connection->receiverCtx.fdCount = 0;
505 return 0;
506 }
507
SetFdEnv(AppSpawnMgr * content,AppSpawningCtx * property)508 APPSPAWN_STATIC int SetFdEnv(AppSpawnMgr *content, AppSpawningCtx *property)
509 {
510 APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1);
511 APPSPAWN_CHECK_ONLY_EXPER(!property->isPrefork, return 0);
512 AppSpawnMsgNode *message = property->message;
513 APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL && message->connection != NULL, return -1);
514 APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset != NULL, return -1);
515 int findFdIndex = 0;
516 AppSpawnMsgReceiverCtx recvCtx = message->connection->receiverCtx;
517 APPSPAWN_CHECK(recvCtx.fds != NULL && recvCtx.fdCount > 0, return 0,
518 "no need set fd info %{public}d, %{public}d", recvCtx.fds != NULL, recvCtx.fdCount);
519 char keyBuffer[APP_FDNAME_MAXLEN + sizeof(APP_FDENV_PREFIX)];
520 char value[sizeof(int)];
521
522 for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) {
523 if (message->tlvOffset[index] == INVALID_OFFSET) {
524 return -1;
525 }
526 uint8_t *data = message->buffer + message->tlvOffset[index];
527 if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) {
528 continue;
529 }
530 AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data;
531 if (strcmp(tlv->tlvName, MSG_EXT_NAME_APP_FD) != 0) {
532 continue;
533 }
534 APPSPAWN_CHECK(findFdIndex < recvCtx.fdCount && recvCtx.fds[findFdIndex] > 0, return -1,
535 "check set env args failed %{public}d, %{public}d, %{public}d",
536 findFdIndex, recvCtx.fdCount, recvCtx.fds[findFdIndex]);
537 APPSPAWN_CHECK(snprintf_s(keyBuffer, sizeof(keyBuffer), sizeof(keyBuffer) - 1, APP_FDENV_PREFIX"%s",
538 data + sizeof(AppSpawnTlvExt)) >= 0, return -1, "failed print env key %{public}d", errno);
539 APPSPAWN_CHECK(snprintf_s(value, sizeof(value), sizeof(value) - 1,
540 "%d", recvCtx.fds[findFdIndex++]) >= 0, return -1, "failed print env key %{public}d", errno);
541 int ret = setenv(keyBuffer, value, 1);
542 APPSPAWN_CHECK(ret == 0, return -1, "failed setenv %{public}s, %{public}s", keyBuffer, value);
543 if (findFdIndex >= recvCtx.fdCount) {
544 break;
545 }
546 }
547 return 0;
548 }
549
RecordStartTime(AppSpawnMgr * content,AppSpawningCtx * property)550 APPSPAWN_STATIC int RecordStartTime(AppSpawnMgr *content, AppSpawningCtx *property)
551 {
552 struct timespec ts;
553 int ret = clock_gettime(CLOCK_MONOTONIC, &ts);
554 APPSPAWN_CHECK(ret == 0, return 0, "clock_gettime failed %{public}d,%{public}d", ret, errno);
555 long long startTime = (ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000);
556 char timeChar[32];
557 ret = snprintf_s(timeChar, sizeof(timeChar), sizeof(timeChar) - 1, "%lld", startTime);
558 APPSPAWN_CHECK(ret > 0, return 0, "failed to snprintf_s %{public}d,%{public}d", ret, errno);
559 ret = setenv(PROCESS_START_TIME_ENV, timeChar, 1);
560 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "set env failed %{public}d,%{public}d", ret, errno);
561 return 0;
562 }
563
MODULE_CONSTRUCTOR(void)564 MODULE_CONSTRUCTOR(void)
565 {
566 APPSPAWN_LOGV("Load common module ...");
567 AddPreloadHook(HOOK_PRIO_COMMON, PreLoadSetSeccompFilter);
568 AddPreloadHook(HOOK_PRIO_COMMON, SpawnLoadConfig);
569
570 AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_HIGHEST, SpawnGetSpawningFlag);
571 AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SpawnInitSpawningEnv);
572 AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON + 1, SpawnSetAppEnv);
573 AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_HIGHEST, SpawnEnableCache);
574 AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_PROPERTY, SpawnSetProperties);
575 AddAppSpawnHook(STAGE_CHILD_POST_RELY, HOOK_PRIO_HIGHEST, SpawnComplete);
576 AddAppSpawnHook(STAGE_PARENT_POST_FORK, HOOK_PRIO_HIGHEST, CloseFdArgs);
577 AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SetFdEnv);
578 AddAppSpawnHook(STAGE_CHILD_PRE_RUN, HOOK_PRIO_HIGHEST, RecordStartTime);
579 }
580