1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "appspawn_adapter.h" 17 18#include "access_token.h" 19#include "appspawn_hook.h" 20#include "appspawn_manager.h" 21#include "appspawn_utils.h" 22#include "cJSON.h" 23#include "token_setproc.h" 24#include "tokenid_kit.h" 25#include "securec.h" 26 27#ifdef WITH_SELINUX 28#include "hap_restorecon.h" 29#include "selinux/selinux.h" 30#endif 31#ifdef WITH_SECCOMP 32#include "seccomp_policy.h" 33#include <sys/prctl.h> 34#ifdef SECCOMP_PRIVILEGE 35#include <dlfcn.h> 36#define GET_ALL_PROCESSES "ohos.permission.GET_ALL_PROCESSES" 37#define GET_PERMISSION_INDEX "GetPermissionIndex" 38using GetPermissionFunc = int32_t (*)(void *, const char *); 39#endif 40#endif 41#define MSG_EXT_NAME_PROCESS_TYPE "ProcessType" 42#define NWEBSPAWN_SERVER_NAME "nwebspawn" 43#define MAX_USERID_LEN 32 44using namespace OHOS::Security::AccessToken; 45 46int SetAppAccessToken(const AppSpawnMgr *content, const AppSpawningCtx *property) 47{ 48 int32_t ret = 0; 49 uint64_t tokenId = 0; 50 AppSpawnMsgAccessToken *tokenInfo = 51 reinterpret_cast<AppSpawnMsgAccessToken *>(GetAppProperty(property, TLV_ACCESS_TOKEN_INFO)); 52 APPSPAWN_CHECK(tokenInfo != NULL, return APPSPAWN_MSG_INVALID, 53 "No access token in msg %{public}s", GetProcessName(property)); 54 55 if (IsNWebSpawnMode(content) || IsIsolatedNativeSpawnMode(content, property)) { 56 TokenIdKit tokenIdKit; 57 tokenId = tokenIdKit.GetRenderTokenID(tokenInfo->accessTokenIdEx); 58 } else { 59 tokenId = tokenInfo->accessTokenIdEx; 60 } 61 ret = SetSelfTokenID(tokenId); 62 APPSPAWN_CHECK(ret == 0, return APPSPAWN_ACCESS_TOKEN_INVALID, 63 "set access token id failed, ret: %{public}d %{public}s", ret, GetProcessName(property)); 64 APPSPAWN_LOGV("SetAppAccessToken success for %{public}s", GetProcessName(property)); 65 return 0; 66} 67 68int SetSelinuxConNweb(const AppSpawnMgr *content, const AppSpawningCtx *property) 69{ 70#if defined(WITH_SELINUX) && !defined(APPSPAWN_TEST) 71 uint32_t len = 0; 72 std::string processType = 73 reinterpret_cast<char *>(GetAppPropertyExt(property, MSG_EXT_NAME_PROCESS_TYPE, &len)); 74 int32_t ret; 75 if (processType == "render") { 76 ret = setcon("u:r:isolated_render:s0"); 77 } else { 78 ret = setcon("u:r:isolated_gpu:s0"); 79 } 80 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Setcon failed, errno: %{public}d", errno); 81#endif 82 return 0; 83} 84 85int SetSelinuxCon(const AppSpawnMgr *content, const AppSpawningCtx *property) 86{ 87#ifdef WITH_SELINUX 88 APPSPAWN_LOGV("SetSelinuxCon IsDeveloperModeOn %{public}d", IsDeveloperModeOn(property)); 89 if (GetAppSpawnMsgType(property) == MSG_SPAWN_NATIVE_PROCESS) { 90 if (!IsDeveloperModeOn(property)) { 91 APPSPAWN_LOGE("Denied Launching a native process: not in developer mode"); 92 return APPSPAWN_NATIVE_NOT_SUPPORT; 93 } 94 return 0; 95 } 96 if (IsNWebSpawnMode(content)) { 97#ifndef APPSPAWN_TEST 98 return SetSelinuxConNweb(content, property); 99#else 100 return 0; 101#endif 102 } else if (IsIsolatedNativeSpawnMode(content, property)) { 103 return setcon("u:r:isolated_render:s0"); 104 } 105 AppSpawnMsgDomainInfo *msgDomainInfo = 106 reinterpret_cast<AppSpawnMsgDomainInfo *>(GetAppProperty(property, TLV_DOMAIN_INFO)); 107 APPSPAWN_CHECK(msgDomainInfo != NULL, return APPSPAWN_TLV_NONE, 108 "No domain info in req form %{public}s", GetProcessName(property)); 109 HapContext hapContext; 110 HapDomainInfo hapDomainInfo; 111 hapDomainInfo.apl = msgDomainInfo->apl; 112 hapDomainInfo.packageName = GetBundleName(property); 113 hapDomainInfo.hapFlags = msgDomainInfo->hapFlags; 114 if (CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE)) { 115 hapDomainInfo.hapFlags |= SELINUX_HAP_DEBUGGABLE; 116 } 117 if (CheckAppMsgFlagsSet(property, APP_FLAGS_DLP_MANAGER)) { 118 hapDomainInfo.hapFlags |= SELINUX_HAP_DLP; 119 } 120 if (CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX)) { 121 hapDomainInfo.hapFlags |= SELINUX_HAP_INPUT_ISOLATE; 122 } 123 int32_t ret = hapContext.HapDomainSetcontext(hapDomainInfo); 124 if (CheckAppMsgFlagsSet(property, APP_FLAGS_ASANENABLED)) { 125 ret = 0; 126 } 127 APPSPAWN_CHECK(ret == 0, return APPSPAWN_ACCESS_TOKEN_INVALID, 128 "Set domain context failed, ret: %{public}d %{public}s", ret, GetProcessName(property)); 129 APPSPAWN_LOGV("SetSelinuxCon success for %{public}s", GetProcessName(property)); 130#endif 131 return 0; 132} 133 134int SetUidGidFilter(const AppSpawnMgr *content) 135{ 136#ifdef WITH_SECCOMP 137 bool ret = false; 138 if (IsNWebSpawnMode(content)) { 139 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 140 APPSPAWN_LOGE("Failed to set no new privs"); 141 } 142 ret = SetSeccompPolicyWithName(INDIVIDUAL, NWEBSPAWN_NAME); 143 } else { 144#ifdef SECCOMP_PRIVILEGE 145 if (IsDeveloperModeOpen()) { 146 return 0; 147 } 148#endif 149 ret = SetSeccompPolicyWithName(INDIVIDUAL, APPSPAWN_NAME); 150 } 151 if (!ret) { 152 APPSPAWN_LOGE("Failed to set APPSPAWN seccomp filter and exit"); 153 _exit(0x7f); 154 } 155 APPSPAWN_LOGV("SetUidGidFilter success"); 156#endif 157 return 0; 158} 159 160int SetSeccompFilter(const AppSpawnMgr *content, const AppSpawningCtx *property) 161{ 162#ifdef WITH_SECCOMP 163 APPSPAWN_CHECK(property != nullptr, return 0, "property is NULL"); 164 const char *appName = APP_NAME; 165 SeccompFilterType type = APP; 166 167 if (IsNWebSpawnMode(content)) { 168 uint32_t len = 0; 169 std::string processType = 170 reinterpret_cast<char *>(GetAppPropertyExt(property, MSG_EXT_NAME_PROCESS_TYPE, &len)); 171 if (processType == "render") { 172 return 0; 173 } 174 } 175 176#ifdef SECCOMP_PRIVILEGE 177 if (IsDeveloperModeOpen()) { 178 static GetPermissionFunc getPermissionFuncPtr = nullptr; 179 if (getPermissionFuncPtr == nullptr) { 180 getPermissionFuncPtr = reinterpret_cast<GetPermissionFunc>(dlsym(nullptr, GET_PERMISSION_INDEX)); 181 if (getPermissionFuncPtr == nullptr) { 182 APPSPAWN_LOGE("Failed to dlsym get permission errno is %{public}d", errno); 183 return -EINVAL; 184 } 185 } 186 int32_t index = getPermissionFuncPtr(nullptr, GET_ALL_PROCESSES); 187 if (CheckAppPermissionFlagSet(property, static_cast<uint32_t>(index)) != 0) { 188 appName = APP_PRIVILEGE; 189 } 190 } 191#endif 192 193 if (CheckAppSpawnMsgFlag(property->message, TLV_MSG_FLAGS, APP_FLAGS_ISOLATED_SANDBOX) != 0) { 194 appName = IMF_EXTENTOIN_NAME; 195 } 196 197 if (!SetSeccompPolicyWithName(type, appName)) { 198 APPSPAWN_LOGE("Failed to set %{public}s seccomp filter and exit %{public}d", appName, errno); 199 return -EINVAL; 200 } 201 APPSPAWN_LOGV("SetSeccompFilter success for %{public}s", GetProcessName(property)); 202#endif 203 return 0; 204} 205 206int SetInternetPermission(const AppSpawningCtx *property) 207{ 208 AppSpawnMsgInternetInfo *info = 209 reinterpret_cast<AppSpawnMsgInternetInfo *>(GetAppProperty(property, TLV_INTERNET_INFO)); 210 APPSPAWN_CHECK(info != NULL, return 0, 211 "No tlv internet permission info in req form %{public}s", GetProcessName(property)); 212 APPSPAWN_LOGV("Set internet permission %{public}d %{public}d", info->setAllowInternet, info->allowInternet); 213 if (info->setAllowInternet == 1 && info->allowInternet == 0) { 214 DisallowInternet(); 215 } 216 return 0; 217} 218 219void InitAppCommonEnv(const AppSpawningCtx *property) 220{ 221 AppDacInfo *appInfo = reinterpret_cast<AppDacInfo *>(GetAppProperty(property, TLV_DAC_INFO)); 222 if (appInfo == NULL) { 223 return; 224 } 225 const uint32_t userId = appInfo->uid / UID_BASE; 226 char user[MAX_USERID_LEN] = {0}; 227 int len = sprintf_s(user, MAX_USERID_LEN, "%u", userId); 228 APPSPAWN_CHECK(len > 0, return, "Failed to format userid: %{public}u", userId); 229 int ret = setenv("USER", user, 1); 230 APPSPAWN_CHECK(ret == 0, return, "setenv failed, userid:%{public}u, errno: %{public}d", userId, errno); 231} 232 233int32_t SetEnvInfo(const AppSpawnMgr *content, const AppSpawningCtx *property) 234{ 235 InitAppCommonEnv(property); 236 237 uint32_t size = 0; 238 char *envStr = reinterpret_cast<char *>(GetAppPropertyExt(property, "AppEnv", &size)); 239 if (size == 0 || envStr == NULL) { 240 return 0; 241 } 242 int ret = 0; 243 cJSON *root = cJSON_Parse(envStr); 244 APPSPAWN_CHECK(root != nullptr, return -1, "SetEnvInfo: json parse failed %{public}s", envStr); 245 cJSON *config = nullptr; 246 cJSON_ArrayForEach(config, root) { 247 const char *name = config->string; 248 const char *value = cJSON_GetStringValue(config); 249 APPSPAWN_LOGV("SetEnvInfo name: %{public}s value: %{public}s", name, value); 250 ret = setenv(name, value, 1); 251 APPSPAWN_CHECK(ret == 0, break, "setenv failed, errno: %{public}d", errno); 252 } 253 cJSON_Delete(root); 254 APPSPAWN_LOGV("SetEnvInfo success"); 255 return ret; 256} 257