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