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_manager.h" 17#include "appspawn_sandbox.h" 18#include "appspawn_utils.h" 19#include "modulemgr.h" 20#include "parameter.h" 21#include "securec.h" 22 23struct ListNode g_sandboxVarList = {&g_sandboxVarList, &g_sandboxVarList}; 24 25static int VarPackageNameIndexReplace(const SandboxContext *context, 26 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData) 27{ 28 AppSpawnMsgBundleInfo *bundleInfo = ( 29 AppSpawnMsgBundleInfo *)GetSpawningMsgInfo(context, TLV_BUNDLE_INFO); 30 APPSPAWN_CHECK(bundleInfo != NULL, return APPSPAWN_TLV_NONE, 31 "No bundle info in msg %{public}s", context->bundleName); 32 int len = 0; 33 if (bundleInfo->bundleIndex > 0) { 34 len = sprintf_s((char *)buffer, bufferLen, "%s_%d", bundleInfo->bundleName, bundleInfo->bundleIndex); 35 } else { 36 len = sprintf_s((char *)buffer, bufferLen, "%s", bundleInfo->bundleName); 37 } 38 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen), 39 return -1, "Failed to format path app: %{public}s", context->bundleName); 40 *realLen = (uint32_t)len; 41 return 0; 42} 43 44APPSPAWN_STATIC int VarPackageNameReplace(const SandboxContext *context, 45 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData) 46{ 47 int len = sprintf_s((char *)buffer, bufferLen, "%s", context->bundleName); 48 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen), 49 return -1, "Failed to format path app: %{public}s", context->bundleName); 50 *realLen = (uint32_t)len; 51 return 0; 52} 53 54static int VarCurrentUseIdReplace(const SandboxContext *context, 55 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData) 56{ 57 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO); 58 APPSPAWN_CHECK(info != NULL, return APPSPAWN_TLV_NONE, 59 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName); 60 int len = 0; 61 if (extraData == NULL || !CHECK_FLAGS_BY_INDEX(extraData->operation, SANDBOX_TAG_PERMISSION)) { 62 len = sprintf_s((char *)buffer, bufferLen, "%u", info->uid / UID_BASE); 63 } else { 64 len = sprintf_s((char *)buffer, bufferLen, "%s", "currentUser"); 65 } 66 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen), 67 return -1, "Failed to format path app: %{public}s", context->bundleName); 68 *realLen = (uint32_t)len; 69 return 0; 70} 71 72static int VarArkWebPackageNameReplace(const SandboxContext *context, 73 const char *buffer, uint32_t bufferLen, uint32_t *realLen, 74 const VarExtraData *extraData) 75{ 76 static char arkWebPackageName[PARAM_BUFFER_SIZE] = {0}; 77 if (strlen(arkWebPackageName) == 0) { 78 int len = GetParameter(ARK_WEB_PERSIST_PACKAGE_NAME, "", 79 arkWebPackageName, sizeof(arkWebPackageName)); 80 APPSPAWN_CHECK(len > 0, return -1, 81 "Failed to get param for var %{public}s", 82 ARK_WEB_PERSIST_PACKAGE_NAME); 83 } 84 APPSPAWN_LOGV("ArkWebPackageNameReplace '%{public}s'", arkWebPackageName); 85 86 int len = sprintf_s((char*) buffer, bufferLen, "%s", arkWebPackageName); 87 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen), return -1, 88 "Failed to format path app: %{public}s", arkWebPackageName); 89 *realLen = (uint32_t) len; 90 return 0; 91} 92 93static int VariableNodeCompareName(ListNode *node, void *data) 94{ 95 AppSandboxVarNode *varNode = (AppSandboxVarNode *)ListEntry(node, AppSandboxVarNode, node); 96 return strcmp((char *)data, varNode->name); 97} 98 99static AppSandboxVarNode *GetAppSandboxVarNode(const char *name) 100{ 101 ListNode *node = OH_ListFind(&g_sandboxVarList, (void *)name, VariableNodeCompareName); 102 if (node == NULL) { 103 return NULL; 104 } 105 return (AppSandboxVarNode *)ListEntry(node, AppSandboxVarNode, node); 106} 107 108static int ReplaceVariableByParameter(const char *varData, SandboxBuffer *sandboxBuffer) 109{ 110 // "<param:persist.nweb.sandbox.src_path>" 111 int len = GetParameter(varData + sizeof("<param:") - 1, 112 DEFAULT_NWEB_SANDBOX_SEC_PATH, sandboxBuffer->buffer + sandboxBuffer->current, 113 sandboxBuffer->bufferLen - sandboxBuffer->current - 1); 114 APPSPAWN_CHECK(len > 0, return -1, "Failed to get param for var %{public}s", varData); 115 sandboxBuffer->current += len; 116 return 0; 117} 118 119APPSPAWN_STATIC int ReplaceVariableForDepSandboxPath(const SandboxContext *context, 120 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData) 121{ 122 APPSPAWN_CHECK(extraData != NULL && extraData->data.depNode != NULL, return -1, "Invalid extra data "); 123 uint32_t len = strlen(extraData->data.depNode->target); 124 int ret = memcpy_s((char *)buffer, bufferLen, extraData->data.depNode->target, len); 125 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data"); 126 *realLen = len; 127 return 0; 128} 129 130APPSPAWN_STATIC int ReplaceVariableForDepSrcPath(const SandboxContext *context, 131 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData) 132{ 133 APPSPAWN_CHECK(extraData != NULL && extraData->data.depNode != NULL, return -1, "Invalid extra data "); 134 uint32_t len = strlen(extraData->data.depNode->source); 135 int ret = memcpy_s((char *)buffer, bufferLen, extraData->data.depNode->source, len); 136 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data"); 137 *realLen = len; 138 return 0; 139} 140 141APPSPAWN_STATIC int ReplaceVariableForDepPath(const SandboxContext *context, 142 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData) 143{ 144 APPSPAWN_CHECK(extraData != NULL && extraData->data.depNode != NULL, return -1, "Invalid extra data "); 145 char *path = extraData->data.depNode->source; 146 if (CHECK_FLAGS_BY_INDEX(extraData->operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX)) { 147 path = extraData->data.depNode->target; 148 } else if (CHECK_FLAGS_BY_INDEX(extraData->operation, MOUNT_PATH_OP_REPLACE_BY_SRC) && IsPathEmpty(path)) { 149 path = extraData->data.depNode->target; 150 } 151 APPSPAWN_CHECK(path != NULL, return -1, "Invalid path %{public}x ", extraData->operation); 152 uint32_t len = strlen(path); 153 int ret = memcpy_s((char *)buffer, bufferLen, path, len); 154 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data"); 155 *realLen = len; 156 return 0; 157} 158 159static int ReplaceVariableForpackageName(const SandboxContext *context, 160 const char *buffer, uint32_t bufferLen, uint32_t *realLen, const VarExtraData *extraData) 161{ 162 APPSPAWN_CHECK(context != NULL, return -1, "Invalid context"); 163 AppSpawnMsgBundleInfo *bundleInfo = (AppSpawnMsgBundleInfo *)GetSpawningMsgInfo(context, TLV_BUNDLE_INFO); 164 APPSPAWN_CHECK(bundleInfo != NULL, return APPSPAWN_TLV_NONE, 165 "No bundle info in msg %{public}s", context->bundleName); 166 167 uint32_t flags = 0; 168 char *extension = NULL; 169 if (CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, APP_FLAGS_ATOMIC_SERVICE)) { 170 flags |= SANDBOX_PACKAGENAME_ATOMIC_SERVICE; 171 } else { 172 flags |= (CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, APP_FLAGS_CLONE_ENABLE) && 173 bundleInfo->bundleIndex > 0) ? SANDBOX_PACKAGENAME_CLONE : 0; 174 flags |= CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, APP_FLAGS_EXTENSION_SANDBOX) 175 ? SANDBOX_PACKAGENAME_EXTENSION : 0; 176 extension = (char *)GetAppSpawnMsgExtInfo(context->message, MSG_EXT_NAME_APP_EXTENSION, NULL); 177 } 178 179 int32_t len = 0; 180 switch (flags) { 181 case SANDBOX_PACKAGENAME_DEFAULT: // 0 packageName 182 len = sprintf_s((char *)buffer, bufferLen, "%s", bundleInfo->bundleName); 183 break; 184 case SANDBOX_PACKAGENAME_CLONE: // 1 +clone-bundleIndex+packageName 185 len = sprintf_s((char *)buffer, bufferLen, "+clone-%u+%s", bundleInfo->bundleIndex, bundleInfo->bundleName); 186 break; 187 case SANDBOX_PACKAGENAME_EXTENSION: { // 2 +extension-<extensionType>+packageName 188 APPSPAWN_CHECK(extension != NULL, return -1, "Invalid extension data"); 189 len = sprintf_s((char *)buffer, bufferLen, "+extension-%s+%s", extension, bundleInfo->bundleName); 190 break; 191 } 192 case SANDBOX_PACKAGENAME_CLONE_AND_EXTENSION: { // 3 +clone-bundleIndex+extension-<extensionType>+packageName 193 APPSPAWN_CHECK(extension != NULL, return -1, "Invalid extension data"); 194 len = sprintf_s((char *)buffer, bufferLen, "+clone-%u+extension-%s+%s", 195 bundleInfo->bundleIndex, extension, bundleInfo->bundleName); 196 break; 197 } 198 case SANDBOX_PACKAGENAME_ATOMIC_SERVICE: { // 4 +auid-<accountId>+packageName 199 char *accountId = (char *)GetAppSpawnMsgExtInfo(context->message, MSG_EXT_NAME_ACCOUNT_ID, NULL); 200 APPSPAWN_CHECK(accountId != NULL, return -1, "Invalid accountId data"); 201 len = sprintf_s((char *)buffer, bufferLen, "+auid-%s+%s", accountId, bundleInfo->bundleName); 202 break; 203 } 204 default: 205 break; 206 } 207 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < bufferLen), 208 return -1, "Failed to format path app: %{public}s flags %{public}u", context->bundleName, flags); 209 *realLen = (uint32_t)len; 210 return 0; 211} 212 213static int GetVariableName(char *varData, uint32_t len, const char *varStart, uint32_t *varLen) 214{ 215 uint32_t i = 0; 216 uint32_t sourceLen = strlen(varStart); 217 for (; i < sourceLen; i++) { 218 if (i > len) { 219 return -1; 220 } 221 varData[i] = *(varStart + i); 222 if (varData[i] == '>') { 223 break; 224 } 225 } 226 varData[i + 1] = '\0'; 227 *varLen = i + 1; 228 return 0; 229} 230 231static int ReplaceVariable(const SandboxContext *context, 232 const char *varStart, SandboxBuffer *sandboxBuffer, uint32_t *varLen, const VarExtraData *extraData) 233{ 234 char varName[128] = {0}; // 128 max len for var 235 int ret = GetVariableName(varName, sizeof(varName), varStart, varLen); 236 APPSPAWN_CHECK(ret == 0, return -1, "Failed to get variable name"); 237 238 uint32_t valueLen = 0; 239 AppSandboxVarNode *node = GetAppSandboxVarNode(varName); 240 if (node != NULL) { 241 ret = node->replaceVar(context, sandboxBuffer->buffer + sandboxBuffer->current, 242 sandboxBuffer->bufferLen - sandboxBuffer->current - 1, &valueLen, extraData); 243 APPSPAWN_CHECK(ret == 0 && valueLen < (sandboxBuffer->bufferLen - sandboxBuffer->current), 244 return -1, "Failed to fill real data"); 245 sandboxBuffer->current += valueLen; 246 return 0; 247 } 248 // "<param:persist.nweb.sandbox.src_path>" 249 if (strncmp(varName, "<param:", sizeof("<param:") - 1) == 0) { // retry param: 250 varName[*varLen - 1] = '\0'; // erase last > 251 return ReplaceVariableByParameter(varName, sandboxBuffer); 252 } 253 if (strncmp(varName, "<lib>", sizeof("<lib>") - 1) == 0) { // retry lib 254 ret = memcpy_s(sandboxBuffer->buffer + sandboxBuffer->current, 255 sandboxBuffer->bufferLen - sandboxBuffer->current, APPSPAWN_LIB_NAME, strlen(APPSPAWN_LIB_NAME)); 256 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data"); 257 sandboxBuffer->current += strlen(APPSPAWN_LIB_NAME); 258 return 0; 259 } 260 // no match revered origin data 261 APPSPAWN_LOGE("ReplaceVariable var '%{public}s' no match variable", varName); 262 ret = memcpy_s(sandboxBuffer->buffer + sandboxBuffer->current, 263 sandboxBuffer->bufferLen - sandboxBuffer->current, varName, *varLen); 264 APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy real data"); 265 sandboxBuffer->current += *varLen; 266 return 0; 267} 268 269static int HandleVariableReplace(const SandboxContext *context, 270 SandboxBuffer *sandboxBuffer, const char *source, const VarExtraData *extraData) 271{ 272 size_t sourceLen = strlen(source); 273 for (size_t i = 0; i < sourceLen; i++) { 274 if ((sandboxBuffer->current + 1) >= sandboxBuffer->bufferLen) { 275 return -1; 276 } 277 if (*(source + i) != '<') { // copy source 278 *(sandboxBuffer->buffer + sandboxBuffer->current) = *(source + i); 279 sandboxBuffer->current++; 280 continue; 281 } 282 uint32_t varLen = 0; 283 int ret = ReplaceVariable(context, source + i, sandboxBuffer, &varLen, extraData); 284 APPSPAWN_CHECK(ret == 0, return ret, "Failed to fill real data"); 285 i += (varLen - 1); 286 } 287 return 0; 288} 289 290const char *GetSandboxRealVar(const SandboxContext *context, 291 uint32_t bufferType, const char *source, const char *prefix, const VarExtraData *extraData) 292{ 293 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return NULL); 294 APPSPAWN_CHECK(bufferType < ARRAY_LENGTH(context->buffer), return NULL, "Invalid index for buffer"); 295 SandboxBuffer *sandboxBuffer = &((SandboxContext *)context)->buffer[bufferType]; 296 APPSPAWN_CHECK_ONLY_EXPER(sandboxBuffer != NULL && sandboxBuffer->buffer != NULL, return NULL); 297 const char *tmp = source; 298 int ret = 0; 299 if (!IsPathEmpty(prefix)) { // copy prefix data 300 ret = HandleVariableReplace(context, sandboxBuffer, prefix, extraData); 301 APPSPAWN_CHECK(ret == 0, return NULL, "Failed to replace source %{public}s ", prefix); 302 303 if (tmp != NULL && sandboxBuffer->buffer[sandboxBuffer->current - 1] == '/' && *tmp == '/') { 304 tmp = source + 1; 305 } 306 } 307 if (!IsPathEmpty(tmp)) { // copy source data 308 ret = HandleVariableReplace(context, sandboxBuffer, tmp, extraData); 309 APPSPAWN_CHECK(ret == 0, return NULL, "Failed to replace source %{public}s ", source); 310 } 311 sandboxBuffer->buffer[sandboxBuffer->current] = '\0'; 312 // restore buffer 313 sandboxBuffer->current = 0; 314 315 // For the depNode scenario, if there are variables in the deps path, a secondary replacement is required 316 if (extraData != NULL && extraData->sandboxTag == SANDBOX_TAG_NAME_GROUP && extraData->data.depNode != NULL) { 317 if (strstr(sandboxBuffer->buffer, "<") != NULL) { 318 SandboxBuffer *tmpBuffer = &((SandboxContext *)context)->buffer[BUFFER_FOR_TMP]; 319 ret = HandleVariableReplace(context, tmpBuffer, sandboxBuffer->buffer, extraData); 320 APPSPAWN_CHECK(ret == 0, return NULL, "Failed to replace source %{public}s ", sandboxBuffer->buffer); 321 tmpBuffer->buffer[tmpBuffer->current] = '\0'; 322 ret = strcpy_s(sandboxBuffer->buffer, sandboxBuffer->bufferLen, tmpBuffer->buffer); 323 APPSPAWN_CHECK(ret == 0, return NULL, "Failed to copy source %{public}s ", sandboxBuffer->buffer); 324 } 325 } 326 return sandboxBuffer->buffer; 327} 328 329int AddVariableReplaceHandler(const char *name, ReplaceVarHandler handler) 330{ 331 APPSPAWN_CHECK(name != NULL && handler != NULL, return APPSPAWN_ARG_INVALID, "Invalid arg "); 332 if (GetAppSandboxVarNode(name) != NULL) { 333 return APPSPAWN_NODE_EXIST; 334 } 335 336 size_t len = APPSPAWN_ALIGN(strlen(name) + 1); 337 AppSandboxVarNode *node = (AppSandboxVarNode *)malloc(sizeof(AppSandboxVarNode) + len); 338 APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create sandbox"); 339 OH_ListInit(&node->node); 340 node->replaceVar = handler; 341 int ret = strcpy_s(node->name, len, name); 342 APPSPAWN_CHECK(ret == 0, free(node); 343 return -1, "Failed to copy name %{public}s", name); 344 OH_ListAddTail(&g_sandboxVarList, &node->node); 345 return 0; 346} 347 348void AddDefaultVariable(void) 349{ 350 AddVariableReplaceHandler(PARAMETER_PACKAGE_NAME, VarPackageNameReplace); 351 AddVariableReplaceHandler(PARAMETER_USER_ID, VarCurrentUseIdReplace); 352 AddVariableReplaceHandler(PARAMETER_PACKAGE_INDEX, VarPackageNameIndexReplace); 353 AddVariableReplaceHandler(PARAMETER_ARK_WEB_PACKAGE_INDEX, VarArkWebPackageNameReplace); 354 /* 355 deps-path路径变量的含义: 356 1)首次挂载时,表示mount-paths-deps->sandbox-path 【STAGE_GLOBAL或者应用孵化时的挂载】 357 使用 MOUNT_PATH_OP_REPLACE_BY_SANDBOX 标记 358 2)二次挂载时,表示mount-paths-deps->src-path; 359 如果mount-paths-deps->src-path为空,则使用mount-paths-deps->sandbox-path 360 使用 MOUNT_PATH_OP_ONLY_SANDBOX + MOUNT_PATH_OP_REPLACE_BY_SRC,只使用源目录,不添加root-dir 361 【RemountByName时,如el2解锁或nweb更新时】 362 */ 363 AddVariableReplaceHandler("<deps-sandbox-path>", ReplaceVariableForDepSandboxPath); 364 AddVariableReplaceHandler("<deps-src-path>", ReplaceVariableForDepSrcPath); 365 AddVariableReplaceHandler("<deps-path>", ReplaceVariableForDepPath); 366 AddVariableReplaceHandler("<variablePackageName>", ReplaceVariableForpackageName); 367} 368 369void ClearVariable(void) 370{ 371 OH_ListRemoveAll(&g_sandboxVarList, NULL); 372} 373