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_sandbox.h" 17#include "sandbox_adapter.h" 18 19#include <errno.h> 20#include <fcntl.h> 21#include <sched.h> 22#include <stdbool.h> 23#include <stdio.h> 24#include <stdlib.h> 25#include <unistd.h> 26 27#include <sys/mount.h> 28#include <sys/stat.h> 29#include <sys/syscall.h> 30#include <sys/types.h> 31#include "securec.h" 32 33#include "appspawn_msg.h" 34#include "appspawn_utils.h" 35#ifdef WITH_DLP 36#include "dlp_fuse_fd.h" 37#endif 38#include "init_utils.h" 39#include "parameter.h" 40#include "appspawn_permission.h" 41 42#ifdef WITH_SELINUX 43#ifdef APPSPAWN_MOUNT_TMPSHM 44#include "policycoreutils.h" 45#endif // APPSPAWN_MOUNT_TMPSHM 46#endif // WITH_SELINUX 47 48#define USER_ID_SIZE 16 49#define DIR_MODE 0711 50#define DEV_SHM_DIR "/dev/shm/" 51 52static inline void SetMountPathOperation(uint32_t *operation, uint32_t index) 53{ 54 *operation |= (1 << index); 55} 56 57static inline bool CheckSpawningMsgFlagSet(const SandboxContext *context, uint32_t index) 58{ 59 APPSPAWN_CHECK(context->message != NULL, return false, "Invalid property for type %{public}u", TLV_MSG_FLAGS); 60 return CheckAppSpawnMsgFlag(context->message, TLV_MSG_FLAGS, index); 61} 62 63APPSPAWN_STATIC inline bool CheckSpawningPermissionFlagSet(const SandboxContext *context, uint32_t index) 64{ 65 APPSPAWN_CHECK(context != NULL && context->message != NULL, 66 return NULL, "Invalid property for type %{public}u", TLV_PERMISSION); 67 return CheckAppSpawnMsgFlag(context->message, TLV_PERMISSION, index); 68} 69 70APPSPAWN_STATIC bool CheckDirRecursive(const char *path) 71{ 72 char buffer[PATH_MAX] = {0}; 73 const char slash = '/'; 74 const char *p = path; 75 char *curPos = strchr(path, slash); 76 while (curPos != NULL) { 77 int len = curPos - p; 78 p = curPos + 1; 79 if (len == 0) { 80 curPos = strchr(p, slash); 81 continue; 82 } 83 int ret = memcpy_s(buffer, PATH_MAX, path, p - path - 1); 84 APPSPAWN_CHECK(ret == 0, return false, "Failed to copy path"); 85 ret = access(buffer, F_OK); 86 APPSPAWN_CHECK(ret == 0, return false, "Dir not exit %{public}s errno: %{public}d", buffer, errno); 87 curPos = strchr(p, slash); 88 } 89 int ret = access(path, F_OK); 90 APPSPAWN_CHECK(ret == 0, return false, "Dir not exit %{public}s errno: %{public}d", buffer, errno); 91 return true; 92} 93 94int SandboxMountPath(const MountArg *arg) 95{ 96 APPSPAWN_CHECK(arg != NULL && arg->originPath != NULL && arg->destinationPath != NULL, 97 return APPSPAWN_ARG_INVALID, "Invalid arg "); 98 99 APPSPAWN_LOGV("Bind mount arg: '%{public}s' '%{public}s' %{public}x '%{public}s' %{public}s => %{public}s", 100 arg->fsType, arg->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE", 101 (uint32_t)arg->mountFlags, arg->options, arg->originPath, arg->destinationPath); 102 103 int ret = mount(arg->originPath, arg->destinationPath, arg->fsType, arg->mountFlags, arg->options); 104 if (ret != 0) { 105 if (arg->originPath != NULL && strstr(arg->originPath, "/data/app/el2/") != NULL) { 106 CheckDirRecursive(arg->originPath); 107 } 108 APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s", 109 errno, arg->originPath, arg->destinationPath); 110 return errno; 111 } 112 ret = mount(NULL, arg->destinationPath, NULL, arg->mountSharedFlag, NULL); 113 if (ret != 0) { 114 APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s", 115 errno, arg->originPath, arg->destinationPath); 116 return errno; 117 } 118 return 0; 119} 120 121static int BuildRootPath(char *buffer, uint32_t bufferLen, const AppSpawnSandboxCfg *sandbox, uid_t uid) 122{ 123 int ret = 0; 124 int len = 0; 125 uint32_t currLen = 0; 126 uint32_t userIdLen = sizeof(PARAMETER_USER_ID) - 1; 127 uint32_t rootLen = strlen(sandbox->rootPath); 128 char *rootPath = strstr(sandbox->rootPath, PARAMETER_USER_ID); 129 if (rootPath == NULL) { 130 len = sprintf_s(buffer, bufferLen, "%s/%d", sandbox->rootPath, uid); 131 } else { 132 ret = memcpy_s(buffer, bufferLen, sandbox->rootPath, rootPath - sandbox->rootPath); 133 APPSPAWN_CHECK(ret == 0, return ret, "Failed to copy root path %{public}s", sandbox->rootPath); 134 currLen = rootPath - sandbox->rootPath; 135 136 if (rootLen > (currLen + userIdLen)) { 137 len = sprintf_s(buffer + currLen, bufferLen - currLen, "%d%s", 138 uid, sandbox->rootPath + currLen + userIdLen); 139 } else { 140 len = sprintf_s(buffer + currLen, bufferLen - currLen, "%d", uid); 141 } 142 APPSPAWN_CHECK(len > 0 && ((uint32_t)len < (bufferLen - currLen)), return ret, 143 "Failed to format root path %{public}s", sandbox->rootPath); 144 currLen += (uint32_t)len; 145 } 146 buffer[currLen] = '\0'; 147 return 0; 148} 149 150static SandboxContext *g_sandboxContext = NULL; 151 152SandboxContext *GetSandboxContext(void) 153{ 154 if (g_sandboxContext == NULL) { 155 SandboxContext *context = calloc(1, MAX_SANDBOX_BUFFER * MAX_BUFFER + sizeof(SandboxContext)); 156 APPSPAWN_CHECK(context != NULL, return NULL, "Failed to get mem"); 157 char *buffer = (char *)(context + 1); 158 for (int i = 0; i < MAX_BUFFER; i++) { 159 context->buffer[i].bufferLen = MAX_SANDBOX_BUFFER; 160 context->buffer[i].current = 0; 161 context->buffer[i].buffer = buffer + MAX_SANDBOX_BUFFER * i; 162 } 163 context->bundleName = NULL; 164 context->bundleHasWps = 0; 165 context->dlpBundle = 0; 166 context->appFullMountEnable = 0; 167 context->sandboxSwitch = 1; 168 context->sandboxShared = false; 169 context->message = NULL; 170 context->rootPath = NULL; 171 g_sandboxContext = context; 172 } 173 return g_sandboxContext; 174} 175 176void DeleteSandboxContext(SandboxContext *context) 177{ 178 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return); 179 if (context->rootPath) { 180 free(context->rootPath); 181 context->rootPath = NULL; 182 } 183 if (context == g_sandboxContext) { 184 g_sandboxContext = NULL; 185 } 186 free(context); 187} 188 189static int InitSandboxContext(SandboxContext *context, 190 const AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn) 191{ 192 AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppProperty(property, TLV_MSG_FLAGS); 193 APPSPAWN_CHECK(msgFlags != NULL, return APPSPAWN_TLV_NONE, 194 "No msg flags in msg %{public}s", GetProcessName(property)); 195 context->nwebspawn = nwebspawn; 196 context->bundleName = GetBundleName(property); 197 context->bundleHasWps = strstr(context->bundleName, "wps") != NULL; 198 context->dlpBundle = strcmp(GetProcessName(property), "com.ohos.dlpmanager") == 0; 199 context->appFullMountEnable = sandbox->appFullMountEnable; 200 201 context->sandboxSwitch = 1; 202 context->sandboxShared = false; 203 SandboxPackageNameNode *packageNode = (SandboxPackageNameNode *)GetSandboxSection( 204 &sandbox->packageNameQueue, context->bundleName); 205 if (packageNode) { 206 context->sandboxShared = packageNode->section.sandboxShared; 207 } 208 context->message = property->message; 209 210 context->sandboxNsFlags = CLONE_NEWNS; 211 if ((CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_SANDBOX) && !IsDeveloperModeOpen()) || 212 CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_NETWORK)) { 213 context->sandboxNsFlags |= sandbox->sandboxNsFlags & CLONE_NEWNET ? CLONE_NEWNET : 0; 214 } 215 216 ListNode *node = sandbox->permissionQueue.front.next; 217 while (node != &sandbox->permissionQueue.front) { 218 SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node); 219 if (permissionNode == NULL) { 220 return -1; 221 } 222 context->sandboxShared = permissionNode->section.sandboxShared; 223 node = node->next; 224 } 225 226 // root path 227 const char *rootPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, sandbox->rootPath, NULL, NULL); 228 if (rootPath) { 229 context->rootPath = strdup(rootPath); 230 } 231 if (context->rootPath == NULL) { 232 DeleteSandboxContext(context); 233 return -1; 234 } 235 return 0; 236} 237 238static VarExtraData *GetVarExtraData(const SandboxContext *context, const SandboxSection *section) 239{ 240 static VarExtraData extraData; 241 (void)memset_s(&extraData, sizeof(extraData), 0, sizeof(extraData)); 242 extraData.sandboxTag = GetSectionType(section); 243 if (GetSectionType(section) == SANDBOX_TAG_NAME_GROUP) { 244 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section; 245 extraData.data.depNode = groupNode->depNode; 246 } 247 return &extraData; 248} 249 250static uint32_t GetMountArgs(const SandboxContext *context, 251 const PathMountNode *sandboxNode, uint32_t operation, MountArg *args) 252{ 253 uint32_t category = sandboxNode->category; 254 const MountArgTemplate *tmp = GetMountArgTemplate(category); 255 if (tmp == 0) { 256 return MOUNT_TMP_DEFAULT; 257 } 258 args->fsType = tmp->fsType; 259 args->options = tmp->options; 260 args->mountFlags = tmp->mountFlags; 261 args->mountSharedFlag = (sandboxNode->mountSharedFlag) ? MS_SHARED : tmp->mountSharedFlag; 262 return category; 263} 264 265APPSPAWN_STATIC int CheckSandboxMountNode(const SandboxContext *context, 266 const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation) 267{ 268 if (sandboxNode->source == NULL || sandboxNode->target == NULL) { 269 APPSPAWN_LOGW("Invalid mount config section %{public}s", section->name); 270 return 0; 271 } 272 // special handle wps and don't use /data/app/xxx/<Package> config 273 if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_SPAWN_FLAGS)) { // flags-point 274 if (context->bundleHasWps && 275 (strstr(sandboxNode->source, "/data/app") != NULL) && 276 (strstr(sandboxNode->source, "/base") != NULL || strstr(sandboxNode->source, "/database") != NULL) && 277 (strstr(sandboxNode->source, PARAMETER_PACKAGE_NAME) != NULL)) { 278 APPSPAWN_LOGW("Invalid mount source %{public}s section %{public}s", 279 sandboxNode->source, section->name); 280 return 0; 281 } 282 } 283 // check apl 284 AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO); 285 if (msgDomainInfo != NULL && sandboxNode->appAplName != NULL) { 286 if (!strcmp(sandboxNode->appAplName, msgDomainInfo->apl)) { 287 APPSPAWN_LOGW("Invalid mount app apl %{public}s %{public}s section %{public}s", 288 sandboxNode->appAplName, msgDomainInfo->apl, section->name); 289 return 0; 290 } 291 } 292 return 1; 293} 294 295static int32_t SandboxMountFusePath(const SandboxContext *context, const MountArg *args) 296{ 297 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO); 298 APPSPAWN_CHECK(info != NULL, return APPSPAWN_TLV_NONE, 299 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName); 300 301 // umount fuse path, make sure that sandbox path is not a mount point 302 umount2(args->destinationPath, MNT_DETACH); 303 304 int fd = open("/dev/fuse", O_RDWR); 305 APPSPAWN_CHECK(fd != -1, return -EINVAL, 306 "open /dev/fuse failed, errno: %{public}d sandbox path %{public}s", errno, args->destinationPath); 307 308 char options[OPTIONS_MAX_LEN] = {0}; 309 int ret = sprintf_s(options, sizeof(options), "fd=%d," 310 "rootmode=40000,user_id=%d,group_id=%d,allow_other," 311 "context=\"u:object_r:dlp_fuse_file:s0\"," 312 "fscontext=u:object_r:dlp_fuse_file:s0", fd, info->uid, info->gid); 313 APPSPAWN_CHECK(ret > 0, return APPSPAWN_ERROR_UTILS_MEM_FAIL, "sprintf options fail"); 314 315 APPSPAWN_LOGV("Bind mount dlp fuse \n " 316 "mount arg: '%{public}s' '%{public}s' %{public}x '%{public}s' %{public}s => %{public}s", 317 args->fsType, args->mountSharedFlag == MS_SHARED ? "MS_SHARED" : "MS_SLAVE", 318 (uint32_t)args->mountFlags, options, args->originPath, args->destinationPath); 319 320 // To make sure destinationPath exist 321 CreateSandboxDir(args->destinationPath, FILE_MODE); 322 MountArg mountArg = {args->originPath, args->destinationPath, args->fsType, args->mountFlags, options, MS_SHARED}; 323 ret = SandboxMountPath(&mountArg); 324 if (ret != 0) { 325 close(fd); 326 return -1; 327 } 328 /* set DLP_FUSE_FD */ 329#ifdef WITH_DLP 330 SetDlpFuseFd(fd); 331#endif 332 return 0; 333} 334 335APPSPAWN_STATIC void CheckAndCreateSandboxFile(const char *file) 336{ 337 if (access(file, F_OK) == 0) { 338 APPSPAWN_LOGI("file %{public}s already exist", file); 339 return; 340 } 341 MakeDirRec(file, FILE_MODE, 0); 342 int fd = open(file, O_CREAT, FILE_MODE); 343 if (fd < 0) { 344 APPSPAWN_LOGW("failed create %{public}s, err=%{public}d", file, errno); 345 } else { 346 close(fd); 347 } 348 return; 349} 350 351APPSPAWN_STATIC void CreateDemandSrc(const SandboxContext *context, const PathMountNode *sandboxNode, 352 const MountArg *args) 353{ 354 if (!sandboxNode->createDemand) { 355 return; 356 } 357 CheckAndCreateSandboxFile(args->originPath); 358 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO); 359 APPSPAWN_CHECK(info != NULL, return, 360 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, context->bundleName); 361 362 // chmod 363 uid_t uid = sandboxNode->demandInfo->uid != INVALID_UID ? sandboxNode->demandInfo->uid : info->uid; 364 gid_t gid = sandboxNode->demandInfo->gid != INVALID_UID ? sandboxNode->demandInfo->gid : info->gid; 365 int ret = chown(args->originPath, uid, gid); 366 if (ret != 0) { 367 APPSPAWN_LOGE("Failed to chown %{public}s errno: %{public}d", args->originPath, errno); 368 } 369 if (sandboxNode->demandInfo->mode != INVALID_UID) { 370 ret = chmod(args->originPath, sandboxNode->demandInfo->mode); 371 if (ret != 0) { 372 APPSPAWN_LOGE("Failed to chmod %{public}s errno: %{public}d", args->originPath, errno); 373 } 374 } 375} 376 377APPSPAWN_STATIC const char *GetRealSrcPath(const SandboxContext *context, const char *source, VarExtraData *extraData) 378{ 379 bool hasPackageName = strstr(source, "<variablePackageName>") != NULL; 380 extraData->variablePackageName = (char *)context->bundleName; 381 const char *originPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, source, NULL, extraData); 382 if (originPath == NULL) { 383 return NULL; 384 } 385 if (hasPackageName && CheckSpawningMsgFlagSet(context, APP_FLAGS_ATOMIC_SERVICE)) { 386 MakeAtomicServiceDir(context, originPath); 387 } 388 return originPath; 389} 390 391// 设置挂载参数options 392static int32_t SetMountArgsOption(const SandboxContext *context, uint32_t category, uint32_t operation, MountArg *args) 393{ 394 if ((category != MOUNT_TMP_DAC_OVERRIDE) && (category != MOUNT_TMP_DAC_OVERRIDE_DELETE)) { 395 return 0; 396 } 397 398 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO); 399 if (info == NULL) { 400 APPSPAWN_LOGE("Get msg dac info failed"); 401 return APPSPAWN_ARG_INVALID; 402 } 403 404 char options[OPTIONS_MAX_LEN] = {0}; 405 int len = sprintf_s(options, OPTIONS_MAX_LEN, "%s%s%d", args->options, SHAREFS_OPTION_USER, info->uid / UID_BASE); 406 if (len <= 0) { 407 APPSPAWN_LOGE("sprintf_s failed"); 408 return APPSPAWN_ERROR_UTILS_MEM_FAIL; 409 } 410 args->options = options; 411 return 0; 412} 413 414// 根据沙盒配置文件中挂载类别进行挂载挂载 415static int DoSandboxMountByCategory(const SandboxContext *context, const PathMountNode *sandboxNode, 416 MountArg *args, uint32_t operation) 417{ 418 int ret = 0; 419 uint32_t category = GetMountArgs(context, sandboxNode, operation, args); 420 if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_PERMISSION) || 421 CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_SPAWN_FLAGS)) { 422 ret = SetMountArgsOption(context, category, operation, args); 423 if (ret != 0) { 424 APPSPAWN_LOGE("set mount arg option fail. ret: %{public}d", ret); 425 return ret; 426 } 427 } 428 if (category == MOUNT_TMP_DLP_FUSE || category == MOUNT_TMP_FUSE) { 429 ret = SandboxMountFusePath(context, args); 430 } else { 431 ret = SandboxMountPath(args); 432 } 433 return ret; 434} 435 436static int DoSandboxPathNodeMount(const SandboxContext *context, 437 const SandboxSection *section, const PathMountNode *sandboxNode, uint32_t operation) 438{ 439 if (CheckSandboxMountNode(context, section, sandboxNode, operation) == 0) { 440 return 0; 441 } 442 443 MountArg args = {}; 444 uint32_t category = GetMountArgs(context, sandboxNode, operation, &args); 445 VarExtraData *extraData = GetVarExtraData(context, section); 446 args.originPath = GetRealSrcPath(context, sandboxNode->source, extraData); 447 // dest 448 extraData->operation = operation; // only destinationPath 449 // 对name group的节点,需要对目的沙盒进行特殊处理,不能带root-dir 450 if (CHECK_FLAGS_BY_INDEX(operation, SANDBOX_TAG_NAME_GROUP) && 451 CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_ONLY_SANDBOX)) { 452 args.destinationPath = GetSandboxRealVar(context, BUFFER_FOR_TARGET, sandboxNode->target, NULL, extraData); 453 } else { 454 args.destinationPath = GetSandboxRealVar(context, 455 BUFFER_FOR_TARGET, sandboxNode->target, context->rootPath, extraData); 456 } 457 APPSPAWN_CHECK(args.originPath != NULL && args.destinationPath != NULL, 458 return APPSPAWN_ARG_INVALID, "Invalid path %{public}s %{public}s", args.originPath, args.destinationPath); 459 460 if (sandboxNode->sandboxNode.type == SANDBOX_TAG_MOUNT_FILE) { 461 CheckAndCreateSandboxFile(args.destinationPath); 462 } else { 463 if (access(args.destinationPath, F_OK) != 0) { 464 CreateSandboxDir(args.destinationPath, FILE_MODE); 465 } 466 } 467 CreateDemandSrc(context, sandboxNode, &args); 468 469 if (CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_UNMOUNT)) { // unmount this deps 470 APPSPAWN_LOGV("umount2 %{public}s", args.destinationPath); 471 umount2(args.destinationPath, MNT_DETACH); 472 } 473 int ret = 0; 474 ret = DoSandboxMountByCategory(context, sandboxNode, &args, operation); 475 if (ret != 0 && sandboxNode->checkErrorFlag) { 476 APPSPAWN_LOGE("Failed to mount config, section: %{public}s result: %{public}d category: %{public}d", 477 section->name, ret, category); 478 return ret; 479 } 480 return 0; 481} 482 483static int DoSandboxPathSymLink(const SandboxContext *context, 484 const SandboxSection *section, const SymbolLinkNode *sandboxNode) 485{ 486 // Check the validity of the symlink configuration 487 if (sandboxNode->linkName == NULL || sandboxNode->target == NULL) { 488 APPSPAWN_LOGW("Invalid symlink config, section %{public}s", section->name); 489 return 0; 490 } 491 492 const char *target = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, sandboxNode->target, NULL, NULL); 493 const char *linkName = GetSandboxRealVar(context, BUFFER_FOR_TARGET, 494 sandboxNode->linkName, context->rootPath, NULL); 495 APPSPAWN_LOGV("symlink from %{public}s to %{public}s", target, linkName); 496 if (access(linkName, F_OK) == 0) { 497 if (rmdir(linkName) != 0) { 498 APPSPAWN_LOGW("linkName %{public}s already exist and rmdir failed, errno %{public}d", linkName, errno); 499 } 500 } 501 int ret = symlink(target, linkName); 502 if (ret && errno != EEXIST) { 503 if (sandboxNode->checkErrorFlag) { 504 APPSPAWN_LOGE("symlink failed, errno: %{public}d link info %{public}s %{public}s", 505 errno, sandboxNode->target, sandboxNode->linkName); 506 return errno; 507 } 508 APPSPAWN_LOGV("symlink failed, errno: %{public}d link info %{public}s %{public}s", 509 errno, sandboxNode->target, sandboxNode->linkName); 510 } 511 return 0; 512} 513 514static int DoSandboxNodeMount(const SandboxContext *context, const SandboxSection *section, uint32_t operation) 515{ 516 ListNode *node = section->front.next; 517 while (node != §ion->front) { 518 int ret = 0; 519 SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node); 520 switch (sandboxNode->type) { 521 case SANDBOX_TAG_MOUNT_PATH: 522 case SANDBOX_TAG_MOUNT_FILE: 523 ret = DoSandboxPathNodeMount(context, section, (PathMountNode *)sandboxNode, operation); 524 break; 525 case SANDBOX_TAG_SYMLINK: 526 if (!CHECK_FLAGS_BY_INDEX(operation, MOUNT_PATH_OP_SYMLINK)) { 527 break; 528 } 529 ret = DoSandboxPathSymLink(context, section, (SymbolLinkNode *)sandboxNode); 530 break; 531 default: 532 break; 533 } 534 if (ret != 0) { 535 return ret; 536 } 537 node = node->next; 538 } 539 return 0; 540} 541 542static bool IsUnlockStatus(uint32_t uid, const char *bundleName, size_t bundleNameLen) 543{ 544 const int userIdBase = UID_BASE; 545 uid = uid / userIdBase; 546 if (uid == 0) { 547 return true; 548 } 549 550 const char rootPath[] = "/data/app/el2/"; 551 const char basePath[] = "/base/"; 552 size_t allPathSize = strlen(rootPath) + strlen(basePath) + 1 + USER_ID_SIZE + bundleNameLen; 553 char *path = (char *)malloc(sizeof(char) * allPathSize); 554 APPSPAWN_CHECK(path != NULL, return true, "Failed to malloc path"); 555 int len = sprintf_s(path, allPathSize, "%s%u%s%s", rootPath, uid, basePath, bundleName); 556 APPSPAWN_CHECK(len > 0 && ((size_t)len < allPathSize), free(path); return true, "Failed to get base path"); 557 558 if (access(path, F_OK) == 0) { 559 APPSPAWN_LOGI("this is unlock status"); 560 free(path); 561 return true; 562 } 563 free(path); 564 APPSPAWN_LOGI("this is lock status"); 565 return false; 566} 567 568static void MountDir(AppSpawnMsgDacInfo *info, const char *bundleName, const char *rootPath, const char *targetPath) 569{ 570 if (info == NULL || bundleName == NULL || rootPath == NULL || targetPath == NULL) { 571 return; 572 } 573 574 const int userIdBase = UID_BASE; 575 size_t allPathSize = strlen(rootPath) + strlen(targetPath) + strlen(bundleName) + 2; 576 allPathSize += USER_ID_SIZE; 577 char *path = (char *)malloc(sizeof(char) * (allPathSize)); 578 APPSPAWN_CHECK(path != NULL, return, "Failed to malloc path"); 579 int len = sprintf_s(path, allPathSize, "%s%u/%s%s", rootPath, info->uid / userIdBase, bundleName, targetPath); 580 APPSPAWN_CHECK(len > 0 && ((size_t)len < allPathSize), free(path); 581 return, "Failed to get sandbox path"); 582 583 if (access(path, F_OK) == 0) { 584 free(path); 585 return; 586 } 587 588 MakeDirRec(path, DIR_MODE, 1); 589 if (mount(path, path, NULL, MS_BIND | MS_REC, NULL) != 0) { 590 APPSPAWN_LOGI("bind mount %{public}s failed, error %{public}d", path, errno); 591 free(path); 592 return; 593 } 594 if (mount(NULL, path, NULL, MS_SHARED, NULL) != 0) { 595 APPSPAWN_LOGI("mount path %{public}s to shared failed, errno %{public}d", path, errno); 596 free(path); 597 return; 598 } 599 APPSPAWN_LOGI("mount path %{public}s to shared success", path); 600 free(path); 601 return; 602} 603 604static const MountSharedTemplate MOUNT_SHARED_MAP[] = { 605 {"/data/storage/el2", NULL}, 606 {"/data/storage/el3", NULL}, 607 {"/data/storage/el4", NULL}, 608 {"/data/storage/el5", "ohos.permission.PROTECT_SCREEN_LOCK_DATA"}, 609 {"/storage/Users", "ohos.permission.FILE_ACCESS_MANAGER"}, 610}; 611 612static void MountDirToShared(const SandboxContext *context, AppSpawnSandboxCfg *sandbox) 613{ 614 const char rootPath[] = "/mnt/sandbox/"; 615 const char nwebPath[] = "/mnt/nweb"; 616 const char nwebTmpPath[] = "/mnt/nweb/tmp"; 617 const char appRootName[] = "app-root"; 618 AppSpawnMsgDacInfo *info = (AppSpawnMsgDacInfo *)GetSpawningMsgInfo(context, TLV_DAC_INFO); 619 if (info == NULL || context->bundleName == NULL) { 620 return; 621 } 622 MountDir(info, appRootName, rootPath, nwebPath); 623 MountDir(info, appRootName, rootPath, nwebTmpPath); 624 625 if (IsUnlockStatus(info->uid, context->bundleName, strlen(context->bundleName))) { 626 return; 627 } 628 629 int length = sizeof(MOUNT_SHARED_MAP) / sizeof(MOUNT_SHARED_MAP[0]); 630 for (int i = 0; i < length; i++) { 631 if (MOUNT_SHARED_MAP[i].permission == NULL) { 632 MountDir(info, context->bundleName, rootPath, MOUNT_SHARED_MAP[i].sandboxPath); 633 } else { 634 int index = GetPermissionIndexInQueue(&sandbox->permissionQueue, MOUNT_SHARED_MAP[i].permission); 635 APPSPAWN_LOGV("mount dir on lock mountPermissionFlags %{public}d", index); 636 if (CheckSpawningPermissionFlagSet(context, index)) { 637 MountDir(info, context->bundleName, rootPath, MOUNT_SHARED_MAP[i].sandboxPath); 638 } 639 } 640 } 641 char lockSbxPathStamp[MAX_SANDBOX_BUFFER] = { 0 }; 642 int ret = 0; 643 if (CheckSpawningMsgFlagSet(context, APP_FLAGS_ISOLATED_SANDBOX_TYPE) != 0) { 644 ret = snprintf_s(lockSbxPathStamp, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s%d/isolated/%s_locked", 645 rootPath, info->uid / UID_BASE, context->bundleName); 646 } else { 647 ret = snprintf_s(lockSbxPathStamp, MAX_SANDBOX_BUFFER, MAX_SANDBOX_BUFFER - 1, "%s%d/%s_locked", 648 rootPath, info->uid / UID_BASE, context->bundleName); 649 } 650 if (ret <= 0) { 651 APPSPAWN_LOGE("snprintf_s lock sandbox path stamp failed"); 652 return; 653 } 654 655 CreateSandboxDir(lockSbxPathStamp, FILE_MODE); 656} 657 658static int UpdateMountPathDepsPath(const SandboxContext *context, SandboxNameGroupNode *groupNode) 659{ 660 PathMountNode *depNode = groupNode->depNode; 661 const char *srcPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, depNode->source, NULL, NULL); 662 const char *sandboxPath = GetSandboxRealVar(context, BUFFER_FOR_TARGET, depNode->target, NULL, NULL); 663 if (srcPath == NULL || sandboxPath == NULL) { 664 APPSPAWN_LOGE("Failed to get real path %{public}s ", groupNode->section.name); 665 return APPSPAWN_SANDBOX_MOUNT_FAIL; 666 } 667 free(depNode->source); 668 depNode->source = strdup(srcPath); 669 free(depNode->target); 670 depNode->target = strdup(sandboxPath); 671 if (depNode->source == NULL || depNode->target == NULL) { 672 APPSPAWN_LOGE("Failed to get real path %{public}s ", groupNode->section.name); 673 if (depNode->source) { 674 free(depNode->source); 675 depNode->source = NULL; 676 } 677 if (depNode->target) { 678 free(depNode->target); 679 depNode->target = NULL; 680 } 681 return APPSPAWN_SANDBOX_MOUNT_FAIL; 682 } 683 return 0; 684} 685 686static bool CheckAndCreateDepPath(const SandboxContext *context, const SandboxNameGroupNode *groupNode) 687{ 688 PathMountNode *mountNode = (PathMountNode *)GetFirstSandboxMountNode(&groupNode->section); 689 if (mountNode == NULL) { 690 return false; 691 } 692 693 // 这里可能需要替换deps的数据 694 VarExtraData *extraData = GetVarExtraData(context, &groupNode->section); 695 const char *srcPath = GetSandboxRealVar(context, BUFFER_FOR_SOURCE, mountNode->source, NULL, extraData); 696 if (srcPath == NULL) { 697 return false; 698 } 699 if (access(srcPath, F_OK) == 0) { 700 APPSPAWN_LOGV("Src path %{public}s exist, do not mount", srcPath); 701 return true; 702 } 703 // 不存在,则创建并挂载 704 APPSPAWN_LOGV("Mount depended source: %{public}s", groupNode->depNode->source); 705 CreateSandboxDir(groupNode->depNode->source, FILE_MODE); 706 return false; 707} 708 709static int MountSandboxConfig(const SandboxContext *context, 710 const AppSpawnSandboxCfg *sandbox, const SandboxSection *section, uint32_t op) 711{ 712 uint32_t operation = (op != MOUNT_PATH_OP_NONE) ? op : 0; 713 SetMountPathOperation(&operation, section->sandboxNode.type); 714 // if sandbox switch is off, don't do symlink work again 715 if (context->sandboxSwitch && sandbox->topSandboxSwitch) { 716 SetMountPathOperation(&operation, MOUNT_PATH_OP_SYMLINK); 717 } 718 719 int ret = DoSandboxNodeMount(context, section, operation); 720 APPSPAWN_CHECK(ret == 0, return ret, 721 "Mount sandbox config fail result: %{public}d, app: %{public}s", ret, context->bundleName); 722 723 if (section->nameGroups == NULL) { 724 return 0; 725 } 726 727 for (uint32_t i = 0; i < section->number; i++) { 728 if (section->nameGroups[i] == NULL) { 729 continue; 730 } 731 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i]; 732 if (groupNode->depMounted != 1) { 733 SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX); 734 } 735 SetMountPathOperation(&operation, SANDBOX_TAG_NAME_GROUP); 736 ret = DoSandboxNodeMount(context, &groupNode->section, operation); 737 APPSPAWN_CHECK(ret == 0, return ret, 738 "Mount name group %{public}s fail result: %{public}d", groupNode->section.name, ret); 739 } 740 return 0; 741} 742 743static int SetExpandSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox) 744{ 745 int ret = ProcessExpandAppSandboxConfig(context, sandbox, "HspList"); 746 APPSPAWN_CHECK(ret == 0, return ret, 747 "Set HspList config fail result: %{public}d, app: %{public}s", ret, context->bundleName); 748 ret = ProcessExpandAppSandboxConfig(context, sandbox, "DataGroup"); 749 APPSPAWN_CHECK(ret == 0, return ret, 750 "Set DataGroup config fail result: %{public}d, app: %{public}s", ret, context->bundleName); 751 752 bool mountDestBundlePath = false; 753 AppSpawnMsgDomainInfo *msgDomainInfo = (AppSpawnMsgDomainInfo *)GetSpawningMsgInfo(context, TLV_DOMAIN_INFO); 754 if (msgDomainInfo != NULL) { 755 mountDestBundlePath = (strcmp(msgDomainInfo->apl, APL_SYSTEM_BASIC) == 0) || 756 (strcmp(msgDomainInfo->apl, APL_SYSTEM_CORE) == 0); 757 } 758 if (mountDestBundlePath || (CheckSpawningMsgFlagSet(context, APP_FLAGS_ACCESS_BUNDLE_DIR) != 0)) { 759 // need permission check for system app here 760 const char *destBundlesPath = GetSandboxRealVar(context, 761 BUFFER_FOR_TARGET, "/data/bundles/", context->rootPath, NULL); 762 CreateSandboxDir(destBundlesPath, FILE_MODE); 763 MountArg mountArg = {PHYSICAL_APP_INSTALL_PATH, destBundlesPath, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE}; 764 ret = SandboxMountPath(&mountArg); 765 APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %{public}d", ret); 766 } 767 return 0; 768} 769 770static int SetSandboxPackageNameConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox) 771{ 772 SandboxPackageNameNode *sandboxNode = 773 (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, context->bundleName); 774 if (sandboxNode != NULL) { 775 int ret = MountSandboxConfig(context, sandbox, &sandboxNode->section, MOUNT_PATH_OP_NONE); 776 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 777 } 778 return 0; 779} 780 781static int SetSandboxSpawnFlagsConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox) 782{ 783 ListNode *node = sandbox->spawnFlagsQueue.front.next; 784 while (node != &sandbox->spawnFlagsQueue.front) { 785 SandboxFlagsNode *sandboxNode = (SandboxFlagsNode *)ListEntry(node, SandboxMountNode, node); 786 // match flags point 787 if (sandboxNode->flagIndex == 0 || !CheckSpawningMsgFlagSet(context, sandboxNode->flagIndex)) { 788 node = node->next; 789 continue; 790 } 791 792 int ret = MountSandboxConfig(context, sandbox, &sandboxNode->section, MOUNT_PATH_OP_NONE); 793 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 794 node = node->next; 795 } 796 return 0; 797} 798 799static int SetSandboxPermissionConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox) 800{ 801 APPSPAWN_LOGV("Set permission config"); 802 ListNode *node = sandbox->permissionQueue.front.next; 803 while (node != &sandbox->permissionQueue.front) { 804 SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node); 805 if (!CheckSpawningPermissionFlagSet(context, permissionNode->permissionIndex)) { 806 node = node->next; 807 continue; 808 } 809 810 APPSPAWN_LOGV("SetSandboxPermissionConfig permission %{public}d %{public}s", 811 permissionNode->permissionIndex, permissionNode->section.name); 812 int ret = MountSandboxConfig(context, sandbox, &permissionNode->section, MOUNT_PATH_OP_NONE); 813 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 814 node = node->next; 815 } 816 return 0; 817} 818 819static int SetOverlayAppSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox) 820{ 821 if (!CheckSpawningMsgFlagSet(context, APP_FLAGS_OVERLAY)) { 822 return 0; 823 } 824 int ret = ProcessExpandAppSandboxConfig(context, sandbox, "Overlay"); 825 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 826 return 0; 827} 828 829static int SetBundleResourceSandboxConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox) 830{ 831 if (!CheckSpawningMsgFlagSet(context, APP_FLAGS_BUNDLE_RESOURCES)) { 832 return 0; 833 } 834 const char *destPath = GetSandboxRealVar(context, 835 BUFFER_FOR_TARGET, "/data/storage/bundle_resources/", context->rootPath, NULL); 836 CreateSandboxDir(destPath, FILE_MODE); 837 MountArg mountArg = { 838 "/data/service/el1/public/bms/bundle_resources/", destPath, NULL, MS_REC | MS_BIND, NULL, MS_SLAVE 839 }; 840 int ret = SandboxMountPath(&mountArg); 841 return ret; 842} 843 844static int32_t ChangeCurrentDir(const SandboxContext *context) 845{ 846 int32_t ret = 0; 847 ret = chdir(context->rootPath); 848 APPSPAWN_CHECK(ret == 0, return ret, 849 "chdir failed, app: %{public}s, path: %{public}s errno: %{public}d", 850 context->bundleName, context->rootPath, errno); 851 852 if (context->sandboxShared) { 853 ret = chroot(context->rootPath); 854 APPSPAWN_CHECK(ret == 0, return ret, 855 "chroot failed, path: %{public}s errno: %{public}d", context->rootPath, errno); 856 return ret; 857 } 858 ret = syscall(SYS_pivot_root, context->rootPath, context->rootPath); 859 APPSPAWN_CHECK(ret == 0, return ret, 860 "pivot root failed, path: %{public}s errno: %{public}d", context->rootPath, errno); 861 ret = umount2(".", MNT_DETACH); 862 APPSPAWN_CHECK(ret == 0, return ret, 863 "MNT_DETACH failed, path: %{public}s errno: %{public}d", context->rootPath, errno); 864 APPSPAWN_LOGV("ChangeCurrentDir %{public}s ", context->rootPath); 865 return ret; 866} 867 868static int SandboxRootFolderCreateNoShare( 869 const SandboxContext *context, const AppSpawnSandboxCfg *sandbox, bool remountProc) 870{ 871 APPSPAWN_LOGV("SandboxRootFolderCreateNoShare %{public}s ", context->rootPath); 872 int ret = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL); 873 APPSPAWN_CHECK(ret == 0, return ret, 874 "set propagation slave failed, app: %{public}s errno: %{public}d", context->rootPath, errno); 875 876 MountArg arg = {context->rootPath, context->rootPath, NULL, BASIC_MOUNT_FLAGS, NULL, MS_SLAVE}; 877 ret = SandboxMountPath(&arg); 878 APPSPAWN_CHECK(ret == 0, return ret, 879 "mount path failed, app: %{public}s errno: %{public}d", context->rootPath, ret); 880 return ret; 881} 882 883static int SandboxRootFolderCreate(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox) 884{ 885 APPSPAWN_LOGV("topSandboxSwitch %{public}d sandboxSwitch: %{public}d sandboxShared: %{public}d \n", 886 sandbox->topSandboxSwitch, context->sandboxSwitch, context->sandboxShared); 887 888 int ret = 0; 889 if (sandbox->topSandboxSwitch == 0 || context->sandboxSwitch == 0) { 890 ret = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL); 891 APPSPAWN_CHECK(ret == 0, return ret, 892 "set propagation slave failed, app: %{public}s errno: %{public}d", context->rootPath, errno); 893 // bind mount "/" to /mnt/sandbox/<packageName> path 894 // rootfs: to do more resources bind mount here to get more strict resources constraints 895 ret = mount("/", context->rootPath, NULL, BASIC_MOUNT_FLAGS, NULL); 896 APPSPAWN_CHECK(ret == 0, return ret, 897 "mount bind / failed, app: %{public}s errno: %{public}d", context->rootPath, errno); 898 } else if (!context->sandboxShared) { 899 bool remountProc = !context->nwebspawn && ((sandbox->sandboxNsFlags & CLONE_NEWPID) == CLONE_NEWPID); 900 ret = SandboxRootFolderCreateNoShare(context, sandbox, remountProc); 901 } 902 return ret; 903} 904 905static bool IsSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, const char *rootPath) 906{ 907 char path[PATH_MAX] = {}; 908 int len = sprintf_s(path, sizeof(path), "%s%s", rootPath, SANDBOX_STAMP_FILE_SUFFIX); 909 APPSPAWN_CHECK(len > 0, return false, "Failed to format path"); 910 911 FILE *f = fopen(path, "rb"); 912 if (f != NULL) { 913 fclose(f); 914#ifndef APPSPAWN_TEST 915 return true; 916#endif 917 } 918 return false; 919} 920 921static int SetSandboxMounted(const AppSpawnSandboxCfg *sandbox, const char *name, char *rootPath) 922{ 923 APPSPAWN_LOGW("SetSystemConstMounted %{public}s ", rootPath); 924 char path[PATH_MAX] = {}; 925 int len = sprintf_s(path, sizeof(path), "%s%s", rootPath, SANDBOX_STAMP_FILE_SUFFIX); 926 APPSPAWN_CHECK(len > 0, return 0, "Failed to format path"); 927 928 FILE *f = fopen(path, "wb"); 929 if (f != NULL) { 930 fclose(f); 931 } 932 return 0; 933} 934 935static void UnmountPath(char *rootPath, uint32_t len, const SandboxMountNode *sandboxNode) 936{ 937 if (sandboxNode->type == SANDBOX_TAG_MOUNT_PATH) { 938 PathMountNode *pathNode = (PathMountNode *)sandboxNode; 939 int ret = strcat_s(rootPath, len, pathNode->target); 940 APPSPAWN_CHECK(ret == 0, return, "Failed to format"); 941 APPSPAWN_LOGV("Unmount sandbox config sandbox path %{public}s ", rootPath); 942 ret = umount2(rootPath, MNT_DETACH); 943 APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to umount2 %{public}s errno: %{public}d", rootPath, errno); 944 } 945} 946 947int UnmountDepPaths(const AppSpawnSandboxCfg *sandbox, uid_t uid) 948{ 949 APPSPAWN_CHECK(sandbox != NULL, return -1, "Invalid sandbox or context"); 950 APPSPAWN_LOGI("Unmount sandbox mount-paths-deps %{public}u ", sandbox->depNodeCount); 951 char path[PATH_MAX] = {}; 952 int ret = BuildRootPath(path, sizeof(path), sandbox, uid / UID_BASE); 953 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return -1); 954 uint32_t rootLen = strlen(path); 955 for (uint32_t i = 0; i < sandbox->depNodeCount; i++) { 956 SandboxNameGroupNode *groupNode = sandbox->depGroupNodes[i]; 957 if (groupNode == NULL || groupNode->depNode == NULL) { 958 continue; 959 } 960 // unmount this deps 961 UnmountPath(path, sizeof(path), &groupNode->depNode->sandboxNode); 962 path[rootLen] = '\0'; 963 } 964 return 0; 965} 966 967int UnmountSandboxConfigs(const AppSpawnSandboxCfg *sandbox, uid_t uid, const char *name) 968{ 969 APPSPAWN_CHECK(sandbox != NULL, return -1, "Invalid sandbox or context"); 970 APPSPAWN_CHECK(name != NULL, return -1, "Invalid name"); 971 char path[PATH_MAX] = {}; 972 int ret = BuildRootPath(path, sizeof(path), sandbox, uid / UID_BASE); 973 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return -1); 974 uint32_t rootLen = strlen(path); 975 APPSPAWN_LOGI("Unmount sandbox %{public}s root: %{public}s", name, path); 976 977 if (!IsSandboxMounted(sandbox, name, path)) { 978 return 0; 979 } 980 981 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, name); 982 if (section == NULL) { 983 return 0; 984 } 985 ListNode *node = section->front.next; 986 while (node != §ion->front) { 987 SandboxMountNode *sandboxNode = (SandboxMountNode *)ListEntry(node, SandboxMountNode, node); 988 UnmountPath(path, sizeof(path), sandboxNode); 989 path[rootLen] = '\0'; 990 // get next 991 node = node->next; 992 } 993 994 // delete stamp file 995 ret = strcat_s(path, sizeof(path), SANDBOX_STAMP_FILE_SUFFIX); 996 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return 0); 997 APPSPAWN_LOGI("Unmount sandbox %{public}s ", path); 998 unlink(path); 999 return 0; 1000} 1001 1002// Check whether the process incubation contains the ohos.permission.ACCESS_DLP_FILE permission 1003static bool IsADFPermission(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property) 1004{ 1005 int index = GetPermissionIndexInQueue(&sandbox->permissionQueue, ACCESS_DLP_FILE_MODE); 1006 if (index > 0 && CheckAppPermissionFlagSet(property, index)) { 1007 return true; 1008 } 1009 1010 if (GetBundleName(property) != NULL && strstr(GetBundleName(property), "com.ohos.dlpmanager") != NULL) { 1011 return true; 1012 } 1013 return false; 1014} 1015 1016int StagedMountSystemConst(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn) 1017{ 1018 APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property)); 1019 /** 1020 * system-const 处理逻辑 1021 * root-dir "/mnt/sandbox/app-root/<currentUserId>" 1022 * 遍历system-const, 处理mount path -- 可以清除配置 1023 * src = mount-path.src-path 1024 * dst = root-dir + mount-path.sandbox-path 1025 * 1026 * 遍历name-groups,处理mount path 1027 * 检查type,必须是 system-const 1028 * 如果存在 mount-paths-deps 1029 * src = mount-path.src-path 1030 * dst = mount-path.sandbox-path --> 存在依赖时,配置<deps-path>、<deps-sandbox-path>、<deps-src-path> 1031 * 否则: 1032 * src = mount-path.src-path 1033 * dst = root-dir + mount-path.sandbox-path 1034 */ 1035 SandboxContext *context = GetSandboxContext(); 1036 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return APPSPAWN_SYSTEM_ERROR); 1037 int ret = InitSandboxContext(context, sandbox, property, nwebspawn); 1038 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 1039 1040 if (IsSandboxMounted(sandbox, "system-const", context->rootPath) && IsADFPermission(sandbox, property) != true) { 1041 APPSPAWN_LOGV("Sandbox system-const %{public}s has been mount", context->rootPath); 1042 DeleteSandboxContext(context); 1043 return 0; 1044 } 1045 1046 APPSPAWN_LOGV("Set sandbox system-const %{public}s", context->rootPath); 1047 uint32_t operation = 0; 1048 SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX); // 首次挂载,使用sandbox替换 1049 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "system-const"); 1050 if (section != NULL) { 1051 ret = MountSandboxConfig(context, sandbox, section, operation); 1052 } 1053 SetSandboxMounted(sandbox, "system-const", context->rootPath); 1054 DeleteSandboxContext(context); 1055 return ret; 1056} 1057 1058static int MountDepGroups(const SandboxContext *context, SandboxNameGroupNode *groupNode) 1059{ 1060 /** 1061 * 在unshare前处理mount-paths-deps 处理逻辑 1062 * 1.判断是否有mount-paths-deps节点,没有直接返回; 1063 * 2.填充json文件中路径的变量值; 1064 * 3.校验deps-mode的值是否是not-exists 1065 * 是not-exist则判断mount-paths.src-path是否存在,若不存在则创建并挂载mount-paths-deps中的目录 1066 * 若存在则不挂载mount-paths-deps中的目录 1067 * 是always则创建并挂载mount-paths-deps中的目录; 1068 * deps-mode默认值为always; 1069 * 1070 */ 1071 int ret = 0; 1072 if (groupNode == NULL || groupNode->depNode == NULL) { 1073 return 0; 1074 } 1075 1076 ret = UpdateMountPathDepsPath(context, groupNode); 1077 APPSPAWN_CHECK(ret == 0, return ret, "Failed to updata deps path name groups %{public}s", groupNode->section.name); 1078 1079 if (groupNode->depMode == MOUNT_MODE_NOT_EXIST && CheckAndCreateDepPath(context, groupNode)) { 1080 return 0; 1081 } 1082 1083 uint32_t operation = 0; 1084 SetMountPathOperation(&operation, MOUNT_PATH_OP_UNMOUNT); 1085 groupNode->depMounted = 1; 1086 ret = DoSandboxPathNodeMount(context, &groupNode->section, groupNode->depNode, operation); 1087 if (ret != 0) { 1088 APPSPAWN_LOGE("Mount deps root fail %{public}s", groupNode->section.name); 1089 } 1090 return ret; 1091} 1092 1093static int SetSystemConstDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox) 1094{ 1095 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "system-const"); 1096 if (section == NULL || section->nameGroups == NULL) { 1097 return 0; 1098 } 1099 1100 int ret = 0; 1101 for (uint32_t i = 0; i < section->number; i++) { 1102 if (section->nameGroups[i] == NULL) { 1103 continue; 1104 } 1105 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i]; 1106 ret = MountDepGroups(context, groupNode); 1107 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups"); 1108 } 1109 return ret; 1110} 1111 1112static int SetAppVariableDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox) 1113{ 1114 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "app-variable"); 1115 if (section == NULL || section->nameGroups == NULL) { 1116 return 0; 1117 } 1118 1119 int ret = 0; 1120 for (uint32_t i = 0; i < section->number; i++) { 1121 if (section->nameGroups[i] == NULL) { 1122 continue; 1123 } 1124 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)section->nameGroups[i]; 1125 ret = MountDepGroups(context, groupNode); 1126 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups"); 1127 } 1128 return ret; 1129} 1130 1131static int SetSpawnFlagsDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox) 1132{ 1133 ListNode *node = sandbox->spawnFlagsQueue.front.next; 1134 int ret = 0; 1135 while (node != &sandbox->spawnFlagsQueue.front) { 1136 SandboxFlagsNode *sandboxNode = (SandboxFlagsNode *)ListEntry(node, SandboxMountNode, node); 1137 // match flags point 1138 if (sandboxNode->flagIndex == 0 || !CheckSpawningMsgFlagSet(context, sandboxNode->flagIndex)) { 1139 node = node->next; 1140 continue; 1141 } 1142 1143 if (sandboxNode->section.nameGroups == NULL) { 1144 node = node->next; 1145 continue; 1146 } 1147 1148 for (uint32_t i = 0; i < sandboxNode->section.number; i++) { 1149 if (sandboxNode->section.nameGroups[i] == NULL) { 1150 continue; 1151 } 1152 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)sandboxNode->section.nameGroups[i]; 1153 ret = MountDepGroups(context, groupNode); 1154 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups"); 1155 } 1156 node = node->next; 1157 } 1158 return ret; 1159} 1160 1161static int SetPackageNameDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox) 1162{ 1163 SandboxPackageNameNode *sandboxNode = 1164 (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, context->bundleName); 1165 if (sandboxNode == NULL || sandboxNode->section.nameGroups == NULL) { 1166 return 0; 1167 } 1168 1169 int ret = 0; 1170 for (uint32_t i = 0; i < sandboxNode->section.number; i++) { 1171 if (sandboxNode->section.nameGroups[i] == NULL) { 1172 continue; 1173 } 1174 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)sandboxNode->section.nameGroups[i]; 1175 ret = MountDepGroups(context, groupNode); 1176 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups"); 1177 } 1178 return ret; 1179} 1180 1181static int SetPermissionDepGroups(const SandboxContext *context, AppSpawnSandboxCfg *sandbox) 1182{ 1183 ListNode *node = sandbox->permissionQueue.front.next; 1184 int ret = 0; 1185 while (node != &sandbox->permissionQueue.front) { 1186 SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node); 1187 // match flags point 1188 if (!CheckSpawningPermissionFlagSet(context, permissionNode->permissionIndex)) { 1189 node = node->next; 1190 continue; 1191 } 1192 1193 if (permissionNode->section.nameGroups == NULL) { 1194 node = node->next; 1195 continue; 1196 } 1197 1198 for (uint32_t i = 0; i < permissionNode->section.number; i++) { 1199 if (permissionNode->section.nameGroups[i] == NULL) { 1200 continue; 1201 } 1202 SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)permissionNode->section.nameGroups[i]; 1203 ret = MountDepGroups(context, groupNode); 1204 APPSPAWN_CHECK(ret == 0, return ret, "Failed to mount deps groups"); 1205 } 1206 node = node->next; 1207 } 1208 return ret; 1209} 1210 1211// The execution of the preunshare phase depends on the mounted mount point 1212static int StagedDepGroupMounts(const SandboxContext *context, AppSpawnSandboxCfg *sandbox) 1213{ 1214 int ret = SetSystemConstDepGroups(context, sandbox); 1215 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set system const deps groups"); 1216 1217 ret = SetAppVariableDepGroups(context, sandbox); 1218 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set app variable deps groups"); 1219 1220 ret = SetSpawnFlagsDepGroups(context, sandbox); 1221 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set spawn flags deps groups"); 1222 1223 ret = SetPackageNameDepGroups(context, sandbox); 1224 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set package name deps groups"); 1225 1226 ret = SetPermissionDepGroups(context, sandbox); 1227 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set permission deps groups"); 1228 1229 return ret; 1230} 1231 1232int StagedMountPreUnShare(const SandboxContext *context, AppSpawnSandboxCfg *sandbox) 1233{ 1234 APPSPAWN_CHECK(sandbox != NULL && context != NULL, return -1, "Invalid sandbox or context"); 1235 APPSPAWN_LOGV("Set sandbox config before unshare group count %{public}d", sandbox->depNodeCount); 1236 1237 MountDirToShared(context, sandbox); 1238 int ret = StagedDepGroupMounts(context, sandbox); 1239 1240 return ret; 1241} 1242 1243static int SetAppVariableConfig(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox) 1244{ 1245 /** 1246 * app-variable 处理逻辑 1247 * root-dir global.sandbox-root 1248 * app-variabl, 处理mount path 1249 * src = mount-path.src-path 1250 * dst = root-dir + mount-path.src-path 1251 * 遍历name-groups,处理mount path 1252 * 如果存在 mount-paths-deps 1253 * dst = mount-path.sandbox-path --> 存在依赖时,配置<deps-path>、<deps-sandbox-path>、<deps-src-path> 1254 * 否则: 1255 * src = mount-path.src-path 1256 * dst = root-dir + mount-path.sandbox-path 1257 */ 1258 int ret = 0; 1259 // 首次挂载,使用sandbox替换 1260 uint32_t operation = 0; 1261 SetMountPathOperation(&operation, MOUNT_PATH_OP_REPLACE_BY_SANDBOX); 1262 SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, "app-variable"); 1263 if (section == NULL) { 1264 return 0; 1265 } 1266 ret = MountSandboxConfig(context, sandbox, section, operation); 1267 APPSPAWN_CHECK(ret == 0, return ret, 1268 "Set app-variable config fail result: %{public}d, app: %{public}s", ret, context->bundleName); 1269 return 0; 1270} 1271 1272int StagedMountPostUnshare(const SandboxContext *context, const AppSpawnSandboxCfg *sandbox) 1273{ 1274 APPSPAWN_CHECK(sandbox != NULL && context != NULL, return -1, "Invalid sandbox or context"); 1275 APPSPAWN_LOGV("Set sandbox config after unshare "); 1276 1277 int ret = SetAppVariableConfig(context, sandbox); 1278 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 1279 if (!context->nwebspawn) { 1280 ret = SetExpandSandboxConfig(context, sandbox); 1281 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 1282 } 1283 1284 ret = SetSandboxSpawnFlagsConfig(context, sandbox); 1285 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 1286 1287 ret = SetSandboxPackageNameConfig(context, sandbox); 1288 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 1289 1290 ret = SetSandboxPermissionConfig(context, sandbox); 1291 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 1292 return ret; 1293} 1294 1295#ifdef APPSPAWN_MOUNT_TMPSHM 1296static void MountDevShmPath(SandboxContext *context) 1297{ 1298 char sandboxDevShmPath[PATH_MAX] = {}; 1299 int ret = strcpy_s(sandboxDevShmPath, sizeof(sandboxDevShmPath), context->rootPath); 1300 APPSPAWN_CHECK(ret == 0, return, "Failed to strcpy rootPath"); 1301 ret = strcat_s(sandboxDevShmPath, sizeof(sandboxDevShmPath), DEV_SHM_DIR); 1302 APPSPAWN_CHECK(ret == 0, return, "Failed to format devShmPath"); 1303 int result = mount("tmpfs", sandboxDevShmPath, "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV, "size=32M"); 1304 if (result != 0) { 1305 APPSPAWN_LOGW("Error mounting %{public}s to tmpfs, errno %{public}d", sandboxDevShmPath, errno); 1306 } 1307} 1308#endif 1309 1310int MountSandboxConfigs(AppSpawnSandboxCfg *sandbox, const AppSpawningCtx *property, int nwebspawn) 1311{ 1312 APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1); 1313 APPSPAWN_CHECK(sandbox != NULL, return -1, "Failed to get sandbox for %{public}s", GetProcessName(property)); 1314 1315 SandboxContext *context = GetSandboxContext(); 1316 APPSPAWN_CHECK_ONLY_EXPER(context != NULL, return APPSPAWN_SYSTEM_ERROR); 1317 int ret = InitSandboxContext(context, sandbox, property, nwebspawn); 1318 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 1319 1320 APPSPAWN_LOGV("Set sandbox config %{public}s sandboxNsFlags 0x%{public}x", 1321 context->rootPath, context->sandboxNsFlags); 1322 do { 1323 ret = StagedMountPreUnShare(context, sandbox); 1324 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); 1325 1326 CreateSandboxDir(context->rootPath, FILE_MODE); 1327 // add pid to a new mnt namespace 1328 ret = unshare(context->sandboxNsFlags); 1329 APPSPAWN_CHECK(ret == 0, break, 1330 "unshare failed, app: %{public}s errno: %{public}d", context->bundleName, errno); 1331 if ((context->sandboxNsFlags & CLONE_NEWNET) == CLONE_NEWNET) { 1332 ret = EnableNewNetNamespace(); 1333 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); 1334 } 1335 1336 ret = SandboxRootFolderCreate(context, sandbox); 1337 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); 1338 1339 ret = StagedMountPostUnshare(context, sandbox); 1340 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); 1341 1342 ret = SetOverlayAppSandboxConfig(context, sandbox); 1343 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); 1344 ret = SetBundleResourceSandboxConfig(context, sandbox); 1345 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); 1346 1347#ifdef APPSPAWN_MOUNT_TMPSHM 1348 MountDevShmPath(context); 1349#endif 1350 ret = ChangeCurrentDir(context); 1351 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); 1352#if defined(APPSPAWN_MOUNT_TMPSHM) && defined(WITH_SELINUX) 1353 Restorecon(DEV_SHM_DIR); 1354#endif 1355 APPSPAWN_LOGV("Change root dir success %{public}s ", context->rootPath); 1356 } while (0); 1357 DeleteSandboxContext(context); 1358 return ret; 1359} 1360