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