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