169570cc8Sopenharmony_ci/* 269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License. 569570cc8Sopenharmony_ci * You may obtain a copy of the License at 669570cc8Sopenharmony_ci * 769570cc8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 869570cc8Sopenharmony_ci * 969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and 1369570cc8Sopenharmony_ci * limitations under the License. 1469570cc8Sopenharmony_ci */ 1569570cc8Sopenharmony_ci#include <fcntl.h> 1669570cc8Sopenharmony_ci#include <grp.h> 1769570cc8Sopenharmony_ci#include <inttypes.h> 1869570cc8Sopenharmony_ci#include <limits.h> 1969570cc8Sopenharmony_ci#include <sys/capability.h> 2069570cc8Sopenharmony_ci#include <stdbool.h> 2169570cc8Sopenharmony_ci#include <stdio.h> 2269570cc8Sopenharmony_ci#include <stdlib.h> 2369570cc8Sopenharmony_ci#include <string.h> 2469570cc8Sopenharmony_ci#include <sys/ioctl.h> 2569570cc8Sopenharmony_ci#include <sys/mount.h> 2669570cc8Sopenharmony_ci#include <sys/prctl.h> 2769570cc8Sopenharmony_ci#include <sys/signalfd.h> 2869570cc8Sopenharmony_ci#include <sys/stat.h> 2969570cc8Sopenharmony_ci#include <sys/syscall.h> 3069570cc8Sopenharmony_ci#include <sys/types.h> 3169570cc8Sopenharmony_ci#include <sys/wait.h> 3269570cc8Sopenharmony_ci#include <unistd.h> 3369570cc8Sopenharmony_ci 3469570cc8Sopenharmony_ci#undef _GNU_SOURCE 3569570cc8Sopenharmony_ci#define _GNU_SOURCE 3669570cc8Sopenharmony_ci#include <dlfcn.h> 3769570cc8Sopenharmony_ci#include <malloc.h> 3869570cc8Sopenharmony_ci#include <sched.h> 3969570cc8Sopenharmony_ci 4069570cc8Sopenharmony_ci#include "appspawn_adapter.h" 4169570cc8Sopenharmony_ci#include "appspawn_hook.h" 4269570cc8Sopenharmony_ci#include "appspawn_service.h" 4369570cc8Sopenharmony_ci#include "appspawn_msg.h" 4469570cc8Sopenharmony_ci#include "appspawn_manager.h" 4569570cc8Sopenharmony_ci#include "appspawn_silk.h" 4669570cc8Sopenharmony_ci#include "init_param.h" 4769570cc8Sopenharmony_ci#include "parameter.h" 4869570cc8Sopenharmony_ci#include "securec.h" 4969570cc8Sopenharmony_ci 5069570cc8Sopenharmony_ci#ifdef CODE_SIGNATURE_ENABLE // for xpm 5169570cc8Sopenharmony_ci#include "code_sign_attr_utils.h" 5269570cc8Sopenharmony_ci#endif 5369570cc8Sopenharmony_ci#ifdef SECURITY_COMPONENT_ENABLE 5469570cc8Sopenharmony_ci#include "sec_comp_enhance_kit_c.h" 5569570cc8Sopenharmony_ci#endif 5669570cc8Sopenharmony_ci#ifdef WITH_SELINUX 5769570cc8Sopenharmony_ci#include "selinux/selinux.h" 5869570cc8Sopenharmony_ci#endif 5969570cc8Sopenharmony_ci 6069570cc8Sopenharmony_ci#define PROVISION_TYPE_DEBUG "debug" 6169570cc8Sopenharmony_ci#define DEVICE_NULL_STR "/dev/null" 6269570cc8Sopenharmony_ci#define BITLEN32 32 6369570cc8Sopenharmony_ci#define PID_NS_INIT_UID 100000 // reserved for pid_ns_init process, avoid app, render proc, etc. 6469570cc8Sopenharmony_ci#define PID_NS_INIT_GID 100000 6569570cc8Sopenharmony_ci 6669570cc8Sopenharmony_cistatic int SetProcessName(const AppSpawnMgr *content, const AppSpawningCtx *property) 6769570cc8Sopenharmony_ci{ 6869570cc8Sopenharmony_ci const char *processName = GetProcessName(property); 6969570cc8Sopenharmony_ci APPSPAWN_CHECK(processName != NULL, return -EINVAL, "Can not get process name"); 7069570cc8Sopenharmony_ci // 解析时已经检查 7169570cc8Sopenharmony_ci size_t len = strlen(processName); 7269570cc8Sopenharmony_ci char shortName[MAX_LEN_SHORT_NAME] = {0}; 7369570cc8Sopenharmony_ci // process short name max length 16 bytes. 7469570cc8Sopenharmony_ci size_t copyLen = len; 7569570cc8Sopenharmony_ci const char *pos = processName; 7669570cc8Sopenharmony_ci if (len >= MAX_LEN_SHORT_NAME) { 7769570cc8Sopenharmony_ci copyLen = MAX_LEN_SHORT_NAME - 1; 7869570cc8Sopenharmony_ci pos += (len - copyLen); 7969570cc8Sopenharmony_ci } 8069570cc8Sopenharmony_ci bool isRet = strncpy_s(shortName, MAX_LEN_SHORT_NAME, pos, copyLen) != EOK; 8169570cc8Sopenharmony_ci APPSPAWN_CHECK(!isRet, return EINVAL, "strncpy_s short name error: %{public}d", errno); 8269570cc8Sopenharmony_ci 8369570cc8Sopenharmony_ci // set short name 8469570cc8Sopenharmony_ci isRet = prctl(PR_SET_NAME, shortName) == -1; 8569570cc8Sopenharmony_ci APPSPAWN_CHECK(!isRet, return errno, "prctl(PR_SET_NAME) error: %{public}d", errno); 8669570cc8Sopenharmony_ci 8769570cc8Sopenharmony_ci // reset longProcName 8869570cc8Sopenharmony_ci isRet = memset_s(content->content.longProcName, 8969570cc8Sopenharmony_ci (size_t)content->content.longProcNameLen, 0, (size_t)content->content.longProcNameLen) != EOK; 9069570cc8Sopenharmony_ci APPSPAWN_CHECK(!isRet, return EINVAL, "Failed to memset long process name"); 9169570cc8Sopenharmony_ci 9269570cc8Sopenharmony_ci // set long process name 9369570cc8Sopenharmony_ci isRet = strncpy_s(content->content.longProcName, content->content.longProcNameLen, processName, len) != EOK; 9469570cc8Sopenharmony_ci APPSPAWN_CHECK(!isRet, return EINVAL, 9569570cc8Sopenharmony_ci "strncpy_s long name error: %{public}d longProcNameLen %{public}u", errno, content->content.longProcNameLen); 9669570cc8Sopenharmony_ci return 0; 9769570cc8Sopenharmony_ci} 9869570cc8Sopenharmony_ci 9969570cc8Sopenharmony_cistatic int SetKeepCapabilities(const AppSpawnMgr *content, const AppSpawningCtx *property) 10069570cc8Sopenharmony_ci{ 10169570cc8Sopenharmony_ci AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO); 10269570cc8Sopenharmony_ci APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE, 10369570cc8Sopenharmony_ci "No tlv %{public}d in msg %{public}s", TLV_DOMAIN_INFO, GetProcessName(property)); 10469570cc8Sopenharmony_ci 10569570cc8Sopenharmony_ci // set keep capabilities when user not root. 10669570cc8Sopenharmony_ci if (dacInfo->uid != 0) { 10769570cc8Sopenharmony_ci bool isRet = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1; 10869570cc8Sopenharmony_ci APPSPAWN_CHECK(!isRet, return errno, "set keepcaps failed: %{public}d", errno); 10969570cc8Sopenharmony_ci } 11069570cc8Sopenharmony_ci return 0; 11169570cc8Sopenharmony_ci} 11269570cc8Sopenharmony_ci 11369570cc8Sopenharmony_cistatic int SetCapabilities(const AppSpawnMgr *content, const AppSpawningCtx *property) 11469570cc8Sopenharmony_ci{ 11569570cc8Sopenharmony_ci // init cap 11669570cc8Sopenharmony_ci struct __user_cap_header_struct capHeader; 11769570cc8Sopenharmony_ci 11869570cc8Sopenharmony_ci bool isRet = memset_s(&capHeader, sizeof(capHeader), 0, sizeof(capHeader)) != EOK; 11969570cc8Sopenharmony_ci APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap header"); 12069570cc8Sopenharmony_ci 12169570cc8Sopenharmony_ci capHeader.version = _LINUX_CAPABILITY_VERSION_3; 12269570cc8Sopenharmony_ci capHeader.pid = 0; 12369570cc8Sopenharmony_ci 12469570cc8Sopenharmony_ci struct __user_cap_data_struct capData[2]; // 2 is data number 12569570cc8Sopenharmony_ci isRet = memset_s(&capData, sizeof(capData), 0, sizeof(capData)) != EOK; 12669570cc8Sopenharmony_ci APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap data"); 12769570cc8Sopenharmony_ci 12869570cc8Sopenharmony_ci // init inheritable permitted effective zero 12969570cc8Sopenharmony_ci#ifdef GRAPHIC_PERMISSION_CHECK 13069570cc8Sopenharmony_ci const uint64_t inheriTable = 0; 13169570cc8Sopenharmony_ci const uint64_t permitted = 0; 13269570cc8Sopenharmony_ci const uint64_t effective = 0; 13369570cc8Sopenharmony_ci#else 13469570cc8Sopenharmony_ci const uint64_t inheriTable = 0x3fffffffff; 13569570cc8Sopenharmony_ci const uint64_t permitted = 0x3fffffffff; 13669570cc8Sopenharmony_ci const uint64_t effective = 0x3fffffffff; 13769570cc8Sopenharmony_ci#endif 13869570cc8Sopenharmony_ci 13969570cc8Sopenharmony_ci capData[0].inheritable = (__u32)(inheriTable); 14069570cc8Sopenharmony_ci capData[1].inheritable = (__u32)(inheriTable >> BITLEN32); 14169570cc8Sopenharmony_ci capData[0].permitted = (__u32)(permitted); 14269570cc8Sopenharmony_ci capData[1].permitted = (__u32)(permitted >> BITLEN32); 14369570cc8Sopenharmony_ci capData[0].effective = (__u32)(effective); 14469570cc8Sopenharmony_ci capData[1].effective = (__u32)(effective >> BITLEN32); 14569570cc8Sopenharmony_ci 14669570cc8Sopenharmony_ci // set capabilities 14769570cc8Sopenharmony_ci isRet = capset(&capHeader, &capData[0]) != 0; 14869570cc8Sopenharmony_ci APPSPAWN_CHECK(!isRet, return -errno, "Failed to capset errno: %{public}d", errno); 14969570cc8Sopenharmony_ci return 0; 15069570cc8Sopenharmony_ci} 15169570cc8Sopenharmony_ci 15269570cc8Sopenharmony_cistatic void InitDebugParams(const AppSpawnMgr *content, const AppSpawningCtx *property) 15369570cc8Sopenharmony_ci{ 15469570cc8Sopenharmony_ci#if defined(__aarch64__) || defined(__x86_64__) 15569570cc8Sopenharmony_ci const char *debugSoPath = "/system/lib64/libhidebug.so"; 15669570cc8Sopenharmony_ci#else 15769570cc8Sopenharmony_ci const char *debugSoPath = "/system/lib/libhidebug.so"; 15869570cc8Sopenharmony_ci#endif 15969570cc8Sopenharmony_ci const char *processName = GetProcessName(property); 16069570cc8Sopenharmony_ci APPSPAWN_CHECK(processName != NULL, return, "Can not get process name"); 16169570cc8Sopenharmony_ci 16269570cc8Sopenharmony_ci bool isRet = access(debugSoPath, F_OK) != 0; 16369570cc8Sopenharmony_ci APPSPAWN_CHECK(!isRet, return, 16469570cc8Sopenharmony_ci "access failed, errno: %{public}d debugSoPath: %{public}s", errno, debugSoPath); 16569570cc8Sopenharmony_ci 16669570cc8Sopenharmony_ci void *handle = dlopen(debugSoPath, RTLD_LAZY); 16769570cc8Sopenharmony_ci APPSPAWN_CHECK(handle != NULL, return, "Failed to dlopen libhidebug.so errno: %{public}s", dlerror()); 16869570cc8Sopenharmony_ci 16969570cc8Sopenharmony_ci bool (*initParam)(const char *name); 17069570cc8Sopenharmony_ci initParam = (bool (*)(const char *name))dlsym(handle, "InitEnvironmentParam"); 17169570cc8Sopenharmony_ci APPSPAWN_CHECK(initParam != NULL, dlclose(handle); 17269570cc8Sopenharmony_ci return, "Failed to dlsym errno: %{public}s", dlerror()); 17369570cc8Sopenharmony_ci (*initParam)(processName); 17469570cc8Sopenharmony_ci dlclose(handle); 17569570cc8Sopenharmony_ci} 17669570cc8Sopenharmony_ci 17769570cc8Sopenharmony_cistatic void ClearEnvironment(const AppSpawnMgr *content, const AppSpawningCtx *property) 17869570cc8Sopenharmony_ci{ 17969570cc8Sopenharmony_ci sigset_t mask; 18069570cc8Sopenharmony_ci sigemptyset(&mask); 18169570cc8Sopenharmony_ci sigaddset(&mask, SIGCHLD); 18269570cc8Sopenharmony_ci sigaddset(&mask, SIGTERM); 18369570cc8Sopenharmony_ci sigprocmask(SIG_UNBLOCK, &mask, NULL); 18469570cc8Sopenharmony_ci // close child fd 18569570cc8Sopenharmony_ci AppSpawningCtx *ctx = (AppSpawningCtx *)property; 18669570cc8Sopenharmony_ci close(ctx->forkCtx.fd[0]); 18769570cc8Sopenharmony_ci ctx->forkCtx.fd[0] = -1; 18869570cc8Sopenharmony_ci return; 18969570cc8Sopenharmony_ci} 19069570cc8Sopenharmony_ci 19169570cc8Sopenharmony_cistatic int SetXpmConfig(const AppSpawnMgr *content, const AppSpawningCtx *property) 19269570cc8Sopenharmony_ci{ 19369570cc8Sopenharmony_ci#ifdef CODE_SIGNATURE_ENABLE 19469570cc8Sopenharmony_ci // nwebspawn no permission set xpm config 19569570cc8Sopenharmony_ci if (IsNWebSpawnMode(content)) { 19669570cc8Sopenharmony_ci return 0; 19769570cc8Sopenharmony_ci } 19869570cc8Sopenharmony_ci 19969570cc8Sopenharmony_ci uint32_t len = 0; 20069570cc8Sopenharmony_ci char *provisionType = GetAppPropertyExt(property, MSG_EXT_NAME_PROVISION_TYPE, &len); 20169570cc8Sopenharmony_ci if (provisionType == NULL || len == 0) { 20269570cc8Sopenharmony_ci APPSPAWN_LOGE("get provision type failed, defaut is %{public}s", PROVISION_TYPE_DEBUG); 20369570cc8Sopenharmony_ci provisionType = PROVISION_TYPE_DEBUG; 20469570cc8Sopenharmony_ci } 20569570cc8Sopenharmony_ci 20669570cc8Sopenharmony_ci AppSpawnMsgOwnerId *ownerInfo = (AppSpawnMsgOwnerId *)GetAppProperty(property, TLV_OWNER_INFO); 20769570cc8Sopenharmony_ci int jitfortEnable = IsJitFortModeOn(property) ? 1 : 0; 20869570cc8Sopenharmony_ci int idType = PROCESS_OWNERID_UNINIT; 20969570cc8Sopenharmony_ci const char *ownerId = NULL; 21069570cc8Sopenharmony_ci if (strcmp(provisionType, PROVISION_TYPE_DEBUG) == 0) { 21169570cc8Sopenharmony_ci idType = PROCESS_OWNERID_DEBUG; 21269570cc8Sopenharmony_ci } else if (ownerInfo == NULL) { 21369570cc8Sopenharmony_ci idType = PROCESS_OWNERID_COMPAT; 21469570cc8Sopenharmony_ci } else if (CheckAppMsgFlagsSet(property, APP_FLAGS_TEMP_JIT)) { 21569570cc8Sopenharmony_ci idType = PROCESS_OWNERID_APP_TEMP_ALLOW; 21669570cc8Sopenharmony_ci ownerId = ownerInfo->ownerId; 21769570cc8Sopenharmony_ci } else { 21869570cc8Sopenharmony_ci idType = PROCESS_OWNERID_APP; 21969570cc8Sopenharmony_ci ownerId = ownerInfo->ownerId; 22069570cc8Sopenharmony_ci } 22169570cc8Sopenharmony_ci int ret = InitXpm(jitfortEnable, idType, ownerId); 22269570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return ret, "set xpm region failed: %{public}d", ret); 22369570cc8Sopenharmony_ci#endif 22469570cc8Sopenharmony_ci return 0; 22569570cc8Sopenharmony_ci} 22669570cc8Sopenharmony_ci 22769570cc8Sopenharmony_cistatic int SetUidGid(const AppSpawnMgr *content, const AppSpawningCtx *property) 22869570cc8Sopenharmony_ci{ 22969570cc8Sopenharmony_ci AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO); 23069570cc8Sopenharmony_ci APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE, 23169570cc8Sopenharmony_ci "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, GetProcessName(property)); 23269570cc8Sopenharmony_ci 23369570cc8Sopenharmony_ci // set gids 23469570cc8Sopenharmony_ci int ret = setgroups(dacInfo->gidCount, (const gid_t *)(&dacInfo->gidTable[0])); 23569570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return errno, 23669570cc8Sopenharmony_ci "setgroups failed: %{public}d, gids.size=%{public}u", errno, dacInfo->gidCount); 23769570cc8Sopenharmony_ci 23869570cc8Sopenharmony_ci // set gid 23969570cc8Sopenharmony_ci if (IsNWebSpawnMode(content)) { 24069570cc8Sopenharmony_ci gid_t gid = dacInfo->gid / UID_BASE; 24169570cc8Sopenharmony_ci if (gid >= 100) { // 100 24269570cc8Sopenharmony_ci APPSPAWN_LOGE("SetUidGid invalid uid for nwebspawn %{public}d", dacInfo->gid); 24369570cc8Sopenharmony_ci return 0; 24469570cc8Sopenharmony_ci } 24569570cc8Sopenharmony_ci ret = setresgid(dacInfo->gid, dacInfo->gid, dacInfo->gid); 24669570cc8Sopenharmony_ci } else { 24769570cc8Sopenharmony_ci ret = setresgid(dacInfo->gid, dacInfo->gid, dacInfo->gid); 24869570cc8Sopenharmony_ci } 24969570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return errno, 25069570cc8Sopenharmony_ci "setgid(%{public}u) failed: %{public}d", dacInfo->gid, errno); 25169570cc8Sopenharmony_ci 25269570cc8Sopenharmony_ci ret = SetSeccompFilter(content, property); 25369570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return ret, "Failed to set setSeccompFilter"); 25469570cc8Sopenharmony_ci 25569570cc8Sopenharmony_ci /* If the effective user ID is changed from 0 to nonzero, 25669570cc8Sopenharmony_ci * then all capabilities are cleared from the effective set 25769570cc8Sopenharmony_ci */ 25869570cc8Sopenharmony_ci ret = setresuid(dacInfo->uid, dacInfo->uid, dacInfo->uid); 25969570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return errno, 26069570cc8Sopenharmony_ci "setuid(%{public}u) failed: %{public}d", dacInfo->uid, errno); 26169570cc8Sopenharmony_ci 26269570cc8Sopenharmony_ci if (CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE) && IsDeveloperModeOn(property)) { 26369570cc8Sopenharmony_ci setenv("HAP_DEBUGGABLE", "true", 1); 26469570cc8Sopenharmony_ci if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { 26569570cc8Sopenharmony_ci APPSPAWN_LOGE("Failed to set app dumpable: %{public}s", strerror(errno)); 26669570cc8Sopenharmony_ci } 26769570cc8Sopenharmony_ci } else { 26869570cc8Sopenharmony_ci setenv("HAP_DEBUGGABLE", "false", 1); 26969570cc8Sopenharmony_ci } 27069570cc8Sopenharmony_ci return 0; 27169570cc8Sopenharmony_ci} 27269570cc8Sopenharmony_ci 27369570cc8Sopenharmony_cistatic int32_t SetFileDescriptors(const AppSpawnMgr *content, const AppSpawningCtx *property) 27469570cc8Sopenharmony_ci{ 27569570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST 27669570cc8Sopenharmony_ci // redirect stdin stdout stderr to /dev/null 27769570cc8Sopenharmony_ci int devNullFd = open(DEVICE_NULL_STR, O_RDWR); 27869570cc8Sopenharmony_ci if (devNullFd == -1) { 27969570cc8Sopenharmony_ci APPSPAWN_LOGE("open dev_null error: %{public}d", errno); 28069570cc8Sopenharmony_ci return (-errno); 28169570cc8Sopenharmony_ci } 28269570cc8Sopenharmony_ci 28369570cc8Sopenharmony_ci // stdin 28469570cc8Sopenharmony_ci if (dup2(devNullFd, STDIN_FILENO) == -1) { 28569570cc8Sopenharmony_ci APPSPAWN_LOGE("dup2 STDIN error: %{public}d", errno); 28669570cc8Sopenharmony_ci return (-errno); 28769570cc8Sopenharmony_ci } 28869570cc8Sopenharmony_ci // stdout 28969570cc8Sopenharmony_ci if (dup2(devNullFd, STDOUT_FILENO) == -1) { 29069570cc8Sopenharmony_ci APPSPAWN_LOGE("dup2 STDOUT error: %{public}d", errno); 29169570cc8Sopenharmony_ci return (-errno); 29269570cc8Sopenharmony_ci } 29369570cc8Sopenharmony_ci // stderr 29469570cc8Sopenharmony_ci if (dup2(devNullFd, STDERR_FILENO) == -1) { 29569570cc8Sopenharmony_ci APPSPAWN_LOGE("dup2 STDERR error: %{public}d", errno); 29669570cc8Sopenharmony_ci return (-errno); 29769570cc8Sopenharmony_ci } 29869570cc8Sopenharmony_ci 29969570cc8Sopenharmony_ci if (devNullFd > STDERR_FILENO) { 30069570cc8Sopenharmony_ci close(devNullFd); 30169570cc8Sopenharmony_ci } 30269570cc8Sopenharmony_ci#endif 30369570cc8Sopenharmony_ci return 0; 30469570cc8Sopenharmony_ci} 30569570cc8Sopenharmony_ci 30669570cc8Sopenharmony_cistatic int32_t CheckTraceStatus(void) 30769570cc8Sopenharmony_ci{ 30869570cc8Sopenharmony_ci int fd = open("/proc/self/status", O_RDONLY); 30969570cc8Sopenharmony_ci APPSPAWN_CHECK(fd >= 0, return errno, "Failed to open /proc/self/status error: %{public}d", errno); 31069570cc8Sopenharmony_ci 31169570cc8Sopenharmony_ci char data[1024] = {0}; // 1024 is data length 31269570cc8Sopenharmony_ci ssize_t dataNum = read(fd, data, sizeof(data) - 1); 31369570cc8Sopenharmony_ci (void)close(fd); 31469570cc8Sopenharmony_ci APPSPAWN_CHECK(dataNum > 0, return -1, "Failed to read file /proc/self/status error: %{public}d", errno); 31569570cc8Sopenharmony_ci 31669570cc8Sopenharmony_ci const char *tracerPid = "TracerPid:\t"; 31769570cc8Sopenharmony_ci data[dataNum] = '\0'; 31869570cc8Sopenharmony_ci char *traceStr = strstr(data, tracerPid); 31969570cc8Sopenharmony_ci APPSPAWN_CHECK(traceStr != NULL, return -1, "Not found %{public}s", tracerPid); 32069570cc8Sopenharmony_ci 32169570cc8Sopenharmony_ci char *separator = strchr(traceStr, '\n'); 32269570cc8Sopenharmony_ci APPSPAWN_CHECK(separator != NULL, return -1, "Not found %{public}s", "\n"); 32369570cc8Sopenharmony_ci 32469570cc8Sopenharmony_ci int len = separator - traceStr - strlen(tracerPid); 32569570cc8Sopenharmony_ci char pid = *(traceStr + strlen(tracerPid)); 32669570cc8Sopenharmony_ci if (len > 1 || pid != '0') { 32769570cc8Sopenharmony_ci return 0; 32869570cc8Sopenharmony_ci } 32969570cc8Sopenharmony_ci return -1; 33069570cc8Sopenharmony_ci} 33169570cc8Sopenharmony_ci 33269570cc8Sopenharmony_cistatic int32_t WaitForDebugger(const AppSpawningCtx *property) 33369570cc8Sopenharmony_ci{ 33469570cc8Sopenharmony_ci // wait for debugger only debugging is required and process is debuggable 33569570cc8Sopenharmony_ci if (CheckAppMsgFlagsSet(property, APP_FLAGS_NATIVEDEBUG) && CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE)) { 33669570cc8Sopenharmony_ci uint32_t count = 0; 33769570cc8Sopenharmony_ci while (CheckTraceStatus() != 0) { 33869570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST 33969570cc8Sopenharmony_ci usleep(1000 * 100); // sleep 1000 * 100 microsecond 34069570cc8Sopenharmony_ci#else 34169570cc8Sopenharmony_ci if (count > 0) { 34269570cc8Sopenharmony_ci break; 34369570cc8Sopenharmony_ci } 34469570cc8Sopenharmony_ci#endif 34569570cc8Sopenharmony_ci count++; 34669570cc8Sopenharmony_ci // remind users to connect to the debugger every 60 * 10 times 34769570cc8Sopenharmony_ci if (count % (10 * 60) == 0) { 34869570cc8Sopenharmony_ci count = 0; 34969570cc8Sopenharmony_ci APPSPAWN_LOGI("wait for debugger, please attach the process"); 35069570cc8Sopenharmony_ci } 35169570cc8Sopenharmony_ci } 35269570cc8Sopenharmony_ci } 35369570cc8Sopenharmony_ci return 0; 35469570cc8Sopenharmony_ci} 35569570cc8Sopenharmony_ci 35669570cc8Sopenharmony_cistatic int SpawnInitSpawningEnv(AppSpawnMgr *content, AppSpawningCtx *property) 35769570cc8Sopenharmony_ci{ 35869570cc8Sopenharmony_ci APPSPAWN_LOGV("Spawning: clear env"); 35969570cc8Sopenharmony_ci int ret = SetProcessName(content, property); 36069570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 36169570cc8Sopenharmony_ci // close socket id and signal for child 36269570cc8Sopenharmony_ci ClearEnvironment(content, property); 36369570cc8Sopenharmony_ci 36469570cc8Sopenharmony_ci ResetParamSecurityLabel(); 36569570cc8Sopenharmony_ci 36669570cc8Sopenharmony_ci ret = SetAppAccessToken(content, property); 36769570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 36869570cc8Sopenharmony_ci return 0; 36969570cc8Sopenharmony_ci} 37069570cc8Sopenharmony_ci 37169570cc8Sopenharmony_cistatic int SpawnSetAppEnv(AppSpawnMgr *content, AppSpawningCtx *property) 37269570cc8Sopenharmony_ci{ 37369570cc8Sopenharmony_ci APPSPAWN_LOGV("Spawning: set appEnv"); 37469570cc8Sopenharmony_ci int ret = SetEnvInfo(content, property); 37569570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 37669570cc8Sopenharmony_ci return 0; 37769570cc8Sopenharmony_ci} 37869570cc8Sopenharmony_ci 37969570cc8Sopenharmony_cistatic int SpawnSetIntPermission(AppSpawnMgr *content, AppSpawningCtx *property) 38069570cc8Sopenharmony_ci{ 38169570cc8Sopenharmony_ci APPSPAWN_LOGV("Spawning: set Internet Permission for app process"); 38269570cc8Sopenharmony_ci int ret = SetInternetPermission(property); 38369570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 38469570cc8Sopenharmony_ci return ret; 38569570cc8Sopenharmony_ci} 38669570cc8Sopenharmony_ci 38769570cc8Sopenharmony_cistatic void SpawnLoadSilk(const AppSpawnMgr *content, const AppSpawningCtx *property) 38869570cc8Sopenharmony_ci{ 38969570cc8Sopenharmony_ci const char *processName = GetBundleName(property); 39069570cc8Sopenharmony_ci APPSPAWN_CHECK(processName != NULL, return, "Can not get bundle name"); 39169570cc8Sopenharmony_ci LoadSilkLibrary(processName); 39269570cc8Sopenharmony_ci} 39369570cc8Sopenharmony_ci 39469570cc8Sopenharmony_cistatic int SpawnSetProperties(AppSpawnMgr *content, AppSpawningCtx *property) 39569570cc8Sopenharmony_ci{ 39669570cc8Sopenharmony_ci APPSPAWN_LOGV("Spawning: set child property"); 39769570cc8Sopenharmony_ci SpawnLoadSilk(content, property); 39869570cc8Sopenharmony_ci (void)umask(DEFAULT_UMASK); 39969570cc8Sopenharmony_ci int ret = SetKeepCapabilities(content, property); 40069570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 40169570cc8Sopenharmony_ci ret = SetXpmConfig(content, property); 40269570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 40369570cc8Sopenharmony_ci 40469570cc8Sopenharmony_ci ret = SetProcessName(content, property); 40569570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 40669570cc8Sopenharmony_ci 40769570cc8Sopenharmony_ci ret = SetUidGid(content, property); 40869570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 40969570cc8Sopenharmony_ci 41069570cc8Sopenharmony_ci ret = SetFileDescriptors(content, property); 41169570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 41269570cc8Sopenharmony_ci 41369570cc8Sopenharmony_ci ret = SetCapabilities(content, property); 41469570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 41569570cc8Sopenharmony_ci 41669570cc8Sopenharmony_ci ret = SetSelinuxCon(content, property) == -1; 41769570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 41869570cc8Sopenharmony_ci 41969570cc8Sopenharmony_ci ret = WaitForDebugger(property); 42069570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 42169570cc8Sopenharmony_ci 42269570cc8Sopenharmony_ci APPSPAWN_ONLY_EXPER(GetAppSpawnMsgType(property) == MSG_SPAWN_NATIVE_PROCESS, return 0); 42369570cc8Sopenharmony_ci#ifdef SECURITY_COMPONENT_ENABLE 42469570cc8Sopenharmony_ci InitSecCompClientEnhance(); 42569570cc8Sopenharmony_ci#endif 42669570cc8Sopenharmony_ci return 0; 42769570cc8Sopenharmony_ci} 42869570cc8Sopenharmony_ci 42969570cc8Sopenharmony_cistatic int PreLoadSetSeccompFilter(AppSpawnMgr *content) 43069570cc8Sopenharmony_ci{ 43169570cc8Sopenharmony_ci // set uid gid filetr 43269570cc8Sopenharmony_ci int ret = SetUidGidFilter(content); 43369570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 43469570cc8Sopenharmony_ci return ret; 43569570cc8Sopenharmony_ci} 43669570cc8Sopenharmony_ci 43769570cc8Sopenharmony_cistatic int SpawnComplete(AppSpawnMgr *content, AppSpawningCtx *property) 43869570cc8Sopenharmony_ci{ 43969570cc8Sopenharmony_ci InitDebugParams(content, property); 44069570cc8Sopenharmony_ci return 0; 44169570cc8Sopenharmony_ci} 44269570cc8Sopenharmony_ci 44369570cc8Sopenharmony_cistatic int CheckEnabled(const char *param, const char *value) 44469570cc8Sopenharmony_ci{ 44569570cc8Sopenharmony_ci char tmp[32] = {0}; // 32 max 44669570cc8Sopenharmony_ci int ret = GetParameter(param, "", tmp, sizeof(tmp)); 44769570cc8Sopenharmony_ci APPSPAWN_LOGV("CheckEnabled key %{public}s ret %{public}d result: %{public}s", param, ret, tmp); 44869570cc8Sopenharmony_ci int enabled = (ret > 0 && strcmp(tmp, value) == 0); 44969570cc8Sopenharmony_ci return enabled; 45069570cc8Sopenharmony_ci} 45169570cc8Sopenharmony_ci 45269570cc8Sopenharmony_cistatic int SpawnGetSpawningFlag(AppSpawnMgr *content, AppSpawningCtx *property) 45369570cc8Sopenharmony_ci{ 45469570cc8Sopenharmony_ci APPSPAWN_LOGV("Spawning: prepare app %{public}s", GetProcessName(property)); 45569570cc8Sopenharmony_ci if (CheckAppMsgFlagsSet(property, APP_FLAGS_COLD_BOOT)) { 45669570cc8Sopenharmony_ci // check cold start 45769570cc8Sopenharmony_ci property->client.flags |= CheckEnabled("startup.appspawn.cold.boot", "true") ? APP_COLD_START : 0; 45869570cc8Sopenharmony_ci } 45969570cc8Sopenharmony_ci if (CheckAppMsgFlagsSet(property, APP_FLAGS_BEGETCTL_BOOT)) { 46069570cc8Sopenharmony_ci // Start app from begetctl for debugging. 46169570cc8Sopenharmony_ci property->client.flags |= APP_BEGETCTL_BOOT; 46269570cc8Sopenharmony_ci APPSPAWN_LOGI("Spawning: prepare app %{public}s, start from begetctl", GetProcessName(property)); 46369570cc8Sopenharmony_ci } 46469570cc8Sopenharmony_ci property->client.flags |= content->flags; 46569570cc8Sopenharmony_ci return 0; 46669570cc8Sopenharmony_ci} 46769570cc8Sopenharmony_ci 46869570cc8Sopenharmony_cistatic int SpawnLoadConfig(AppSpawnMgr *content) 46969570cc8Sopenharmony_ci{ 47069570cc8Sopenharmony_ci LoadSilkConfig(); 47169570cc8Sopenharmony_ci // init flags that will not change until next reboot 47269570cc8Sopenharmony_ci content->flags |= CheckEnabled("const.security.developermode.state", "true") ? APP_DEVELOPER_MODE : 0; 47369570cc8Sopenharmony_ci content->flags |= CheckEnabled("persist.security.jitfort.disabled", "true") ? 0 : APP_JITFORT_MODE; 47469570cc8Sopenharmony_ci return 0; 47569570cc8Sopenharmony_ci} 47669570cc8Sopenharmony_ci 47769570cc8Sopenharmony_cistatic int CloseFdArgs(AppSpawnMgr *content, AppSpawningCtx *property) 47869570cc8Sopenharmony_ci{ 47969570cc8Sopenharmony_ci APPSPAWN_CHECK(property != NULL && property->message != NULL 48069570cc8Sopenharmony_ci && property->message->connection != NULL, 48169570cc8Sopenharmony_ci return -1, "Get connection info failed"); 48269570cc8Sopenharmony_ci int fdCount = property->message->connection->receiverCtx.fdCount; 48369570cc8Sopenharmony_ci int *fds = property->message->connection->receiverCtx.fds; 48469570cc8Sopenharmony_ci if (fds != NULL && fdCount > 0) { 48569570cc8Sopenharmony_ci for (int i = 0; i < fdCount; i++) { 48669570cc8Sopenharmony_ci if (fds[i] > 0) { 48769570cc8Sopenharmony_ci close(fds[i]); 48869570cc8Sopenharmony_ci } 48969570cc8Sopenharmony_ci } 49069570cc8Sopenharmony_ci } 49169570cc8Sopenharmony_ci property->message->connection->receiverCtx.fdCount = 0; 49269570cc8Sopenharmony_ci return 0; 49369570cc8Sopenharmony_ci} 49469570cc8Sopenharmony_ci 49569570cc8Sopenharmony_ciAPPSPAWN_STATIC int SetFdEnv(AppSpawnMgr *content, AppSpawningCtx *property) 49669570cc8Sopenharmony_ci{ 49769570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1); 49869570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(!property->isPrefork, return 0); 49969570cc8Sopenharmony_ci AppSpawnMsgNode *message = property->message; 50069570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL && message->connection != NULL, return -1); 50169570cc8Sopenharmony_ci APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset != NULL, return -1); 50269570cc8Sopenharmony_ci int findFdIndex = 0; 50369570cc8Sopenharmony_ci AppSpawnMsgReceiverCtx recvCtx = message->connection->receiverCtx; 50469570cc8Sopenharmony_ci APPSPAWN_CHECK(recvCtx.fds != NULL && recvCtx.fdCount > 0, return 0, 50569570cc8Sopenharmony_ci "no need set fd info %{public}d, %{public}d", recvCtx.fds != NULL, recvCtx.fdCount); 50669570cc8Sopenharmony_ci char keyBuffer[APP_FDNAME_MAXLEN + sizeof(APP_FDENV_PREFIX)]; 50769570cc8Sopenharmony_ci char value[sizeof(int)]; 50869570cc8Sopenharmony_ci 50969570cc8Sopenharmony_ci for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) { 51069570cc8Sopenharmony_ci if (message->tlvOffset[index] == INVALID_OFFSET) { 51169570cc8Sopenharmony_ci return -1; 51269570cc8Sopenharmony_ci } 51369570cc8Sopenharmony_ci uint8_t *data = message->buffer + message->tlvOffset[index]; 51469570cc8Sopenharmony_ci if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) { 51569570cc8Sopenharmony_ci continue; 51669570cc8Sopenharmony_ci } 51769570cc8Sopenharmony_ci AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data; 51869570cc8Sopenharmony_ci if (strcmp(tlv->tlvName, MSG_EXT_NAME_APP_FD) != 0) { 51969570cc8Sopenharmony_ci continue; 52069570cc8Sopenharmony_ci } 52169570cc8Sopenharmony_ci APPSPAWN_CHECK(findFdIndex < recvCtx.fdCount && recvCtx.fds[findFdIndex] > 0, return -1, 52269570cc8Sopenharmony_ci "check set env args failed %{public}d, %{public}d, %{public}d", 52369570cc8Sopenharmony_ci findFdIndex, recvCtx.fdCount, recvCtx.fds[findFdIndex]); 52469570cc8Sopenharmony_ci APPSPAWN_CHECK(snprintf_s(keyBuffer, sizeof(keyBuffer), sizeof(keyBuffer) - 1, APP_FDENV_PREFIX"%s", 52569570cc8Sopenharmony_ci data + sizeof(AppSpawnTlvExt)) >= 0, return -1, "failed print env key %{public}d", errno); 52669570cc8Sopenharmony_ci APPSPAWN_CHECK(snprintf_s(value, sizeof(value), sizeof(value) - 1, 52769570cc8Sopenharmony_ci "%d", recvCtx.fds[findFdIndex++]) >= 0, return -1, "failed print env key %{public}d", errno); 52869570cc8Sopenharmony_ci int ret = setenv(keyBuffer, value, 1); 52969570cc8Sopenharmony_ci APPSPAWN_CHECK(ret == 0, return -1, "failed setenv %{public}s, %{public}s", keyBuffer, value); 53069570cc8Sopenharmony_ci if (findFdIndex >= recvCtx.fdCount) { 53169570cc8Sopenharmony_ci break; 53269570cc8Sopenharmony_ci } 53369570cc8Sopenharmony_ci } 53469570cc8Sopenharmony_ci return 0; 53569570cc8Sopenharmony_ci} 53669570cc8Sopenharmony_ci 53769570cc8Sopenharmony_ciMODULE_CONSTRUCTOR(void) 53869570cc8Sopenharmony_ci{ 53969570cc8Sopenharmony_ci APPSPAWN_LOGV("Load common module ..."); 54069570cc8Sopenharmony_ci AddPreloadHook(HOOK_PRIO_COMMON, PreLoadSetSeccompFilter); 54169570cc8Sopenharmony_ci AddPreloadHook(HOOK_PRIO_COMMON, SpawnLoadConfig); 54269570cc8Sopenharmony_ci 54369570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_HIGHEST, SpawnGetSpawningFlag); 54469570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SpawnInitSpawningEnv); 54569570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON + 1, SpawnSetAppEnv); 54669570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_HIGHEST, SpawnSetIntPermission); 54769570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_PROPERTY, SpawnSetProperties); 54869570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_CHILD_POST_RELY, HOOK_PRIO_HIGHEST, SpawnComplete); 54969570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_PARENT_POST_FORK, HOOK_PRIO_HIGHEST, CloseFdArgs); 55069570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SetFdEnv); 55169570cc8Sopenharmony_ci} 552