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#include <ctype.h> 16#include <stdbool.h> 17#include <stdlib.h> 18#ifndef _GNU_SOURCE 19#define _GNU_SOURCE 20#endif 21#include <errno.h> 22#include <fcntl.h> 23#include <sched.h> 24#include <stdio.h> 25#include <unistd.h> 26 27#include <sys/mount.h> 28#include <sys/types.h> 29 30#include "appspawn_msg.h" 31#include "appspawn_permission.h" 32#include "appspawn_sandbox.h" 33#include "appspawn_utils.h" 34#include "cJSON.h" 35#include "init_utils.h" 36#include "json_utils.h" 37#include "parameter.h" 38#include "securec.h" 39 40static const SandboxFlagInfo NAMESPACE_FLAGS_MAP[] = { 41 {"pid", CLONE_NEWPID}, {"net", CLONE_NEWNET} 42}; 43 44static const SandboxFlagInfo FLAGE_POINT_MAP[] = { 45 {"0", 0}, 46 {"START_FLAGS_BACKUP", (unsigned long)APP_FLAGS_BACKUP_EXTENSION}, 47 {"DLP_MANAGER", (unsigned long)APP_FLAGS_DLP_MANAGER}, 48 {"DEVELOPER_MODE", (unsigned long)APP_FLAGS_DEVELOPER_MODE} 49}; 50 51static const SandboxFlagInfo MOUNT_MODE_MAP[] = { 52 {"not-exists", (unsigned long)MOUNT_MODE_NOT_EXIST}, 53 {"always", (unsigned long)MOUNT_MODE_ALWAYS} 54}; 55 56static const SandboxFlagInfo NAME_GROUP_TYPE_MAP[] = { 57 {"system-const", (unsigned long)SANDBOX_TAG_SYSTEM_CONST}, 58 {"app-variable", (unsigned long)SANDBOX_TAG_APP_VARIABLE} 59}; 60 61static inline PathMountNode *CreatePathMountNode(uint32_t type, uint32_t hasDemandInfo) 62{ 63 uint32_t len = hasDemandInfo ? sizeof(PathDemandInfo) : 0; 64 return (PathMountNode *)CreateSandboxMountNode(sizeof(PathMountNode) + len, type); 65} 66 67static inline SymbolLinkNode *CreateSymbolLinkNode(void) 68{ 69 return (SymbolLinkNode *)CreateSandboxMountNode(sizeof(SymbolLinkNode), SANDBOX_TAG_SYMLINK); 70} 71 72static inline SandboxPackageNameNode *CreateSandboxPackageNameNode(const char *name) 73{ 74 return (SandboxPackageNameNode *)CreateSandboxSection(name, 75 sizeof(SandboxPackageNameNode), SANDBOX_TAG_PACKAGE_NAME); 76} 77 78static inline SandboxFlagsNode *CreateSandboxFlagsNode(const char *name) 79{ 80 return (SandboxFlagsNode *)CreateSandboxSection(name, sizeof(SandboxFlagsNode), SANDBOX_TAG_SPAWN_FLAGS); 81} 82 83static inline SandboxNameGroupNode *CreateSandboxNameGroupNode(const char *name) 84{ 85 return (SandboxNameGroupNode *)CreateSandboxSection(name, sizeof(SandboxNameGroupNode), SANDBOX_TAG_NAME_GROUP); 86} 87 88static inline SandboxPermissionNode *CreateSandboxPermissionNode(const char *name) 89{ 90 size_t len = sizeof(SandboxPermissionNode); 91 SandboxPermissionNode *node = (SandboxPermissionNode *)CreateSandboxSection(name, len, SANDBOX_TAG_PERMISSION); 92 APPSPAWN_CHECK(node != NULL, return NULL, "Failed to create permission node"); 93 node->permissionIndex = 0; 94 return node; 95} 96 97static inline bool GetBoolParameter(const char *param, bool value) 98{ 99 char tmp[32] = {0}; // 32 max 100 int ret = GetParameter(param, "", tmp, sizeof(tmp)); 101 APPSPAWN_LOGV("GetBoolParameter key %{public}s ret %{public}d result: %{public}s", param, ret, tmp); 102 if (ret > 0 && strcmp(tmp, "false") == 0) { 103 return false; 104 } 105 if (ret > 0 && strcmp(tmp, "true") == 0) { 106 return true; 107 } 108 return value; 109} 110 111static inline bool AppSandboxPidNsIsSupport(void) 112{ 113 // only set false, return false 114 return GetBoolParameter("const.sandbox.pidns.support", true); 115} 116 117static inline bool CheckAppFullMountEnable(void) 118{ 119 return GetBoolParameter("const.filemanager.full_mount.enable", false); 120} 121 122APPSPAWN_STATIC unsigned long GetMountModeFromConfig(const cJSON *config, const char *key, unsigned long def) 123{ 124 char *value = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(config, key)); 125 if (value == NULL) { 126 return def; 127 } 128 const SandboxFlagInfo *info = GetSandboxFlagInfo(value, MOUNT_MODE_MAP, ARRAY_LENGTH(MOUNT_MODE_MAP)); 129 if (info != NULL) { 130 return info->flags; 131 } 132 return def; 133} 134 135static uint32_t GetNameGroupTypeFromConfig(const cJSON *config, const char *key, unsigned long def) 136{ 137 char *value = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(config, key)); 138 if (value == NULL) { 139 return def; 140 } 141 const SandboxFlagInfo *info = GetSandboxFlagInfo(value, NAME_GROUP_TYPE_MAP, ARRAY_LENGTH(NAME_GROUP_TYPE_MAP)); 142 if (info != NULL) { 143 return (uint32_t)info->flags; 144 } 145 return def; 146} 147 148static uint32_t GetSandboxNsFlags(const cJSON *appConfig) 149{ 150 uint32_t nsFlags = 0; 151 cJSON *obj = cJSON_GetObjectItemCaseSensitive(appConfig, "sandbox-ns-flags"); 152 if (obj == NULL || !cJSON_IsArray(obj)) { 153 return nsFlags; 154 } 155 int count = cJSON_GetArraySize(obj); 156 for (int i = 0; i < count; i++) { 157 char *value = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i)); 158 const SandboxFlagInfo *info = GetSandboxFlagInfo(value, NAMESPACE_FLAGS_MAP, ARRAY_LENGTH(NAMESPACE_FLAGS_MAP)); 159 if (info != NULL) { 160 nsFlags |= info->flags; 161 } 162 } 163 return nsFlags; 164} 165 166static int SetMode(const char *str, void *context) 167{ 168 mode_t *mode = (mode_t *)context; 169 *mode |= GetPathMode(str); 170 return 0; 171} 172 173static mode_t GetChmodFromJson(const cJSON *config) 174{ 175 mode_t mode = 0; 176 char *modeStrs = GetStringFromJsonObj(config, "dest-mode"); 177 if (modeStrs == NULL) { 178 return mode; 179 } 180 (void)StringSplit(modeStrs, "|", (void *)&mode, SetMode); 181 return mode; 182} 183 184APPSPAWN_STATIC uint32_t GetFlagIndexFromJson(const cJSON *config) 185{ 186 char *flagStr = GetStringFromJsonObj(config, "name"); 187 if (flagStr == NULL) { 188 return 0; 189 } 190 const SandboxFlagInfo *info = GetSandboxFlagInfo(flagStr, FLAGE_POINT_MAP, ARRAY_LENGTH(FLAGE_POINT_MAP)); 191 if (info != NULL) { 192 return info->flags; 193 } 194 return 0; 195} 196 197static void FillPathDemandInfo(const cJSON *config, PathMountNode *sandboxNode) 198{ 199 APPSPAWN_CHECK_ONLY_EXPER(config != NULL, return); 200 sandboxNode->demandInfo->uid = GetIntValueFromJsonObj(config, "uid", -1); 201 sandboxNode->demandInfo->gid = GetIntValueFromJsonObj(config, "gid", -1); 202 sandboxNode->demandInfo->mode = GetIntValueFromJsonObj(config, "ugo", -1); 203} 204 205static PathMountNode *DecodeMountPathConfig(const SandboxSection *section, const cJSON *config, uint32_t type) 206{ 207 char *srcPath = GetStringFromJsonObj(config, "src-path"); 208 char *dstPath = GetStringFromJsonObj(config, "sandbox-path"); 209 if (srcPath == NULL || dstPath == NULL) { 210 return NULL; 211 } 212 213 PathMountNode *tmp = GetPathMountNode(section, type, srcPath, dstPath); 214 if (tmp != NULL) { // 删除老的节点,保存新的节点 215 DeleteSandboxMountNode((SandboxMountNode *)tmp); 216 APPSPAWN_LOGW("path %{public}s %{public}s repeat config, delete old", srcPath, dstPath); 217 } 218 219 cJSON *demandInfo = cJSON_GetObjectItemCaseSensitive(config, "create-on-demand"); 220 PathMountNode *sandboxNode = CreatePathMountNode(type, demandInfo != NULL); 221 APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, return NULL); 222 sandboxNode->createDemand = demandInfo != NULL; 223 sandboxNode->source = strdup(srcPath); 224 sandboxNode->target = strdup(dstPath); 225 226 sandboxNode->destMode = GetChmodFromJson(config); 227 sandboxNode->mountSharedFlag = GetBoolValueFromJsonObj(config, "mount-shared-flag", false); 228 sandboxNode->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false); 229 230 sandboxNode->category = GetMountCategory(GetStringFromJsonObj(config, "category")); 231 const char *value = GetStringFromJsonObj(config, "app-apl-name"); 232 if (value != NULL) { 233 sandboxNode->appAplName = strdup(value); 234 } 235 FillPathDemandInfo(demandInfo, sandboxNode); 236 237 if (sandboxNode->source == NULL || sandboxNode->target == NULL) { 238 APPSPAWN_LOGE("Failed to get sourc or target path"); 239 DeleteSandboxMountNode((SandboxMountNode *)sandboxNode); 240 return NULL; 241 } 242 return sandboxNode; 243} 244 245APPSPAWN_STATIC int ParseMountPathsConfig(AppSpawnSandboxCfg *sandbox, 246 const cJSON *mountConfigs, SandboxSection *section, uint32_t type) 247{ 248 APPSPAWN_CHECK_ONLY_EXPER(mountConfigs != NULL && cJSON_IsArray(mountConfigs), return -1); 249 250 uint32_t mountPointSize = cJSON_GetArraySize(mountConfigs); 251 for (uint32_t i = 0; i < mountPointSize; i++) { 252 cJSON *mntJson = cJSON_GetArrayItem(mountConfigs, i); 253 if (mntJson == NULL) { 254 continue; 255 } 256 PathMountNode *sandboxNode = DecodeMountPathConfig(section, mntJson, type); 257 APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, continue); 258 AddSandboxMountNode(&sandboxNode->sandboxNode, section); 259 } 260 return 0; 261} 262 263static SymbolLinkNode *DecodeSymbolLinksConfig(const SandboxSection *section, const cJSON *config) 264{ 265 const char *target = GetStringFromJsonObj(config, "target-name"); 266 const char *linkName = GetStringFromJsonObj(config, "link-name"); 267 if (target == NULL || linkName == NULL) { 268 return NULL; 269 } 270 271 SymbolLinkNode *tmp = GetSymbolLinkNode(section, target, linkName); 272 if (tmp != NULL) { // 删除老的节点,保存新的节点 273 DeleteSandboxMountNode((SandboxMountNode *)tmp); 274 APPSPAWN_LOGW("SymbolLink %{public}s %{public}s repeat config, delete old", target, linkName); 275 } 276 277 SymbolLinkNode *node = CreateSymbolLinkNode(); 278 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL); 279 node->destMode = GetChmodFromJson(config); 280 node->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false); 281 node->target = strdup(target); 282 node->linkName = strdup(linkName); 283 if (node->target == NULL || node->linkName == NULL) { 284 APPSPAWN_LOGE("Failed to get sourc or target path"); 285 DeleteSandboxMountNode((SandboxMountNode *)node); 286 return NULL; 287 } 288 return node; 289} 290 291APPSPAWN_STATIC int ParseSymbolLinksConfig(AppSpawnSandboxCfg *sandbox, const cJSON *symbolLinkConfigs, 292 SandboxSection *section) 293{ 294 APPSPAWN_CHECK_ONLY_EXPER(symbolLinkConfigs != NULL && cJSON_IsArray(symbolLinkConfigs), return -1); 295 uint32_t symlinkPointSize = cJSON_GetArraySize(symbolLinkConfigs); 296 for (uint32_t i = 0; i < symlinkPointSize; i++) { 297 cJSON *symConfig = cJSON_GetArrayItem(symbolLinkConfigs, i); 298 if (symConfig == NULL) { 299 continue; 300 } 301 SymbolLinkNode *node = DecodeSymbolLinksConfig(section, symConfig); 302 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1); 303 AddSandboxMountNode(&node->sandboxNode, section); 304 } 305 return 0; 306} 307 308APPSPAWN_STATIC int ParseGidTableConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, SandboxSection *section) 309{ 310 APPSPAWN_CHECK(cJSON_IsArray(configs), return 0, "json is not array."); 311 uint32_t arrayLen = (uint32_t)cJSON_GetArraySize(configs); 312 APPSPAWN_CHECK_ONLY_EXPER(arrayLen > 0, return 0); 313 APPSPAWN_CHECK(arrayLen < APP_MAX_GIDS, arrayLen = APP_MAX_GIDS, "More gid in gids json."); 314 315 // 配置存在,以后面的配置为准 316 if (section->gidTable) { 317 free(section->gidTable); 318 section->gidTable = NULL; 319 section->gidCount = 0; 320 } 321 section->gidTable = (gid_t *)calloc(1, sizeof(gid_t) * arrayLen); 322 APPSPAWN_CHECK(section->gidTable != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory."); 323 324 for (uint32_t i = 0; i < arrayLen; i++) { 325 cJSON *item = cJSON_GetArrayItem(configs, i); 326 gid_t gid = 0; 327 if (cJSON_IsNumber(item)) { 328 gid = (gid_t)cJSON_GetNumberValue(item); 329 } else { 330 char *value = cJSON_GetStringValue(item); 331 gid = DecodeGid(value); 332 } 333 if (gid <= 0) { 334 continue; 335 } 336 section->gidTable[section->gidCount++] = gid; 337 } 338 return 0; 339} 340 341static int ParseMountGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig, SandboxSection *section) 342{ 343 APPSPAWN_CHECK(cJSON_IsArray(groupConfig), 344 return APPSPAWN_SANDBOX_INVALID, "Invalid mount-groups config %{public}s", section->name); 345 346 // 合并name-group 347 uint32_t count = (uint32_t)cJSON_GetArraySize(groupConfig); 348 APPSPAWN_LOGV("mount-group in section %{public}s %{public}u", section->name, count); 349 APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0); 350 count += section->number; 351 SandboxMountNode **nameGroups = (SandboxMountNode **)calloc(1, sizeof(SandboxMountNode *) * count); 352 APPSPAWN_CHECK(nameGroups != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory for group name"); 353 354 uint32_t j = 0; 355 uint32_t number = 0; 356 for (j = 0; j < section->number; j++) { // copy old 357 if (section->nameGroups[j] == NULL) { 358 continue; 359 } 360 nameGroups[number++] = section->nameGroups[j]; 361 } 362 363 SandboxNameGroupNode *mountNode = NULL; 364 for (uint32_t i = 0; i < count; i++) { 365 nameGroups[number] = NULL; 366 367 char *name = cJSON_GetStringValue(cJSON_GetArrayItem(groupConfig, i)); 368 mountNode = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name); 369 if (mountNode == NULL) { 370 APPSPAWN_LOGE("Can not find name-group %{public}s", name); 371 continue; 372 } 373 // check type 374 if (strcmp(section->name, "system-const") == 0 && mountNode->destType != SANDBOX_TAG_SYSTEM_CONST) { 375 APPSPAWN_LOGE("Invalid name-group %{public}s", name); 376 continue; 377 } 378 // 过滤重复的节点 379 for (j = 0; j < section->number; j++) { 380 if (section->nameGroups[j] != NULL && section->nameGroups[j] == (SandboxMountNode *)mountNode) { 381 APPSPAWN_LOGE("Name-group %{public}s bas been set", name); 382 break; 383 } 384 } 385 if (j < section->number) { 386 continue; 387 } 388 nameGroups[number++] = (SandboxMountNode *)mountNode; 389 APPSPAWN_LOGV("Name-group %{public}d %{public}s set", section->number, name); 390 } 391 if (section->nameGroups != NULL) { 392 free(section->nameGroups); 393 } 394 section->nameGroups = nameGroups; 395 section->number = number; 396 APPSPAWN_LOGV("mount-group in section %{public}s %{public}u", section->name, section->number); 397 return 0; 398} 399 400static int ParseBaseConfig(AppSpawnSandboxCfg *sandbox, SandboxSection *section, const cJSON *configs) 401{ 402 APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0); 403 APPSPAWN_CHECK(cJSON_IsObject(configs), 404 return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", section->name); 405 APPSPAWN_LOGV("Parse sandbox %{public}s", section->name); 406 407 // "sandbox-switch": "ON", default sandbox switch is on 408 section->sandboxSwitch = GetBoolValueFromJsonObj(configs, "sandbox-switch", true); 409 // "sandbox-shared" 410 section->sandboxShared = GetBoolValueFromJsonObj(configs, "sandbox-shared", false); 411 412 int ret = 0; 413 cJSON *gidTabJson = cJSON_GetObjectItemCaseSensitive(configs, "gids"); 414 if (gidTabJson) { 415 ret = ParseGidTableConfig(sandbox, gidTabJson, section); 416 APPSPAWN_CHECK(ret == 0, return ret, "Parse gids for %{public}s", section->name); 417 } 418 419 cJSON *pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-paths"); 420 if (pathConfigs != NULL) { // mount-paths 421 ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_PATH); 422 APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name); 423 } 424 425 pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-files"); 426 if (pathConfigs != NULL) { // mount-files 427 ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_FILE); 428 APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name); 429 } 430 431 pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "symbol-links"); 432 if (pathConfigs != NULL) { // symbol-links 433 ret = ParseSymbolLinksConfig(sandbox, pathConfigs, section); 434 APPSPAWN_CHECK(ret == 0, return ret, "Parse symbol-links for %{public}s", section->name); 435 } 436 437 cJSON *groupConfig = cJSON_GetObjectItemCaseSensitive(configs, "mount-groups"); 438 if (groupConfig != NULL) { 439 ret = ParseMountGroupsConfig(sandbox, groupConfig, section); 440 APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-groups for %{public}s", section->name); 441 } 442 return 0; 443} 444 445static int ParsePackageNameConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *packageNameConfigs) 446{ 447 APPSPAWN_LOGV("Parse package-name config %{public}s", name); 448 SandboxPackageNameNode *node = (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, name); 449 if (node == NULL) { 450 node = CreateSandboxPackageNameNode(name); 451 } 452 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1); 453 454 int ret = ParseBaseConfig(sandbox, &node->section, packageNameConfigs); 455 if (ret != 0) { 456 DeleteSandboxSection((SandboxSection *)node); 457 return ret; 458 } 459 // success, insert section 460 AddSandboxSection(&node->section, &sandbox->packageNameQueue); 461 return 0; 462} 463 464static int ParseSpawnFlagsConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *flagsConfig) 465{ 466 uint32_t flagIndex = GetFlagIndexFromJson(flagsConfig); 467 APPSPAWN_LOGV("Parse spawn-flags config %{public}s flagIndex %{public}u", name, flagIndex); 468 SandboxFlagsNode *node = (SandboxFlagsNode *)GetSandboxSection(&sandbox->spawnFlagsQueue, name); 469 if (node == NULL) { 470 node = CreateSandboxFlagsNode(name); 471 } 472 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1); 473 node->flagIndex = flagIndex; 474 475 int ret = ParseBaseConfig(sandbox, &node->section, flagsConfig); 476 if (ret != 0) { 477 DeleteSandboxSection((SandboxSection *)node); 478 return ret; 479 } 480 // success, insert section 481 AddSandboxSection(&node->section, &sandbox->spawnFlagsQueue); 482 return 0; 483} 484 485static int ParsePermissionConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *permissionConfig) 486{ 487 APPSPAWN_LOGV("Parse permission config %{public}s", name); 488 SandboxPermissionNode *node = (SandboxPermissionNode *)GetSandboxSection(&sandbox->permissionQueue, name); 489 if (node == NULL) { 490 node = CreateSandboxPermissionNode(name); 491 } 492 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1); 493 494 int ret = ParseBaseConfig(sandbox, &node->section, permissionConfig); 495 if (ret != 0) { 496 DeleteSandboxSection((SandboxSection *)node); 497 return ret; 498 } 499 // success, insert section 500 AddSandboxSection(&node->section, &sandbox->permissionQueue); 501 return 0; 502} 503 504static SandboxNameGroupNode *ParseNameGroup(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig) 505{ 506 char *name = GetStringFromJsonObj(groupConfig, "name"); 507 APPSPAWN_CHECK(name != NULL, return NULL, "No name in name group config"); 508 APPSPAWN_LOGV("Parse name-group config %{public}s", name); 509 SandboxNameGroupNode *node = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name); 510 if (node == NULL) { 511 node = CreateSandboxNameGroupNode(name); 512 } 513 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL); 514 515 cJSON *obj = cJSON_GetObjectItemCaseSensitive(groupConfig, "mount-paths-deps"); 516 if (obj) { 517 if (node->depNode) { // free repeat 518 DeleteSandboxMountNode((SandboxMountNode *)node->depNode); 519 } 520 node->depNode = DecodeMountPathConfig(NULL, obj, SANDBOX_TAG_MOUNT_PATH); 521 if (node->depNode == NULL) { 522 DeleteSandboxSection((SandboxSection *)node); 523 return NULL; 524 } 525 // "deps-mode": "not-exists" 526 node->depMode = GetMountModeFromConfig(groupConfig, "deps-mode", MOUNT_MODE_ALWAYS); 527 } 528 529 int ret = ParseBaseConfig(sandbox, &node->section, groupConfig); 530 if (ret != 0) { 531 DeleteSandboxSection((SandboxSection *)node); 532 return NULL; 533 } 534 // "type": "system-const", 535 // "caps": ["shared"], 536 node->destType = GetNameGroupTypeFromConfig(groupConfig, "type", SANDBOX_TAG_INVALID); 537 node->depMounted = 0; 538 // success, insert section 539 AddSandboxSection(&node->section, &sandbox->nameGroupsQueue); 540 return node; 541} 542 543static int ParseNameGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root) 544{ 545 APPSPAWN_CHECK(root != NULL, return APPSPAWN_SANDBOX_INVALID, "Invalid config "); 546 cJSON *configs = cJSON_GetObjectItemCaseSensitive(root, "name-groups"); 547 APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0); 548 APPSPAWN_CHECK(cJSON_IsArray(configs), return APPSPAWN_SANDBOX_INVALID, "Invalid config "); 549 int count = cJSON_GetArraySize(configs); 550 APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0); 551 552 sandbox->depNodeCount = 0; 553 for (int i = 0; i < count; i++) { 554 cJSON *json = cJSON_GetArrayItem(configs, i); 555 if (json == NULL) { 556 continue; 557 } 558 SandboxNameGroupNode *node = ParseNameGroup(sandbox, json); 559 APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return APPSPAWN_SANDBOX_INVALID); 560 if (node->depNode) { 561 sandbox->depNodeCount++; 562 } 563 } 564 APPSPAWN_LOGV("ParseNameGroupsConfig depNodeCount %{public}d", sandbox->depNodeCount); 565 return 0; 566} 567 568static int ParseConditionalConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, const char *configName, 569 int (*parseConfig)(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *configs)) 570{ 571 APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0); 572 APPSPAWN_CHECK(cJSON_IsArray(configs), 573 return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", configName); 574 int ret = 0; 575 int count = cJSON_GetArraySize(configs); 576 for (int i = 0; i < count; i++) { 577 cJSON *json = cJSON_GetArrayItem(configs, i); 578 if (json == NULL) { 579 continue; 580 } 581 char *name = GetStringFromJsonObj(json, "name"); 582 if (name == NULL) { 583 APPSPAWN_LOGE("No name in %{public}s configs", configName); 584 continue; 585 } 586 ret = parseConfig(sandbox, name, json); 587 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 588 } 589 return 0; 590} 591 592static int ParseGlobalSandboxConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root) 593{ 594 cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "global"); 595 if (json) { 596 sandbox->sandboxNsFlags = GetSandboxNsFlags(json); 597 char *rootPath = GetStringFromJsonObj(json, "sandbox-root"); 598 APPSPAWN_CHECK(rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "No root path in config"); 599 if (sandbox->rootPath) { 600 free(sandbox->rootPath); 601 } 602 sandbox->rootPath = strdup(rootPath); 603 APPSPAWN_CHECK(sandbox->rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to copy root path"); 604 sandbox->topSandboxSwitch = GetBoolValueFromJsonObj(json, "top-sandbox-switch", true); 605 } 606 return 0; 607} 608 609typedef struct TagParseJsonContext { 610 AppSpawnSandboxCfg *sandboxCfg; 611}ParseJsonContext; 612 613APPSPAWN_STATIC int ParseAppSandboxConfig(const cJSON *root, ParseJsonContext *context) 614{ 615 APPSPAWN_CHECK(root != NULL && context != NULL && context->sandboxCfg != NULL, 616 return APPSPAWN_SYSTEM_ERROR, "Invalid json"); 617 AppSpawnSandboxCfg *sandbox = context->sandboxCfg; 618 int ret = ParseGlobalSandboxConfig(sandbox, root); // "global": 619 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID); 620 ret = ParseNameGroupsConfig(sandbox, root); // name-groups 621 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID); 622 623 // "required" 624 cJSON *required = cJSON_GetObjectItemCaseSensitive(root, "required"); 625 if (required) { 626 cJSON *config = NULL; 627 cJSON_ArrayForEach(config, required) 628 { 629 APPSPAWN_LOGI("Sandbox required config: %{public}s", config->string); 630 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, config->string); 631 if (section == NULL) { 632 section = CreateSandboxSection(config->string, sizeof(SandboxSection), SANDBOX_TAG_REQUIRED); 633 } 634 APPSPAWN_CHECK_ONLY_EXPER(section != NULL, return -1); 635 636 ret = ParseBaseConfig(sandbox, section, config); 637 if (ret != 0) { 638 DeleteSandboxSection(section); 639 return ret; 640 } 641 // success, insert section 642 AddSandboxSection(section, &sandbox->requiredQueue); 643 } 644 } 645 646 // conditional 647 cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "conditional"); 648 if (json != NULL) { 649 // permission 650 cJSON *config = cJSON_GetObjectItemCaseSensitive(json, "permission"); 651 ret = ParseConditionalConfig(sandbox, config, "permission", ParsePermissionConfig); 652 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 653 // spawn-flag 654 config = cJSON_GetObjectItemCaseSensitive(json, "spawn-flag"); 655 ret = ParseConditionalConfig(sandbox, config, "spawn-flag", ParseSpawnFlagsConfig); 656 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 657 // package-name 658 config = cJSON_GetObjectItemCaseSensitive(json, "package-name"); 659 ret = ParseConditionalConfig(sandbox, config, "package-name", ParsePackageNameConfig); 660 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 661 } 662 return ret; 663} 664 665APPSPAWN_STATIC const char *GetSandboxNameByMode(RunMode mode) 666{ 667 if (mode == MODE_FOR_NATIVE_SPAWN) { 668 return ISOLATED_SANDBOX_FILE_NAME; 669 } 670 if (mode == MODE_FOR_NWEB_SPAWN || mode == MODE_FOR_NWEB_COLD_RUN) { 671 return WEB_SANDBOX_FILE_NAME; 672 } 673 return APP_SANDBOX_FILE_NAME; 674} 675 676int LoadAppSandboxConfig(AppSpawnSandboxCfg *sandbox, RunMode mode) 677{ 678 APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_ARG_INVALID); 679 const char *sandboxName = GetSandboxNameByMode(mode); 680 if (sandbox->depGroupNodes != NULL) { 681 APPSPAWN_LOGW("Sandbox has been load"); 682 return 0; 683 } 684 ParseJsonContext context = {}; 685 context.sandboxCfg = sandbox; 686 int ret = ParseJsonConfig("etc/sandbox", sandboxName, ParseAppSandboxConfig, &context); 687 if (ret == APPSPAWN_SANDBOX_NONE) { 688 APPSPAWN_LOGW("No sandbox config"); 689 ret = 0; 690 } 691 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 692 sandbox->pidNamespaceSupport = AppSandboxPidNsIsSupport(); 693 sandbox->appFullMountEnable = CheckAppFullMountEnable(); 694 APPSPAWN_LOGI("Sandbox pidNamespaceSupport: %{public}d appFullMountEnable: %{public}d", 695 sandbox->pidNamespaceSupport, sandbox->appFullMountEnable); 696 697 uint32_t depNodeCount = sandbox->depNodeCount; 698 APPSPAWN_CHECK_ONLY_EXPER(depNodeCount > 0, return ret); 699 700 sandbox->depGroupNodes = (SandboxNameGroupNode **)calloc(1, sizeof(SandboxNameGroupNode *) * depNodeCount); 701 APPSPAWN_CHECK(sandbox->depGroupNodes != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed alloc memory "); 702 sandbox->depNodeCount = 0; 703 ListNode *node = sandbox->nameGroupsQueue.front.next; 704 while (node != &sandbox->nameGroupsQueue.front) { 705 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)ListEntry(node, SandboxMountNode, node); 706 if (groupNode->depNode) { 707 sandbox->depGroupNodes[sandbox->depNodeCount++] = groupNode; 708 } 709 node = node->next; 710 } 711 APPSPAWN_LOGI("LoadAppSandboxConfig depNodeCount %{public}d", sandbox->depNodeCount); 712 713 return 0; 714} 715