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