• 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 #include <dirent.h>
34 
35 #undef _GNU_SOURCE
36 #define _GNU_SOURCE
37 #include <dlfcn.h>
38 #include <malloc.h>
39 #include <sched.h>
40 
41 #include "appspawn_adapter.h"
42 #include "appspawn_hook.h"
43 #include "appspawn_service.h"
44 #include "appspawn_msg.h"
45 #include "appspawn_manager.h"
46 #include "appspawn_silk.h"
47 #include "appspawn_trace.h"
48 #include "init_param.h"
49 #include "parameter.h"
50 #include "securec.h"
51 
52 #ifdef APPSPAWN_HITRACE_OPTION
53 #include "hitrace_option/hitrace_option.h"
54 #endif
55 
56 #ifdef CODE_SIGNATURE_ENABLE  // for xpm
57 #include "code_sign_attr_utils.h"
58 #endif
59 #ifdef SECURITY_COMPONENT_ENABLE
60 #include "sec_comp_enhance_kit_c.h"
61 #endif
62 #ifdef WITH_SELINUX
63 #include "selinux/selinux.h"
64 #endif
65 
66 #define PROVISION_TYPE_DEBUG "debug"
67 #define DEVICE_NULL_STR "/dev/null"
68 #define PROCESS_START_TIME_ENV "PROCESS_START_TIME"
69 #define BITLEN32 32
70 #define PID_NS_INIT_UID 100000  // reserved for pid_ns_init process, avoid app, render proc, etc.
71 #define PID_NS_INIT_GID 100000
72 #define PREINSTALLED_HAP_FLAG 0x01 // hapFlags 0x01: SELINUX_HAP_RESTORECON_PREINSTALLED_APP in selinux
73 #define ISOLATE_PATH_NUM 2
74 #define ISOLATE_PATH_SIZE 4096
75 #define HM_DEC_IOCTL_BASE 's'
76 #define HM_ADD_ISOLATE_DIR 16
77 #define ADD_ISOLATE_DIR_CMD _IOWR(HM_DEC_IOCTL_BASE, HM_ADD_ISOLATE_DIR, IsolateDirInfo)
78 
SetProcessName(const AppSpawnMgr * content,const AppSpawningCtx * property)79 static int SetProcessName(const AppSpawnMgr *content, const AppSpawningCtx *property)
80 {
81     const char *processName = GetProcessName(property);
82     APPSPAWN_CHECK(processName != NULL, return -EINVAL, "Can not get process name");
83     // 解析时已经检查
84     size_t len = strlen(processName);
85     char shortName[MAX_LEN_SHORT_NAME] = {0};
86     // process short name max length 16 bytes.
87     size_t copyLen = len;
88     const char *pos = processName;
89     if (len >= MAX_LEN_SHORT_NAME) {
90         copyLen = MAX_LEN_SHORT_NAME - 1;
91         pos += (len - copyLen);
92     }
93     bool isRet = strncpy_s(shortName, MAX_LEN_SHORT_NAME, pos, copyLen) != EOK;
94     APPSPAWN_CHECK(!isRet, return EINVAL, "strncpy_s short name error: %{public}d", errno);
95 
96     // set short name
97     isRet = prctl(PR_SET_NAME, shortName) == -1;
98     APPSPAWN_CHECK(!isRet, return errno, "prctl(PR_SET_NAME) error: %{public}d", errno);
99 
100     // reset longProcName
101     isRet = memset_s(content->content.longProcName,
102         (size_t)content->content.longProcNameLen, 0, (size_t)content->content.longProcNameLen) != EOK;
103     APPSPAWN_CHECK(!isRet, return EINVAL, "Failed to memset long process name");
104 
105     // set long process name
106     isRet = strncpy_s(content->content.longProcName, content->content.longProcNameLen, processName, len) != EOK;
107     APPSPAWN_CHECK(!isRet, return EINVAL,
108         "strncpy_s long name error: %{public}d longProcNameLen %{public}u", errno, content->content.longProcNameLen);
109     return 0;
110 }
111 
SetKeepCapabilities(const AppSpawnMgr * content,const AppSpawningCtx * property)112 static int SetKeepCapabilities(const AppSpawnMgr *content, const AppSpawningCtx *property)
113 {
114     AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO);
115     APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE,
116         "No tlv %{public}d in msg %{public}s", TLV_DOMAIN_INFO, GetProcessName(property));
117 
118     // set keep capabilities when user not root.
119     if (dacInfo->uid != 0) {
120         bool isRet = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1;
121         APPSPAWN_CHECK(!isRet, return errno, "set keepcaps failed: %{public}d", errno);
122     }
123     return 0;
124 }
125 
126 #ifdef APPSPAWN_SUPPORT_NOSHAREFS
SetAmbientCapability(int cap)127 static int SetAmbientCapability(int cap)
128 {
129     if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0)) {
130         APPSPAWN_LOGE("prctl PR_CAP_AMBIENT failed: %{public}d", errno);
131         return -1;
132     }
133     return 0;
134 }
135 
SetAmbientCapabilities(const AppSpawningCtx * property)136 static int SetAmbientCapabilities(const AppSpawningCtx *property)
137 {
138     const int caps[] = {CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER};
139     size_t capCount = sizeof(caps) / sizeof(caps[0]);
140     for (size_t i = 0; i < capCount; ++i) {
141         if (SetAmbientCapability(caps[i]) != 0) {
142             APPSPAWN_LOGE("set cap failed: %{public}d", caps[i]);
143             return -1;
144         }
145     }
146     // Only custom sandbox app can set the CAP_KILL ambient to 1
147     if (CheckAppMsgFlagsSet(property, APP_FLAGS_CUSTOM_SANDBOX)) {
148         APPSPAWN_CHECK(SetAmbientCapability(CAP_KILL) == 0, return -1, "set ambient failed:%{public}d", CAP_KILL);
149     }
150     return 0;
151 }
152 #endif
153 
SetCapabilities(const AppSpawnMgr * content,const AppSpawningCtx * property)154 APPSPAWN_STATIC int SetCapabilities(const AppSpawnMgr *content, const AppSpawningCtx *property)
155 {
156     // init cap
157     struct __user_cap_header_struct capHeader;
158     bool isRet = memset_s(&capHeader, sizeof(capHeader), 0, sizeof(capHeader)) != EOK;
159     APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap header");
160 
161     capHeader.version = _LINUX_CAPABILITY_VERSION_3;
162     capHeader.pid = 0;
163     struct __user_cap_data_struct capData[2];
164     isRet = memset_s(&capData, sizeof(capData), 0, sizeof(capData)) != EOK;
165     APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap data");
166 
167     // init inheritable permitted effective zero
168 #ifdef GRAPHIC_PERMISSION_CHECK
169     u_int64_t baseCaps = 0;
170 #ifdef APPSPAWN_SUPPORT_NOSHAREFS
171     if (!CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE) &&
172             (IsAppSpawnMode(content) || IsNativeSpawnMode(content))) {
173         baseCaps = CAP_TO_MASK(CAP_DAC_OVERRIDE) | CAP_TO_MASK(CAP_DAC_READ_SEARCH) |
174                    CAP_TO_MASK(CAP_FOWNER);
175         if (CheckAppMsgFlagsSet(property, APP_FLAGS_CUSTOM_SANDBOX)) {
176             baseCaps |= CAP_TO_MASK(CAP_KILL);
177         }
178     }
179 #else
180     if (IsAppSpawnMode(content)) {
181         baseCaps = CheckAppMsgFlagsSet(property, APP_FLAGS_SET_CAPS_FOWNER) ? (1 << CAP_FOWNER) : 0;
182     }
183 #endif
184     const uint64_t inheriTable = baseCaps;
185     const uint64_t permitted = baseCaps;
186     const uint64_t effective = baseCaps;
187 #else
188     const uint64_t inheriTable = 0x3fffffffff;
189     const uint64_t permitted = 0x3fffffffff;
190     const uint64_t effective = 0x3fffffffff;
191 #endif
192     capData[0].inheritable = (__u32)(inheriTable);
193     capData[1].inheritable = (__u32)(inheriTable >> BITLEN32);
194     capData[0].permitted = (__u32)(permitted);
195     capData[1].permitted = (__u32)(permitted >> BITLEN32);
196     capData[0].effective = (__u32)(effective);
197     capData[1].effective = (__u32)(effective >> BITLEN32);
198     isRet = capset(&capHeader, &capData[0]) != 0;
199     APPSPAWN_CHECK(!isRet, return -errno, "Failed to capset errno: %{public}d", errno);
200 
201 #ifdef APPSPAWN_SUPPORT_NOSHAREFS
202     if (!CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE) &&
203         (IsAppSpawnMode(content) || IsNativeSpawnMode(content))) {
204         isRet = SetAmbientCapabilities(property);
205         APPSPAWN_CHECK(!isRet, return -1, "Failed to set ambient");
206     }
207 #endif
208     return 0;
209 }
210 
InitDebugParams(const AppSpawnMgr * content,const AppSpawningCtx * property)211 static void InitDebugParams(const AppSpawnMgr *content, const AppSpawningCtx *property)
212 {
213 #if defined(__aarch64__) || defined(__x86_64__)
214     const char *debugSoPath = "/system/lib64/libhidebug.so";
215 #else
216     const char *debugSoPath = "/system/lib/libhidebug.so";
217 #endif
218     const char *processName = GetProcessName(property);
219     APPSPAWN_CHECK(processName != NULL, return, "Can not get process name");
220 
221     bool isRet = access(debugSoPath, F_OK) != 0;
222     APPSPAWN_CHECK(!isRet, return,
223         "access failed, errno: %{public}d debugSoPath: %{public}s", errno, debugSoPath);
224 
225     void *handle = dlopen(debugSoPath, RTLD_LAZY);
226     APPSPAWN_CHECK(handle != NULL, return, "Failed to dlopen libhidebug.so errno: %{public}s", dlerror());
227 
228     bool (*initParam)(const char *name);
229     initParam = (bool (*)(const char *name))dlsym(handle, "InitEnvironmentParam");
230     APPSPAWN_CHECK(initParam != NULL, dlclose(handle);
231         return, "Failed to dlsym errno: %{public}s", dlerror());
232     (*initParam)(processName);
233     dlclose(handle);
234 }
235 
ClearEnvironment(const AppSpawnMgr * content,const AppSpawningCtx * property)236 static void ClearEnvironment(const AppSpawnMgr *content, const AppSpawningCtx *property)
237 {
238     sigset_t mask;
239     sigemptyset(&mask);
240     sigaddset(&mask, SIGCHLD);
241     sigaddset(&mask, SIGTERM);
242     sigprocmask(SIG_UNBLOCK, &mask, NULL);
243     // close child fd
244     AppSpawningCtx *ctx = (AppSpawningCtx *)property;
245     close(ctx->forkCtx.fd[0]);
246     ctx->forkCtx.fd[0] = -1;
247     return;
248 }
249 
SetXpmConfig(const AppSpawnMgr * content,const AppSpawningCtx * property)250 static int SetXpmConfig(const AppSpawnMgr *content, const AppSpawningCtx *property)
251 {
252 #ifdef CODE_SIGNATURE_ENABLE
253     // nwebspawn no permission set xpm config
254     if (IsNWebSpawnMode(content)) {
255         return 0;
256     }
257 
258     uint32_t len = 0;
259     char *provisionType = GetAppPropertyExt(property, MSG_EXT_NAME_PROVISION_TYPE, &len);
260     if (provisionType == NULL || len == 0) {
261         APPSPAWN_LOGE("get provision type failed, defaut is %{public}s", PROVISION_TYPE_DEBUG);
262         provisionType = PROVISION_TYPE_DEBUG;
263     }
264 
265     AppSpawnMsgOwnerId *ownerInfo = (AppSpawnMsgOwnerId *)GetAppProperty(property, TLV_OWNER_INFO);
266     int jitfortEnable = IsJitFortModeOn(property) ? 1 : 0;
267     int idType = PROCESS_OWNERID_UNINIT;
268     const char *ownerId = NULL;
269     if (strcmp(provisionType, PROVISION_TYPE_DEBUG) == 0) {
270         idType = PROCESS_OWNERID_DEBUG;
271     } else if (ownerInfo == NULL) {
272         idType = PROCESS_OWNERID_COMPAT;
273     } else if (CheckAppMsgFlagsSet(property, APP_FLAGS_TEMP_JIT)) {
274         idType = PROCESS_OWNERID_APP_TEMP_ALLOW;
275         ownerId = ownerInfo->ownerId;
276     } else {
277         idType = PROCESS_OWNERID_APP;
278         ownerId = ownerInfo->ownerId;
279     }
280 
281     char *apiTargetVersionStr = GetAppPropertyExt(property, MSG_EXT_NAME_API_TARGET_VERSION, &len);
282     int ret = InitXpm(jitfortEnable, idType, ownerId, apiTargetVersionStr);
283     APPSPAWN_CHECK(ret == 0, return ret, "set xpm region failed: %{public}d", ret);
284 #endif
285     return 0;
286 }
287 
SetUidGid(const AppSpawnMgr * content,const AppSpawningCtx * property)288 static int SetUidGid(const AppSpawnMgr *content, const AppSpawningCtx *property)
289 {
290     if (IsAppSpawnMode(content) || IsHybridSpawnMode(content)) {
291         struct sched_param param = { 0 };
292         param.sched_priority = 0;
293         int ret = sched_setscheduler(0, SCHED_OTHER, &param);
294         APPSPAWN_CHECK_ONLY_LOG(ret == 0, "UpdateSchedPrio failed ret: %{public}d, %{public}d", ret, errno);
295     }
296     AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO);
297     APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE,
298         "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, GetProcessName(property));
299 
300     // set gids
301     int ret = setgroups(dacInfo->gidCount, (const gid_t *)(&dacInfo->gidTable[0]));
302     APPSPAWN_CHECK(ret == 0, return errno,
303         "setgroups failed: %{public}d, gids.size=%{public}u", errno, dacInfo->gidCount);
304 
305     // set gid
306     if (IsNWebSpawnMode(content)) {
307         gid_t gid = dacInfo->gid / UID_BASE;
308         if (gid >= 100) { // 100
309             APPSPAWN_LOGE("SetUidGid invalid uid for nwebspawn %{public}d", dacInfo->gid);
310             return 0;
311         }
312         ret = setresgid(dacInfo->gid, dacInfo->gid, dacInfo->gid);
313     } else {
314         ret = setresgid(dacInfo->gid, dacInfo->gid, dacInfo->gid);
315     }
316     APPSPAWN_CHECK(ret == 0, return errno,
317         "setgid(%{public}u) failed: %{public}d", dacInfo->gid, errno);
318 
319     StartAppspawnTrace("SetSeccompFilter");
320     ret = SetSeccompFilter(content, property);
321     FinishAppspawnTrace();
322     APPSPAWN_CHECK(ret == 0, return ret, "Failed to set setSeccompFilter");
323 
324     /* If the effective user ID is changed from 0 to nonzero,
325      * then all capabilities are cleared from the effective set
326      */
327     ret = setresuid(dacInfo->uid, dacInfo->uid, dacInfo->uid);
328     APPSPAWN_CHECK(ret == 0, return errno,
329         "setuid(%{public}u) failed: %{public}d", dacInfo->uid, errno);
330 
331     if (CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE) && IsDeveloperModeOn(property)) {
332         setenv("HAP_DEBUGGABLE", "true", 1);
333         if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
334             APPSPAWN_LOGE("Failed to set app dumpable: %{public}s", strerror(errno));
335         }
336     } else {
337         setenv("HAP_DEBUGGABLE", "false", 1);
338     }
339     return 0;
340 }
341 
SetFileDescriptors(const AppSpawnMgr * content,const AppSpawningCtx * property)342 static int32_t SetFileDescriptors(const AppSpawnMgr *content, const AppSpawningCtx *property)
343 {
344 #ifndef APPSPAWN_TEST
345     // redirect stdin stdout stderr to /dev/null
346     int devNullFd = open(DEVICE_NULL_STR, O_RDWR);
347     if (devNullFd == -1) {
348         APPSPAWN_LOGE("open dev_null error: %{public}d", errno);
349         return (-errno);
350     }
351 
352     // stdin
353     if (dup2(devNullFd, STDIN_FILENO) == -1) {
354         APPSPAWN_LOGE("dup2 STDIN error: %{public}d", errno);
355         return (-errno);
356     }
357     // stdout
358     if (dup2(devNullFd, STDOUT_FILENO) == -1) {
359         APPSPAWN_LOGE("dup2 STDOUT error: %{public}d", errno);
360         return (-errno);
361     }
362     // stderr
363     if (dup2(devNullFd, STDERR_FILENO) == -1) {
364         APPSPAWN_LOGE("dup2 STDERR error: %{public}d", errno);
365         return (-errno);
366     }
367 
368     if (devNullFd > STDERR_FILENO) {
369         close(devNullFd);
370     }
371 #endif
372     return 0;
373 }
374 
CheckTraceStatus(void)375 static int32_t CheckTraceStatus(void)
376 {
377     int fd = open("/proc/self/status", O_RDONLY);
378     APPSPAWN_CHECK(fd >= 0, return errno, "Failed to open /proc/self/status error: %{public}d", errno);
379 
380     char data[1024] = {0};  // 1024 is data length
381     ssize_t dataNum = read(fd, data, sizeof(data) - 1);
382     (void)close(fd);
383     APPSPAWN_CHECK(dataNum > 0, return -1, "Failed to read file /proc/self/status error: %{public}d", errno);
384 
385     const char *tracerPid = "TracerPid:\t";
386     data[dataNum] = '\0';
387     char *traceStr = strstr(data, tracerPid);
388     APPSPAWN_CHECK(traceStr != NULL, return -1, "Not found %{public}s", tracerPid);
389 
390     char *separator = strchr(traceStr, '\n');
391     APPSPAWN_CHECK(separator != NULL, return -1, "Not found %{public}s", "\n");
392 
393     int len = separator - traceStr - strlen(tracerPid);
394     char pid = *(traceStr + strlen(tracerPid));
395     if (len > 1 || pid != '0') {
396         return 0;
397     }
398     return -1;
399 }
400 
WaitForDebugger(const AppSpawningCtx * property)401 static int32_t WaitForDebugger(const AppSpawningCtx *property)
402 {
403     // wait for debugger only debugging is required and process is debuggable
404     if (CheckAppMsgFlagsSet(property, APP_FLAGS_NATIVEDEBUG) && CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE)) {
405         uint32_t count = 0;
406         while (CheckTraceStatus() != 0) {
407 #ifndef APPSPAWN_TEST
408             usleep(1000 * 100);  // sleep 1000 * 100 microsecond
409 #else
410             if (count > 0) {
411                 break;
412             }
413 #endif
414             count++;
415             // remind users to connect to the debugger every 60 * 10 times
416             if (count % (10 * 60) == 0) {
417                 count = 0;
418                 APPSPAWN_LOGI("wait for debugger, please attach the process");
419             }
420         }
421     }
422     return 0;
423 }
424 
SpawnSetPreInstalledFlag(AppSpawningCtx * property)425 static int SpawnSetPreInstalledFlag(AppSpawningCtx *property)
426 {
427     AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetAppProperty(property, TLV_DOMAIN_INFO);
428     APPSPAWN_CHECK(msgDomainInfo != NULL, return APPSPAWN_TLV_NONE, "No domain info in req from %{public}s",
429                    GetProcessName(property));
430     if ((msgDomainInfo->hapFlags & PREINSTALLED_HAP_FLAG) != 0) {
431         int ret = SetAppSpawnMsgFlag(property->message, TLV_MSG_FLAGS, APP_FLAGS_PRE_INSTALLED_HAP);
432         if (ret != 0) {
433             APPSPAWN_LOGE("Set appspawn msg flag failed");
434             return ret;
435         }
436     }
437     return 0;
438 }
439 
440 typedef struct {
441     char isolatePath[ISOLATE_PATH_NUM][ISOLATE_PATH_SIZE];
442     int pathNum;
443 } IsolateDirInfo;
444 
445 /*
446  * Open isolate dir to prevent vnode from being released and ensure that
447  * vflag in vnode which we set by ioctl is valid during the app running.
448  * Fd will be automatically released when process exits.
449  */
450 #ifdef CUSTOM_SANDBOX
HoldIsolateDir(IsolateDirInfo * isolateDirInfo)451 static void HoldIsolateDir(IsolateDirInfo *isolateDirInfo)
452 {
453     DIR *dir = opendir(isolateDirInfo->isolatePath[0]);
454     APPSPAWN_CHECK_ONLY_LOG(!(dir == NULL), "open isolate dir %{public}s failed, errno is %{public}d",
455         isolateDirInfo->isolatePath[0], errno);
456 
457     DIR *dir1 = opendir(isolateDirInfo->isolatePath[1]);
458     APPSPAWN_CHECK_ONLY_LOG(!(dir1 == NULL), "open isolate dir %{public}s failed, errno is %{public}d",
459         isolateDirInfo->isolatePath[1], errno);
460 }
461 #endif
462 
SetIsolateDir(const AppSpawningCtx * property)463 APPSPAWN_STATIC int SetIsolateDir(const AppSpawningCtx *property)
464 {
465 #ifdef CUSTOM_SANDBOX
466     const char *bundleName = GetBundleName(property);
467     APPSPAWN_CHECK(bundleName != NULL, return -1, "Can not get bundle name");
468 
469     AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO);
470     APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE,
471         "No tlv %{public}d in msg %{public}s", TLV_DOMAIN_INFO, bundleName);
472     APPSPAWN_ONLY_EXPER(dacInfo->uid / UID_BASE == 0, return 0);
473 
474     int ret = 0;
475     IsolateDirInfo isolateDirInfo = {0};
476     ret = snprintf_s(isolateDirInfo.isolatePath[0], ISOLATE_PATH_SIZE, ISOLATE_PATH_SIZE - 1, "%s/%u/%s",
477                      "/data/app/el2", dacInfo->uid / UID_BASE, "base");
478     APPSPAWN_CHECK(ret >= 0, return ret, "snprintf_s el2 path failed, errno %{public}d", errno);
479     ret = snprintf_s(isolateDirInfo.isolatePath[1], ISOLATE_PATH_SIZE, ISOLATE_PATH_SIZE - 1, "%s/%u/%s",
480                      "/storage/media", dacInfo->uid / UID_BASE, "local/files/Docs");
481     APPSPAWN_CHECK(ret >= 0, return ret, "snprintf_s storage path failed, errno %{public}d", errno);
482     isolateDirInfo.pathNum = ISOLATE_PATH_NUM;
483 
484     HoldIsolateDir(&isolateDirInfo);
485 
486     int fd = open("/dev/dec", O_RDWR);
487     APPSPAWN_CHECK(fd >= 0, return fd, "open dec file fail, errno %{public}d", errno);
488 
489     ret = ioctl(fd, ADD_ISOLATE_DIR_CMD, &isolateDirInfo);
490     APPSPAWN_CHECK(ret == 0, close(fd);
491                    return ret, "ioctl ADD_ISOLATE_DIR_CMD fail, errno %{public}d", errno);
492 
493     APPSPAWN_LOGI("ioctl ADD_ISOLATE_DIR_CMD success");
494     close(fd);
495 #endif
496     return 0;
497 }
498 
SpawnInitSpawningEnv(AppSpawnMgr * content,AppSpawningCtx * property)499 static int SpawnInitSpawningEnv(AppSpawnMgr *content, AppSpawningCtx *property)
500 {
501     APPSPAWN_LOGV("Spawning: clear env");
502     int ret = SetProcessName(content, property);
503     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
504     // close socket id and signal for child
505     ClearEnvironment(content, property);
506 
507     ResetParamSecurityLabel();
508 
509     ret = SetAppAccessToken(content, property);
510     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
511 
512     if ((IsAppSpawnMode(content) || IsHybridSpawnMode(content) || IsNativeSpawnMode(content))) {
513         ret = SetIsolateDir(property);
514         APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to set isolate dir, ret %{public}d", ret);
515     }
516 
517     ret = SpawnSetPreInstalledFlag(property);
518     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
519     return 0;
520 }
521 
SpawnSetAppEnv(AppSpawnMgr * content,AppSpawningCtx * property)522 static int SpawnSetAppEnv(AppSpawnMgr *content, AppSpawningCtx *property)
523 {
524     APPSPAWN_LOGV("Spawning: set appEnv");
525     int ret = SetEnvInfo(content, property);
526     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
527     return 0;
528 }
529 
SpawnEnableCache(AppSpawnMgr * content,AppSpawningCtx * property)530 static int SpawnEnableCache(AppSpawnMgr *content, AppSpawningCtx *property)
531 {
532     APPSPAWN_LOGV("Spawning: enable cache for app process");
533     // enable cache for app process
534     mallopt(M_OHOS_CONFIG, M_TCACHE_PERFORMANCE_MODE);
535     mallopt(M_OHOS_CONFIG, M_ENABLE_OPT_TCACHE);
536     mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_ENABLE);
537     mallopt(M_DELAYED_FREE, M_DELAYED_FREE_ENABLE);
538 
539     int ret = SetInternetPermission(property);
540     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
541     return ret;
542 }
543 
SpawnLoadSilk(const AppSpawnMgr * content,const AppSpawningCtx * property)544 static void SpawnLoadSilk(const AppSpawnMgr *content, const AppSpawningCtx *property)
545 {
546     const char *processName = GetBundleName(property);
547     APPSPAWN_CHECK(processName != NULL, return, "Can not get bundle name");
548     (void)LoadSilkLibrary(processName);
549 }
550 
551 #ifdef APPSPAWN_HITRACE_OPTION
FilterAppSpawnTrace(AppSpawnMgr * content,AppSpawningCtx * property)552 APPSPAWN_STATIC int FilterAppSpawnTrace(AppSpawnMgr *content, AppSpawningCtx *property)
553 {
554     const char *processName = GetProcessName(property);
555     if (processName != NULL) {
556         pid_t pid = getpid();
557         APPSPAWN_LOGV("processName: %{public}s pid: %{public}d", processName, pid);
558         FilterAppTrace(processName, pid);
559     } else {
560         APPSPAWN_LOGI("processName is NULL");
561     }
562 
563     return 0;
564 }
565 #endif
566 
SpawnSetProperties(AppSpawnMgr * content,AppSpawningCtx * property)567 static int SpawnSetProperties(AppSpawnMgr *content, AppSpawningCtx *property)
568 {
569     APPSPAWN_LOGV("Spawning: set child property");
570     SpawnLoadSilk(content, property);
571     (void)umask(DEFAULT_UMASK);
572     int ret = SetKeepCapabilities(content, property);
573     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
574     ret = SetXpmConfig(content, property);
575     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
576 
577     ret = SetProcessName(content, property);
578     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
579 
580     ret = SetUidGid(content, property);
581     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
582 
583     ret = SetFileDescriptors(content, property);
584     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
585 
586     ret = SetCapabilities(content, property);
587     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
588 
589     StartAppspawnTrace("SetSelinuxCon");
590     ret = SetSelinuxCon(content, property);
591     FinishAppspawnTrace();
592     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
593 
594     ret = WaitForDebugger(property);
595     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
596 
597     APPSPAWN_ONLY_EXPER(GetAppSpawnMsgType(property) == MSG_SPAWN_NATIVE_PROCESS, return 0);
598 #ifdef SECURITY_COMPONENT_ENABLE
599     StartAppspawnTrace("InitSecCompClientEnhance");
600     InitSecCompClientEnhance();
601     FinishAppspawnTrace();
602 #endif
603     return 0;
604 }
605 
PreLoadSetSeccompFilter(AppSpawnMgr * content)606 static int PreLoadSetSeccompFilter(AppSpawnMgr *content)
607 {
608     // set uid gid filetr
609     int ret = SetUidGidFilter(content);
610     APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
611     return ret;
612 }
613 
SpawnComplete(AppSpawnMgr * content,AppSpawningCtx * property)614 static int SpawnComplete(AppSpawnMgr *content, AppSpawningCtx *property)
615 {
616     InitDebugParams(content, property);
617     return 0;
618 }
619 
CheckEnabled(const char * param,const char * value)620 static int CheckEnabled(const char *param, const char *value)
621 {
622     char tmp[32] = {0};  // 32 max
623     int ret = GetParameter(param, "", tmp, sizeof(tmp));
624     APPSPAWN_LOGV("CheckEnabled key %{public}s ret %{public}d result: %{public}s", param, ret, tmp);
625     int enabled = (ret > 0 && strcmp(tmp, value) == 0);
626     return enabled;
627 }
628 
SpawnGetSpawningFlag(AppSpawnMgr * content,AppSpawningCtx * property)629 static int SpawnGetSpawningFlag(AppSpawnMgr *content, AppSpawningCtx *property)
630 {
631     APPSPAWN_LOGV("Spawning: prepare app %{public}s", GetProcessName(property));
632     if (CheckAppMsgFlagsSet(property, APP_FLAGS_COLD_BOOT)) {
633         // check cold start
634         property->client.flags |= CheckEnabled("startup.appspawn.cold.boot", "true") ? APP_COLD_START : 0;
635     }
636     if (CheckAppMsgFlagsSet(property, APP_FLAGS_BEGETCTL_BOOT)) {
637        // Start app from begetctl for debugging.
638         property->client.flags |=  APP_BEGETCTL_BOOT;
639         APPSPAWN_LOGI("Spawning: prepare app %{public}s, start from begetctl", GetProcessName(property));
640     }
641     property->client.flags |= content->flags;
642     return 0;
643 }
644 
SpawnLoadConfig(AppSpawnMgr * content)645 static int SpawnLoadConfig(AppSpawnMgr *content)
646 {
647     LoadSilkConfig();
648     // init flags that will not change until next reboot
649     content->flags |= CheckEnabled("const.security.developermode.state", "true") ? APP_DEVELOPER_MODE : 0;
650     content->flags |= CheckEnabled("persist.security.jitfort.disabled", "true") ? 0 : APP_JITFORT_MODE;
651     return 0;
652 }
653 
CloseFdArgs(AppSpawnMgr * content,AppSpawningCtx * property)654 static int CloseFdArgs(AppSpawnMgr *content, AppSpawningCtx *property)
655 {
656     APPSPAWN_CHECK(property != NULL && property->message != NULL
657         && property->message->connection != NULL,
658         return -1, "Get connection info failed");
659     int fdCount = property->message->connection->receiverCtx.fdCount;
660     int *fds = property->message->connection->receiverCtx.fds;
661     if (fds != NULL && fdCount > 0) {
662         for (int i = 0; i < fdCount; i++) {
663             if (fds[i] > 0) {
664                 close(fds[i]);
665             }
666         }
667     }
668     property->message->connection->receiverCtx.fdCount = 0;
669     return 0;
670 }
671 
SetFdEnv(AppSpawnMgr * content,AppSpawningCtx * property)672 APPSPAWN_STATIC int SetFdEnv(AppSpawnMgr *content, AppSpawningCtx *property)
673 {
674     APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1);
675     APPSPAWN_CHECK_ONLY_EXPER(!property->isPrefork, return 0);
676     AppSpawnMsgNode *message = property->message;
677     APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL && message->connection != NULL, return -1);
678     APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset != NULL, return -1);
679     int findFdIndex = 0;
680     AppSpawnMsgReceiverCtx recvCtx = message->connection->receiverCtx;
681     APPSPAWN_CHECK_LOGV(recvCtx.fds != NULL && recvCtx.fdCount > 0, return 0,
682         "no need set fd info %{public}d, %{public}d", recvCtx.fds != NULL, recvCtx.fdCount);
683     char keyBuffer[APP_FDNAME_MAXLEN + sizeof(APP_FDENV_PREFIX)];
684     char value[sizeof(int)];
685 
686     for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) {
687         if (message->tlvOffset[index] == INVALID_OFFSET) {
688             return -1;
689         }
690         uint8_t *data = message->buffer + message->tlvOffset[index];
691         if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) {
692             continue;
693         }
694         AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data;
695         if (strcmp(tlv->tlvName, MSG_EXT_NAME_APP_FD) != 0) {
696             continue;
697         }
698         APPSPAWN_CHECK(findFdIndex < recvCtx.fdCount && recvCtx.fds[findFdIndex] > 0, return -1,
699             "check set env args failed %{public}d, %{public}d, %{public}d",
700             findFdIndex, recvCtx.fdCount, recvCtx.fds[findFdIndex]);
701         APPSPAWN_CHECK(snprintf_s(keyBuffer, sizeof(keyBuffer), sizeof(keyBuffer) - 1, APP_FDENV_PREFIX"%s",
702             data + sizeof(AppSpawnTlvExt)) >= 0, return -1, "failed print env key %{public}d", errno);
703         APPSPAWN_CHECK(snprintf_s(value, sizeof(value), sizeof(value) - 1,
704             "%d", recvCtx.fds[findFdIndex++]) >= 0, return -1, "failed print env key %{public}d", errno);
705         int ret = setenv(keyBuffer, value, 1);
706         APPSPAWN_CHECK(ret == 0, return -1, "failed setenv %{public}s, %{public}s", keyBuffer, value);
707         if (findFdIndex >= recvCtx.fdCount) {
708             break;
709         }
710     }
711     return 0;
712 }
713 
RecordStartTime(AppSpawnMgr * content,AppSpawningCtx * property)714 APPSPAWN_STATIC int RecordStartTime(AppSpawnMgr *content, AppSpawningCtx *property)
715 {
716     struct timespec ts;
717     int ret = clock_gettime(CLOCK_MONOTONIC, &ts);
718     APPSPAWN_CHECK(ret == 0, return 0, "clock_gettime failed %{public}d,%{public}d", ret, errno);
719     long long startTime = (ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000);
720     char timeChar[32];
721     ret = snprintf_s(timeChar, sizeof(timeChar), sizeof(timeChar) - 1, "%lld", startTime);
722     APPSPAWN_CHECK(ret > 0, return 0, "failed to snprintf_s %{public}d,%{public}d", ret, errno);
723     ret = setenv(PROCESS_START_TIME_ENV, timeChar, 1);
724     APPSPAWN_CHECK_ONLY_LOG(ret == 0, "set env failed %{public}d,%{public}d", ret, errno);
725     return 0;
726 }
727 
MODULE_CONSTRUCTOR(void)728 MODULE_CONSTRUCTOR(void)
729 {
730     APPSPAWN_LOGV("Load common module ...");
731     AddPreloadHook(HOOK_PRIO_COMMON, PreLoadSetSeccompFilter);
732     AddPreloadHook(HOOK_PRIO_COMMON, SpawnLoadConfig);
733 
734     AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_HIGHEST, SpawnGetSpawningFlag);
735     AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SpawnInitSpawningEnv);
736     AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON + 1, SpawnSetAppEnv);
737     AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_HIGHEST, SpawnEnableCache);
738 #ifdef APPSPAWN_HITRACE_OPTION
739     AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_COMMON, FilterAppSpawnTrace);
740 #endif
741     AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_PROPERTY, SpawnSetProperties);
742     AddAppSpawnHook(STAGE_CHILD_POST_RELY, HOOK_PRIO_HIGHEST, SpawnComplete);
743     AddAppSpawnHook(STAGE_PARENT_POST_FORK, HOOK_PRIO_HIGHEST, CloseFdArgs);
744     AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SetFdEnv);
745     AddAppSpawnHook(STAGE_CHILD_PRE_RUN, HOOK_PRIO_HIGHEST, RecordStartTime);
746 }
747