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
1669570cc8Sopenharmony_ci#include "appspawn_adapter.h"
1769570cc8Sopenharmony_ci
1869570cc8Sopenharmony_ci#include "access_token.h"
1969570cc8Sopenharmony_ci#include "appspawn_hook.h"
2069570cc8Sopenharmony_ci#include "appspawn_manager.h"
2169570cc8Sopenharmony_ci#include "appspawn_utils.h"
2269570cc8Sopenharmony_ci#include "cJSON.h"
2369570cc8Sopenharmony_ci#include "token_setproc.h"
2469570cc8Sopenharmony_ci#include "tokenid_kit.h"
2569570cc8Sopenharmony_ci#include "securec.h"
2669570cc8Sopenharmony_ci
2769570cc8Sopenharmony_ci#ifdef WITH_SELINUX
2869570cc8Sopenharmony_ci#include "hap_restorecon.h"
2969570cc8Sopenharmony_ci#include "selinux/selinux.h"
3069570cc8Sopenharmony_ci#endif
3169570cc8Sopenharmony_ci#ifdef WITH_SECCOMP
3269570cc8Sopenharmony_ci#include "seccomp_policy.h"
3369570cc8Sopenharmony_ci#include <sys/prctl.h>
3469570cc8Sopenharmony_ci#ifdef SECCOMP_PRIVILEGE
3569570cc8Sopenharmony_ci#include <dlfcn.h>
3669570cc8Sopenharmony_ci#define GET_ALL_PROCESSES "ohos.permission.GET_ALL_PROCESSES"
3769570cc8Sopenharmony_ci#define GET_PERMISSION_INDEX "GetPermissionIndex"
3869570cc8Sopenharmony_ciusing GetPermissionFunc = int32_t (*)(void *, const char *);
3969570cc8Sopenharmony_ci#endif
4069570cc8Sopenharmony_ci#endif
4169570cc8Sopenharmony_ci#define MSG_EXT_NAME_PROCESS_TYPE "ProcessType"
4269570cc8Sopenharmony_ci#define NWEBSPAWN_SERVER_NAME "nwebspawn"
4369570cc8Sopenharmony_ci#define MAX_USERID_LEN  32
4469570cc8Sopenharmony_ciusing namespace OHOS::Security::AccessToken;
4569570cc8Sopenharmony_ci
4669570cc8Sopenharmony_ciint SetAppAccessToken(const AppSpawnMgr *content, const AppSpawningCtx *property)
4769570cc8Sopenharmony_ci{
4869570cc8Sopenharmony_ci    int32_t ret = 0;
4969570cc8Sopenharmony_ci    uint64_t tokenId = 0;
5069570cc8Sopenharmony_ci    AppSpawnMsgAccessToken *tokenInfo =
5169570cc8Sopenharmony_ci        reinterpret_cast<AppSpawnMsgAccessToken *>(GetAppProperty(property, TLV_ACCESS_TOKEN_INFO));
5269570cc8Sopenharmony_ci    APPSPAWN_CHECK(tokenInfo != NULL, return APPSPAWN_MSG_INVALID,
5369570cc8Sopenharmony_ci        "No access token in msg %{public}s", GetProcessName(property));
5469570cc8Sopenharmony_ci
5569570cc8Sopenharmony_ci    if (IsNWebSpawnMode(content) || IsIsolatedNativeSpawnMode(content, property)) {
5669570cc8Sopenharmony_ci        TokenIdKit tokenIdKit;
5769570cc8Sopenharmony_ci        tokenId = tokenIdKit.GetRenderTokenID(tokenInfo->accessTokenIdEx);
5869570cc8Sopenharmony_ci    } else {
5969570cc8Sopenharmony_ci        tokenId = tokenInfo->accessTokenIdEx;
6069570cc8Sopenharmony_ci    }
6169570cc8Sopenharmony_ci    ret = SetSelfTokenID(tokenId);
6269570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return APPSPAWN_ACCESS_TOKEN_INVALID,
6369570cc8Sopenharmony_ci        "set access token id failed, ret: %{public}d %{public}s", ret, GetProcessName(property));
6469570cc8Sopenharmony_ci    APPSPAWN_LOGV("SetAppAccessToken success for %{public}s", GetProcessName(property));
6569570cc8Sopenharmony_ci    return 0;
6669570cc8Sopenharmony_ci}
6769570cc8Sopenharmony_ci
6869570cc8Sopenharmony_ciint SetSelinuxConNweb(const AppSpawnMgr *content, const AppSpawningCtx *property)
6969570cc8Sopenharmony_ci{
7069570cc8Sopenharmony_ci#if defined(WITH_SELINUX) && !defined(APPSPAWN_TEST)
7169570cc8Sopenharmony_ci    uint32_t len = 0;
7269570cc8Sopenharmony_ci    std::string processType =
7369570cc8Sopenharmony_ci        reinterpret_cast<char *>(GetAppPropertyExt(property, MSG_EXT_NAME_PROCESS_TYPE, &len));
7469570cc8Sopenharmony_ci    int32_t ret;
7569570cc8Sopenharmony_ci    if (processType == "render") {
7669570cc8Sopenharmony_ci        ret = setcon("u:r:isolated_render:s0");
7769570cc8Sopenharmony_ci    } else {
7869570cc8Sopenharmony_ci        ret = setcon("u:r:isolated_gpu:s0");
7969570cc8Sopenharmony_ci    }
8069570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Setcon failed, errno: %{public}d", errno);
8169570cc8Sopenharmony_ci#endif
8269570cc8Sopenharmony_ci    return 0;
8369570cc8Sopenharmony_ci}
8469570cc8Sopenharmony_ci
8569570cc8Sopenharmony_ciint SetSelinuxCon(const AppSpawnMgr *content, const AppSpawningCtx *property)
8669570cc8Sopenharmony_ci{
8769570cc8Sopenharmony_ci#ifdef WITH_SELINUX
8869570cc8Sopenharmony_ci    APPSPAWN_LOGV("SetSelinuxCon IsDeveloperModeOn %{public}d", IsDeveloperModeOn(property));
8969570cc8Sopenharmony_ci    if (GetAppSpawnMsgType(property) == MSG_SPAWN_NATIVE_PROCESS) {
9069570cc8Sopenharmony_ci        if (!IsDeveloperModeOn(property)) {
9169570cc8Sopenharmony_ci            APPSPAWN_LOGE("Denied Launching a native process: not in developer mode");
9269570cc8Sopenharmony_ci            return APPSPAWN_NATIVE_NOT_SUPPORT;
9369570cc8Sopenharmony_ci        }
9469570cc8Sopenharmony_ci        return 0;
9569570cc8Sopenharmony_ci    }
9669570cc8Sopenharmony_ci    if (IsNWebSpawnMode(content)) {
9769570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST
9869570cc8Sopenharmony_ci        return SetSelinuxConNweb(content, property);
9969570cc8Sopenharmony_ci#else
10069570cc8Sopenharmony_ci        return 0;
10169570cc8Sopenharmony_ci#endif
10269570cc8Sopenharmony_ci    } else if (IsIsolatedNativeSpawnMode(content, property)) {
10369570cc8Sopenharmony_ci        return setcon("u:r:isolated_render:s0");
10469570cc8Sopenharmony_ci    }
10569570cc8Sopenharmony_ci    AppSpawnMsgDomainInfo *msgDomainInfo =
10669570cc8Sopenharmony_ci        reinterpret_cast<AppSpawnMsgDomainInfo *>(GetAppProperty(property, TLV_DOMAIN_INFO));
10769570cc8Sopenharmony_ci    APPSPAWN_CHECK(msgDomainInfo != NULL, return APPSPAWN_TLV_NONE,
10869570cc8Sopenharmony_ci        "No domain info in req form %{public}s", GetProcessName(property));
10969570cc8Sopenharmony_ci    HapContext hapContext;
11069570cc8Sopenharmony_ci    HapDomainInfo hapDomainInfo;
11169570cc8Sopenharmony_ci    hapDomainInfo.apl = msgDomainInfo->apl;
11269570cc8Sopenharmony_ci    hapDomainInfo.packageName = GetBundleName(property);
11369570cc8Sopenharmony_ci    hapDomainInfo.hapFlags = msgDomainInfo->hapFlags;
11469570cc8Sopenharmony_ci    if (CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE)) {
11569570cc8Sopenharmony_ci        hapDomainInfo.hapFlags |= SELINUX_HAP_DEBUGGABLE;
11669570cc8Sopenharmony_ci    }
11769570cc8Sopenharmony_ci    if (CheckAppMsgFlagsSet(property, APP_FLAGS_DLP_MANAGER)) {
11869570cc8Sopenharmony_ci        hapDomainInfo.hapFlags |= SELINUX_HAP_DLP;
11969570cc8Sopenharmony_ci    }
12069570cc8Sopenharmony_ci    if (CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX)) {
12169570cc8Sopenharmony_ci        hapDomainInfo.hapFlags |= SELINUX_HAP_INPUT_ISOLATE;
12269570cc8Sopenharmony_ci    }
12369570cc8Sopenharmony_ci    int32_t ret = hapContext.HapDomainSetcontext(hapDomainInfo);
12469570cc8Sopenharmony_ci    if (CheckAppMsgFlagsSet(property, APP_FLAGS_ASANENABLED)) {
12569570cc8Sopenharmony_ci        ret = 0;
12669570cc8Sopenharmony_ci    }
12769570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return APPSPAWN_ACCESS_TOKEN_INVALID,
12869570cc8Sopenharmony_ci        "Set domain context failed, ret: %{public}d %{public}s", ret, GetProcessName(property));
12969570cc8Sopenharmony_ci    APPSPAWN_LOGV("SetSelinuxCon success for %{public}s", GetProcessName(property));
13069570cc8Sopenharmony_ci#endif
13169570cc8Sopenharmony_ci    return 0;
13269570cc8Sopenharmony_ci}
13369570cc8Sopenharmony_ci
13469570cc8Sopenharmony_ciint SetUidGidFilter(const AppSpawnMgr *content)
13569570cc8Sopenharmony_ci{
13669570cc8Sopenharmony_ci#ifdef WITH_SECCOMP
13769570cc8Sopenharmony_ci    bool ret = false;
13869570cc8Sopenharmony_ci    if (IsNWebSpawnMode(content)) {
13969570cc8Sopenharmony_ci        if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
14069570cc8Sopenharmony_ci            APPSPAWN_LOGE("Failed to set no new privs");
14169570cc8Sopenharmony_ci        }
14269570cc8Sopenharmony_ci        ret = SetSeccompPolicyWithName(INDIVIDUAL, NWEBSPAWN_NAME);
14369570cc8Sopenharmony_ci    } else {
14469570cc8Sopenharmony_ci#ifdef SECCOMP_PRIVILEGE
14569570cc8Sopenharmony_ci        if (IsDeveloperModeOpen()) {
14669570cc8Sopenharmony_ci            return 0;
14769570cc8Sopenharmony_ci        }
14869570cc8Sopenharmony_ci#endif
14969570cc8Sopenharmony_ci        ret = SetSeccompPolicyWithName(INDIVIDUAL, APPSPAWN_NAME);
15069570cc8Sopenharmony_ci    }
15169570cc8Sopenharmony_ci    if (!ret) {
15269570cc8Sopenharmony_ci        APPSPAWN_LOGE("Failed to set APPSPAWN seccomp filter and exit");
15369570cc8Sopenharmony_ci        _exit(0x7f);
15469570cc8Sopenharmony_ci    }
15569570cc8Sopenharmony_ci    APPSPAWN_LOGV("SetUidGidFilter success");
15669570cc8Sopenharmony_ci#endif
15769570cc8Sopenharmony_ci    return 0;
15869570cc8Sopenharmony_ci}
15969570cc8Sopenharmony_ci
16069570cc8Sopenharmony_ciint SetSeccompFilter(const AppSpawnMgr *content, const AppSpawningCtx *property)
16169570cc8Sopenharmony_ci{
16269570cc8Sopenharmony_ci#ifdef WITH_SECCOMP
16369570cc8Sopenharmony_ci    APPSPAWN_CHECK(property != nullptr, return 0, "property is NULL");
16469570cc8Sopenharmony_ci    const char *appName = APP_NAME;
16569570cc8Sopenharmony_ci    SeccompFilterType type = APP;
16669570cc8Sopenharmony_ci
16769570cc8Sopenharmony_ci    if (IsNWebSpawnMode(content)) {
16869570cc8Sopenharmony_ci        uint32_t len = 0;
16969570cc8Sopenharmony_ci        std::string processType =
17069570cc8Sopenharmony_ci            reinterpret_cast<char *>(GetAppPropertyExt(property, MSG_EXT_NAME_PROCESS_TYPE, &len));
17169570cc8Sopenharmony_ci        if (processType == "render") {
17269570cc8Sopenharmony_ci            return 0;
17369570cc8Sopenharmony_ci        }
17469570cc8Sopenharmony_ci    }
17569570cc8Sopenharmony_ci
17669570cc8Sopenharmony_ci#ifdef SECCOMP_PRIVILEGE
17769570cc8Sopenharmony_ci    if (IsDeveloperModeOpen()) {
17869570cc8Sopenharmony_ci        static GetPermissionFunc getPermissionFuncPtr = nullptr;
17969570cc8Sopenharmony_ci        if (getPermissionFuncPtr == nullptr) {
18069570cc8Sopenharmony_ci            getPermissionFuncPtr = reinterpret_cast<GetPermissionFunc>(dlsym(nullptr, GET_PERMISSION_INDEX));
18169570cc8Sopenharmony_ci            if (getPermissionFuncPtr == nullptr) {
18269570cc8Sopenharmony_ci                APPSPAWN_LOGE("Failed to dlsym get permission errno is %{public}d", errno);
18369570cc8Sopenharmony_ci                return -EINVAL;
18469570cc8Sopenharmony_ci            }
18569570cc8Sopenharmony_ci        }
18669570cc8Sopenharmony_ci        int32_t index = getPermissionFuncPtr(nullptr, GET_ALL_PROCESSES);
18769570cc8Sopenharmony_ci        if (CheckAppPermissionFlagSet(property, static_cast<uint32_t>(index)) != 0) {
18869570cc8Sopenharmony_ci            appName = APP_PRIVILEGE;
18969570cc8Sopenharmony_ci        }
19069570cc8Sopenharmony_ci    }
19169570cc8Sopenharmony_ci#endif
19269570cc8Sopenharmony_ci
19369570cc8Sopenharmony_ci    if (CheckAppSpawnMsgFlag(property->message, TLV_MSG_FLAGS, APP_FLAGS_ISOLATED_SANDBOX) != 0) {
19469570cc8Sopenharmony_ci        appName = IMF_EXTENTOIN_NAME;
19569570cc8Sopenharmony_ci    }
19669570cc8Sopenharmony_ci
19769570cc8Sopenharmony_ci    if (!SetSeccompPolicyWithName(type, appName)) {
19869570cc8Sopenharmony_ci        APPSPAWN_LOGE("Failed to set %{public}s seccomp filter and exit %{public}d", appName, errno);
19969570cc8Sopenharmony_ci        return -EINVAL;
20069570cc8Sopenharmony_ci    }
20169570cc8Sopenharmony_ci    APPSPAWN_LOGV("SetSeccompFilter success for %{public}s", GetProcessName(property));
20269570cc8Sopenharmony_ci#endif
20369570cc8Sopenharmony_ci    return 0;
20469570cc8Sopenharmony_ci}
20569570cc8Sopenharmony_ci
20669570cc8Sopenharmony_ciint SetInternetPermission(const AppSpawningCtx *property)
20769570cc8Sopenharmony_ci{
20869570cc8Sopenharmony_ci    AppSpawnMsgInternetInfo *info =
20969570cc8Sopenharmony_ci        reinterpret_cast<AppSpawnMsgInternetInfo *>(GetAppProperty(property, TLV_INTERNET_INFO));
21069570cc8Sopenharmony_ci    APPSPAWN_CHECK(info != NULL, return 0,
21169570cc8Sopenharmony_ci        "No tlv internet permission info in req form %{public}s", GetProcessName(property));
21269570cc8Sopenharmony_ci    APPSPAWN_LOGV("Set internet permission %{public}d %{public}d", info->setAllowInternet, info->allowInternet);
21369570cc8Sopenharmony_ci    if (info->setAllowInternet == 1 && info->allowInternet == 0) {
21469570cc8Sopenharmony_ci        DisallowInternet();
21569570cc8Sopenharmony_ci    }
21669570cc8Sopenharmony_ci    return 0;
21769570cc8Sopenharmony_ci}
21869570cc8Sopenharmony_ci
21969570cc8Sopenharmony_civoid InitAppCommonEnv(const AppSpawningCtx *property)
22069570cc8Sopenharmony_ci{
22169570cc8Sopenharmony_ci    AppDacInfo *appInfo = reinterpret_cast<AppDacInfo *>(GetAppProperty(property, TLV_DAC_INFO));
22269570cc8Sopenharmony_ci    if (appInfo == NULL) {
22369570cc8Sopenharmony_ci        return;
22469570cc8Sopenharmony_ci    }
22569570cc8Sopenharmony_ci    const uint32_t userId = appInfo->uid / UID_BASE;
22669570cc8Sopenharmony_ci    char user[MAX_USERID_LEN] = {0};
22769570cc8Sopenharmony_ci    int len = sprintf_s(user, MAX_USERID_LEN, "%u", userId);
22869570cc8Sopenharmony_ci    APPSPAWN_CHECK(len > 0, return, "Failed to format userid: %{public}u", userId);
22969570cc8Sopenharmony_ci    int ret = setenv("USER", user, 1);
23069570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return, "setenv failed, userid:%{public}u, errno: %{public}d", userId, errno);
23169570cc8Sopenharmony_ci}
23269570cc8Sopenharmony_ci
23369570cc8Sopenharmony_ciint32_t SetEnvInfo(const AppSpawnMgr *content, const AppSpawningCtx *property)
23469570cc8Sopenharmony_ci{
23569570cc8Sopenharmony_ci    InitAppCommonEnv(property);
23669570cc8Sopenharmony_ci
23769570cc8Sopenharmony_ci    uint32_t size = 0;
23869570cc8Sopenharmony_ci    char *envStr = reinterpret_cast<char *>(GetAppPropertyExt(property, "AppEnv", &size));
23969570cc8Sopenharmony_ci    if (size == 0 || envStr == NULL) {
24069570cc8Sopenharmony_ci        return 0;
24169570cc8Sopenharmony_ci    }
24269570cc8Sopenharmony_ci    int ret = 0;
24369570cc8Sopenharmony_ci    cJSON *root = cJSON_Parse(envStr);
24469570cc8Sopenharmony_ci    APPSPAWN_CHECK(root != nullptr, return -1, "SetEnvInfo: json parse failed %{public}s", envStr);
24569570cc8Sopenharmony_ci    cJSON *config = nullptr;
24669570cc8Sopenharmony_ci    cJSON_ArrayForEach(config, root) {
24769570cc8Sopenharmony_ci        const char *name = config->string;
24869570cc8Sopenharmony_ci        const char *value = cJSON_GetStringValue(config);
24969570cc8Sopenharmony_ci        APPSPAWN_LOGV("SetEnvInfo name: %{public}s value: %{public}s", name, value);
25069570cc8Sopenharmony_ci        ret = setenv(name, value, 1);
25169570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, break, "setenv failed, errno: %{public}d", errno);
25269570cc8Sopenharmony_ci    }
25369570cc8Sopenharmony_ci    cJSON_Delete(root);
25469570cc8Sopenharmony_ci    APPSPAWN_LOGV("SetEnvInfo success");
25569570cc8Sopenharmony_ci    return ret;
25669570cc8Sopenharmony_ci}
257