已关闭
条件挂载支持inverted-permission #2952
zhangyanchuan创建于 3 天前关闭于 6 小时前
条件挂载支持inverted-permission #2952
已关闭
zhangyanchuan创建于 3 天前关闭于 6 小时前
12 个文件变更+1152-58
@@ -602,11 +602,6 @@
602 "sandbox-path" : "/vendor/lib",602 "sandbox-path" : "/vendor/lib",
603 "sandbox-flags" : [ "bind", "rec" ],603 "sandbox-flags" : [ "bind", "rec" ],
604 "check-action-status": "false"604 "check-action-status": "false"
605- }, {
606- "src-path" : "/data/app/el1/bundle/public/<arkWebPackageName>",
607- "sandbox-path" : "/data/app/el1/bundle/public/<arkWebPackageName>",
608- "sandbox-flags" : [ "bind", "rec" ],
609- "check-action-status": "false"
610 }, {605 }, {
611 "src-path" : "/system/app/NWeb",606 "src-path" : "/system/app/NWeb",
612 "sandbox-path" : "/system/app/NWeb",607 "sandbox-path" : "/system/app/NWeb",
@@ -617,6 +612,23 @@
617 "sandbox-path" : "/module_update/ArkWebCore/app/<arkWebPackageName>",612 "sandbox-path" : "/module_update/ArkWebCore/app/<arkWebPackageName>",
618 "sandbox-flags" : [ "bind", "rec" ],613 "sandbox-flags" : [ "bind", "rec" ],
619 "check-action-status": "false"614 "check-action-status": "false"
615+ }, {
616+ "src-path": "/mnt/sandbox/arkwebcore/dummyfile",
617+ "sandbox-path": "/system/app/ArkWebCore/ArkWebCoreEx.hap",
618+ "sandbox-flags" : [ "bind", "rec" ],
619+ "check-action-status": "false",
620+ "path-type": "file"
621+ }, {
622+ "src-path": "/mnt/sandbox/arkwebcore/dummylibs",
623+ "sandbox-path": "/data/storage/el1/bundle/arkwebcore/feature",
624+ "sandbox-flags" : [ "bind", "rec" ],
625+ "check-action-status": "false"
626+ }, {
627+ "src-path": "/mnt/sandbox/arkwebcore/dummyfile",
628+ "sandbox-path": "/data/storage/el1/bundle/arkwebcore/feature.hap",
629+ "sandbox-flags" : [ "bind", "rec" ],
630+ "check-action-status": "false",
631+ "path-type": "file"
620 }, {632 }, {
621 "src-path" : "/data/service/el1/<hostUserId>/for-all-app/fonts",633 "src-path" : "/data/service/el1/<hostUserId>/for-all-app/fonts",
622 "sandbox-path" : "/data/service/el1/public/for-all-app/fonts",634 "sandbox-path" : "/data/service/el1/public/for-all-app/fonts",
@@ -697,11 +709,6 @@
697 "sandbox-path" : "/vendor/lib",709 "sandbox-path" : "/vendor/lib",
698 "sandbox-flags" : [ "bind", "rec" ],710 "sandbox-flags" : [ "bind", "rec" ],
699 "check-action-status": "false"711 "check-action-status": "false"
700- }, {
701- "src-path" : "/data/app/el1/bundle/public/<arkWebPackageName>",
702- "sandbox-path" : "/data/app/el1/bundle/public/<arkWebPackageName>",
703- "sandbox-flags" : [ "bind", "rec" ],
704- "check-action-status": "false"
705 }, {712 }, {
706 "src-path" : "/system/app/NWeb",713 "src-path" : "/system/app/NWeb",
707 "sandbox-path" : "/system/app/NWeb",714 "sandbox-path" : "/system/app/NWeb",
@@ -712,6 +719,23 @@
712 "sandbox-path" : "/module_update/ArkWebCore/app/<arkWebPackageName>",719 "sandbox-path" : "/module_update/ArkWebCore/app/<arkWebPackageName>",
713 "sandbox-flags" : [ "bind", "rec" ],720 "sandbox-flags" : [ "bind", "rec" ],
714 "check-action-status": "false"721 "check-action-status": "false"
722+ }, {
723+ "src-path": "/mnt/sandbox/arkwebcore/dummyfile",
724+ "sandbox-path": "/system/app/ArkWebCore/ArkWebCoreEx.hap",
725+ "sandbox-flags" : [ "bind", "rec" ],
726+ "check-action-status": "false",
727+ "path-type": "file"
728+ }, {
729+ "src-path": "/mnt/sandbox/arkwebcore/dummylibs",
730+ "sandbox-path": "/data/storage/el1/bundle/arkwebcore/feature",
731+ "sandbox-flags" : [ "bind", "rec" ],
732+ "check-action-status": "false"
733+ }, {
734+ "src-path": "/mnt/sandbox/arkwebcore/dummyfile",
735+ "sandbox-path": "/data/storage/el1/bundle/arkwebcore/feature.hap",
736+ "sandbox-flags" : [ "bind", "rec" ],
737+ "check-action-status": "false",
738+ "path-type": "file"
715 }, {739 }, {
716 "src-path" : "/vendor/etc/vulkan/icd.d",740 "src-path" : "/vendor/etc/vulkan/icd.d",
717 "sandbox-path" : "/vendor/etc/vulkan/icd.d",741 "sandbox-path" : "/vendor/etc/vulkan/icd.d",
@@ -1208,6 +1232,26 @@
1208 ]1232 ]
1209 }]1233 }]
1210 }],1234 }],
1235+ "inverted-permission": [{
1236+ "ohos.permission.ARKWEBCORE_SYS_CAP": [{
1237+ "sandbox-switch": "ON",
1238+ "mount-paths": [{
1239+ "src-path": "/mnt/sandbox/arkwebcore/dummyfile",
1240+ "sandbox-path": "/system/app/ArkWebCore/ArkWebCoreEx.hap",
1241+ "sandbox-flags": [ "bind", "rec" ],
1242+ "path-type": "file"
1243+ }, {
1244+ "src-path": "/mnt/sandbox/arkwebcore/dummylibs",
1245+ "sandbox-path": "/data/storage/el1/bundle/arkwebcore/feature",
1246+ "sandbox-flags": [ "bind", "rec" ]
1247+ }, {
1248+ "src-path": "/mnt/sandbox/arkwebcore/dummyfile",
1249+ "sandbox-path": "/data/storage/el1/bundle/arkwebcore/feature.hap",
1250+ "sandbox-flags": [ "bind", "rec" ],
1251+ "path-type": "file"
1252+ }]
1253+ }]
1254+ }],
1211 "debug": [{1255 "debug": [{
1212 "common":[{1256 "common":[{
1213 "mount-paths":[1257 "mount-paths":[
@@ -60,6 +60,7 @@ APP_SANDBOX_DEFAULT = '''
60 }],60 }],
61 "individual" : [{}],61 "individual" : [{}],
62 "permission" :[{}],62 "permission" :[{}],
63+ "inverted-permission" :[{}],
63 "debug" : [{}]64 "debug" : [{}]
64}65}
65'''66'''
@@ -178,6 +179,14 @@ def _merge_scope_permission(origin, new):
178 _merge_scope_app(origin[k], v)179 _merge_scope_app(origin[k], v)
179 180 
180 181 
182+def _merge_scope_inverted_permission(origin, new):
183+ for k, v in new.items():
184+ if k not in origin:
185+ origin[k] = v
186+ else:
187+ _merge_scope_app(origin[k], v)
188+ 
189+ 
181def _merge_scope_create_only(origin, new):190def _merge_scope_create_only(origin, new):
182 for k, v in new.items():191 for k, v in new.items():
183 if k not in origin:192 if k not in origin:
@@ -288,6 +297,11 @@ def fix_sandbox_config_file(options):
288 if permission is not None and len(permission) > 0:297 if permission is not None and len(permission) > 0:
289 _merge_scope_permission(origin_json.get("permission")[0], permission[0])298 _merge_scope_permission(origin_json.get("permission")[0], permission[0])
290 299 
300+ # 处理inverted-permission
301+ inverted_permission = data.get("inverted-permission")
302+ if inverted_permission is not None and len(inverted_permission) > 0:
303+ _merge_scope_inverted_permission(origin_json.get("inverted-permission")[0], inverted_permission[0])
304+ 
291 debug = data.get("debug")305 debug = data.get("debug")
292 if debug is not None and len(debug) > 0:306 if debug is not None and len(debug) > 0:
293 _merge_scope_permission(origin_json.get("debug")[0], debug[0])307 _merge_scope_permission(origin_json.get("debug")[0], debug[0])
@@ -49,21 +49,32 @@ static int ParsePermissionConfig(const cJSON *permissionConfigs, PermissionManag
49 return 0;49 return 0;
50}50}
51 51 
52-static int ParseAppSandboxConfig(const cJSON *appSandboxConfig, PermissionManager *mgr)52+static int ParsePermissionsConfig(const char *key, const cJSON *appSandboxConfig, PermissionManager *mgr)
53{53{
54- cJSON *configs = cJSON_GetObjectItemCaseSensitive(appSandboxConfig, "permission");54+ cJSON *configs = cJSON_GetObjectItemCaseSensitive(appSandboxConfig, key);
55- APPSPAWN_CHECK(configs != NULL && cJSON_IsArray(configs), return 0, "No permission in json");55+ APPSPAWN_CHECK(configs != NULL && cJSON_IsArray(configs), return 0, "No %{public}s in json", key);
56 56 
57 int ret = 0;57 int ret = 0;
58 uint32_t configSize = (uint32_t)cJSON_GetArraySize(configs);58 uint32_t configSize = (uint32_t)cJSON_GetArraySize(configs);
59 for (uint32_t i = 0; i < configSize; i++) {59 for (uint32_t i = 0; i < configSize; i++) {
60 cJSON *json = cJSON_GetArrayItem(configs, i);60 cJSON *json = cJSON_GetArrayItem(configs, i);
61 ret = ParsePermissionConfig(json, mgr);61 ret = ParsePermissionConfig(json, mgr);
62- APPSPAWN_CHECK(ret == 0, return ret, "Parse permission config fail result: %{public}d ", ret);62+ APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
63 }63 }
64 return ret;64 return ret;
65}65}
66 66 
67+static int ParseAppSandboxConfig(const cJSON *appSandboxConfig, PermissionManager *mgr)
68+{
69+ int ret = ParsePermissionsConfig("permission", appSandboxConfig, mgr);
70+ APPSPAWN_CHECK(ret == 0, return ret, "Parse permission config fail result: %{public}d ", ret);
71+
72+ ret = ParsePermissionsConfig("inverted-permission", appSandboxConfig, mgr);
73+ APPSPAWN_CHECK(ret == 0, return ret, "Parse inverted-permission config fail result: %{public}d ", ret);
74+
75+ return ret;
76+}
77+ 
67static PermissionManager *GetPermissionMgrByType(AppSpawnClientType type)78static PermissionManager *GetPermissionMgrByType(AppSpawnClientType type)
68{79{
69 APPSPAWN_CHECK_ONLY_EXPER(type < CLIENT_MAX, return NULL);80 APPSPAWN_CHECK_ONLY_EXPER(type < CLIENT_MAX, return NULL);
@@ -101,6 +101,7 @@ MODULE_CONSTRUCTOR(void)
101 APPSPAWN_LOGV("Load sandbox module ...");101 APPSPAWN_LOGV("Load sandbox module ...");
102 (void)AddServerStageHook(STAGE_SERVER_PRELOAD, HOOK_PRIO_SANDBOX,102 (void)AddServerStageHook(STAGE_SERVER_PRELOAD, HOOK_PRIO_SANDBOX,
103 OHOS::AppSpawn::SandboxCommon::LoadAppSandboxConfigCJson);103 OHOS::AppSpawn::SandboxCommon::LoadAppSandboxConfigCJson);
104+ (void)AddPreloadHook(HOOK_PRIO_SANDBOX_MARK_PATH, OHOS::AppSpawn::SandboxCommon::CreateDummyPaths);
104#ifdef WITH_CONTROLLED_APP105#ifdef WITH_CONTROLLED_APP
105 (void)AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_SANDBOX, LoadControlledAppList);106 (void)AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_SANDBOX, LoadControlledAppList);
106#endif107#endif
@@ -328,6 +328,25 @@ void SandboxCommon::CreateFileIfNotExist(const char *file)
328 return;328 return;
329}329}
330 330 
331+int SandboxCommon::CreateDummyPaths(AppSpawnMgr *content)
332+{
333+ // 创建ArkWeb dummy文件
334+ const char *dummyFilePath = "/mnt/sandbox/arkwebcore/dummyfile";
335+ CreateFileIfNotExist(dummyFilePath);
336+ APPSPAWN_LOGV("Create ArkWeb dummy file: %{public}s", dummyFilePath);
337+ 
338+ // 创建ArkWeb dummy目录
339+ const char *dummyDirPath = "/mnt/sandbox/arkwebcore/dummylibs";
340+ int32_t ret = CreateDirRecursive(dummyDirPath, SandboxCommonDef::FILE_MODE);
341+ if (ret == 0) {
342+ APPSPAWN_LOGV("Create ArkWeb dummy dir: %{public}s", dummyDirPath);
343+ } else {
344+ APPSPAWN_LOGW("Failed to create ArkWeb dummy dir: %{public}s, ret=%{public}d", dummyDirPath, ret);
345+ }
346+ 
347+ return 0;
348+}
349+ 
331void SandboxCommon::SetSandboxPathChmod(cJSON *jsonConfig, std::string &sandboxRoot)350void SandboxCommon::SetSandboxPathChmod(cJSON *jsonConfig, std::string &sandboxRoot)
332{351{
333 const std::map<std::string, mode_t> modeMap = {{"S_IRUSR", S_IRUSR}, {"S_IWUSR", S_IWUSR}, {"S_IXUSR", S_IXUSR},352 const std::map<std::string, mode_t> modeMap = {{"S_IRUSR", S_IRUSR}, {"S_IWUSR", S_IWUSR}, {"S_IXUSR", S_IXUSR},
@@ -593,6 +612,7 @@ void SandboxCommon::GetSandboxMountConfig(const AppSpawningCtx *appProperty, con
593 cJSON *mntPoint, SandboxMountConfig &mountConfig)612 cJSON *mntPoint, SandboxMountConfig &mountConfig)
594{613{
595 if (section.compare(SandboxCommonDef::g_permissionPrefix) == 0 ||614 if (section.compare(SandboxCommonDef::g_permissionPrefix) == 0 ||
615+ section.compare(SandboxCommonDef::g_invertedPermissionPrefix) == 0 ||
596 section.compare(SandboxCommonDef::g_flagsPoint) == 0 ||616 section.compare(SandboxCommonDef::g_flagsPoint) == 0 ||
597 section.compare(SandboxCommonDef::g_debughap) == 0) {617 section.compare(SandboxCommonDef::g_debughap) == 0) {
598 mountConfig.optionsPoint = GetOptions(appProperty, mntPoint);618 mountConfig.optionsPoint = GetOptions(appProperty, mntPoint);
@@ -1133,9 +1153,10 @@ int32_t SandboxCommon::DoAppSandboxMountOnce(const AppSpawningCtx *appProperty,
1133 if (!(arg && arg->srcPath && arg->destPath && arg->srcPath[0] != '\0' && arg->destPath[0] != '\0')) {1153 if (!(arg && arg->srcPath && arg->destPath && arg->srcPath[0] != '\0' && arg->destPath[0] != '\0')) {
1134 return 0;1154 return 0;
1135 }1155 }
1136- if (strstr(arg->srcPath, "system/etc/hosts") != nullptr ||1156+ bool isFilePath = (arg->pathType == SANDBOX_FILE_PATH) || (strstr(arg->srcPath, "system/etc/hosts") != nullptr) ||
1137- strstr(arg->srcPath, "system/etc/profile") != nullptr ||1157+ (strstr(arg->srcPath, "system/etc/profile") != nullptr) ||
1138- strstr(arg->srcPath, "system/etc/sudoers") != nullptr) {1158+ (strstr(arg->srcPath, "system/etc/sudoers") != nullptr);
1159+ if (isFilePath) {
1139 CreateFileIfNotExist(arg->destPath);1160 CreateFileIfNotExist(arg->destPath);
1140 } else {1161 } else {
1141 (void)CreateDirRecursive(arg->destPath, SandboxCommonDef::FILE_MODE);1162 (void)CreateDirRecursive(arg->destPath, SandboxCommonDef::FILE_MODE);
@@ -1186,9 +1207,12 @@ int32_t SandboxCommon::DoAppSandboxMountOnceNocheck(const AppSpawningCtx *appPro
1186 if (!(arg && arg->srcPath && arg->destPath && arg->srcPath[0] != '\0' && arg->destPath[0] != '\0')) {1207 if (!(arg && arg->srcPath && arg->destPath && arg->srcPath[0] != '\0' && arg->destPath[0] != '\0')) {
1187 return 0;1208 return 0;
1188 }1209 }
1189- if ((strncmp(arg->srcPath, SandboxCommonDef::g_hostsPrefix, strlen(SandboxCommonDef::g_hostsPrefix)) == 0) ||1210+ bool isFilePath =
1211+ (arg->pathType == SANDBOX_FILE_PATH) ||
1212+ (strncmp(arg->srcPath, SandboxCommonDef::g_hostsPrefix, strlen(SandboxCommonDef::g_hostsPrefix)) == 0) ||
1190 (strncmp(arg->srcPath, SandboxCommonDef::g_profilePrefix, strlen(SandboxCommonDef::g_profilePrefix)) == 0) ||1213 (strncmp(arg->srcPath, SandboxCommonDef::g_profilePrefix, strlen(SandboxCommonDef::g_profilePrefix)) == 0) ||
1191- (strncmp(arg->srcPath, SandboxCommonDef::SUDOERS_PREFIX, strlen(SandboxCommonDef::SUDOERS_PREFIX)) == 0)) {1214+ (strncmp(arg->srcPath, SandboxCommonDef::SUDOERS_PREFIX, strlen(SandboxCommonDef::SUDOERS_PREFIX)) == 0);
1215+ if (isFilePath) {
1192 CreateFileIfNotExist(arg->destPath);1216 CreateFileIfNotExist(arg->destPath);
1193 } else {1217 } else {
1194 (void)CreateDirRecursive(arg->destPath, SandboxCommonDef::FILE_MODE);1218 (void)CreateDirRecursive(arg->destPath, SandboxCommonDef::FILE_MODE);
@@ -71,6 +71,9 @@ public:
71 static void CreateDirRecursiveWithClock(const std::string &path, mode_t mode); // MakeDirRecursiveWithClock71 static void CreateDirRecursiveWithClock(const std::string &path, mode_t mode); // MakeDirRecursiveWithClock
72 static void SetSandboxPathChmod(cJSON *jsonConfig, std::string &sandboxRoot); // DoSandboxChmod72 static void SetSandboxPathChmod(cJSON *jsonConfig, std::string &sandboxRoot); // DoSandboxChmod
73 73 
74+ // 创建dummy文件和dummy目录
75+ static int CreateDummyPaths(AppSpawnMgr *content);
76+ 
74 // 获取挂载配置参数信息77 // 获取挂载配置参数信息
75 static uint32_t ConvertFlagStr(const std::string &flagStr);78 static uint32_t ConvertFlagStr(const std::string &flagStr);
76 static unsigned long GetMountFlags(cJSON *config); // GetSandboxMountFlags79 static unsigned long GetMountFlags(cJSON *config); // GetSandboxMountFlags
@@ -148,7 +148,8 @@ std::string SandboxCore::GetSandboxPath(const AppSpawningCtx *appProperty, cJSON
148 return "";148 return "";
149 }149 }
150 std::string tmpSandboxPath(tmpSandboxPathChr);150 std::string tmpSandboxPath(tmpSandboxPathChr);
151- if (section.compare(SandboxCommonDef::g_permissionPrefix) == 0) {151+ if (section.compare(SandboxCommonDef::g_permissionPrefix) == 0 ||
152+ section.compare(SandboxCommonDef::g_invertedPermissionPrefix) == 0) {
152 sandboxPath = sandboxRoot + SandboxCommon::ConvertToRealPathWithPermission(appProperty, tmpSandboxPath);153 sandboxPath = sandboxRoot + SandboxCommon::ConvertToRealPathWithPermission(appProperty, tmpSandboxPath);
153 } else {154 } else {
154 sandboxPath = sandboxRoot + SandboxCommon::ConvertToRealPath(appProperty, tmpSandboxPath);155 sandboxPath = sandboxRoot + SandboxCommon::ConvertToRealPath(appProperty, tmpSandboxPath);
@@ -342,6 +343,52 @@ int32_t SandboxCore::SetPermissionAppSandboxProperty_(AppSpawningCtx *appPropert
342 return ret;343 return ret;
343}344}
344 345 
346+int32_t SandboxCore::DoSandboxFileInvertedPermissionBind(AppSpawningCtx *appProperty, cJSON *wholeConfig)
347+{
348+ cJSON *permission = cJSON_GetObjectItemCaseSensitive(wholeConfig,
349+ SandboxCommonDef::g_invertedPermissionPrefix);
350+ if (!permission || !cJSON_IsArray(permission)) {
351+ return 0;
352+ }
353+ 
354+ auto processor = [&appProperty](cJSON *item) {
355+ cJSON *permissionChild = item->child;
356+ while (permissionChild != nullptr) {
357+ int index = GetPermissionIndex(nullptr, permissionChild->string);
358+ if (CheckAppPermissionFlagSet(appProperty, static_cast<uint32_t>(index)) != 0) {
359+ APPSPAWN_LOGV("Skip inverted-permission %{public}s as app has the permission", permissionChild->string);
360+ permissionChild = permissionChild->next;
361+ continue;
362+ }
363+ cJSON *permissionMountPaths = cJSON_GetArrayItem(permissionChild, 0);
364+ if (!permissionMountPaths) {
365+ permissionChild = permissionChild->next;
366+ continue;
367+ }
368+ APPSPAWN_LOGV("DoSandboxFileInvertedPermissionBind %{public}s index %{public}d",
369+ permissionChild->string, index);
370+ DoAddGid(appProperty, permissionMountPaths, permissionChild->string,
371+ SandboxCommonDef::g_invertedPermissionPrefix);
372+ int ret = DoAllMntPointsMount(appProperty, permissionMountPaths, permissionChild->string,
373+ SandboxCommonDef::g_invertedPermissionPrefix);
374+ APPSPAWN_CHECK(ret == 0, return ret, "DoAllMntPointsMount failed, %{public}s", GetBundleName(appProperty));
375+ DoAllSymlinkPointslink(appProperty, permissionMountPaths);
376+ 
377+ permissionChild = permissionChild->next;
378+ }
379+ return 0;
380+ };
381+ 
382+ return SandboxCommon::HandleArrayForeach(permission, processor);
383+}
384+ 
385+int32_t SandboxCore::SetInvertedPermissionAppSandboxProperty_(AppSpawningCtx *appProperty, cJSON *config)
386+{
387+ int ret = DoSandboxFileInvertedPermissionBind(appProperty, config);
388+ APPSPAWN_CHECK(ret == 0, return ret, "DoSandboxFileInvertedPermissionBind failed");
389+ return ret;
390+}
391+ 
345cJSON *SandboxCore::GetFirstCommonConfig(cJSON *wholeConfig, const char *prefix)392cJSON *SandboxCore::GetFirstCommonConfig(cJSON *wholeConfig, const char *prefix)
346{393{
347 cJSON *commonConfig = cJSON_GetObjectItemCaseSensitive(wholeConfig, prefix);394 cJSON *commonConfig = cJSON_GetObjectItemCaseSensitive(wholeConfig, prefix);
@@ -645,6 +692,18 @@ static int ExecuteMountOnce(cJSON *mntPoint, const SharedMountArgs &arg, MountPo
645 return 0;692 return 0;
646}693}
647 694 
695+SandboxPathType SandboxCore::GetSandboxPathType(cJSON *mntPoint)
696+{
697+ const char *pathTypeStr = GetStringFromJsonObj(mntPoint, SandboxCommonDef::g_pathType);
698+ if (pathTypeStr == nullptr) {
699+ return SANDBOX_DIR_PATH;
700+ }
701+ if (strcmp(pathTypeStr, SandboxCommonDef::g_pathTypeFile) == 0) {
702+ return SANDBOX_FILE_PATH;
703+ }
704+ return SANDBOX_DIR_PATH;
705+}
706+ 
648int32_t SandboxCore::ProcessMountPointCommmon(cJSON *mntPoint, MountPointProcessParams &params, bool enableLogging)707int32_t SandboxCore::ProcessMountPointCommmon(cJSON *mntPoint, MountPointProcessParams &params, bool enableLogging)
649{708{
650 APPSPAWN_ONLY_EXPER(TryControlledSkip(mntPoint, params), return 0);709 APPSPAWN_ONLY_EXPER(TryControlledSkip(mntPoint, params), return 0);
@@ -671,7 +730,8 @@ int32_t SandboxCore::ProcessMountPointCommmon(cJSON *mntPoint, MountPointProcess
671 .mountFlags = SandboxCommon::GetMountFlags(mntPoint),730 .mountFlags = SandboxCommon::GetMountFlags(mntPoint),
672 .options = mountConfig.optionsPoint.c_str(),731 .options = mountConfig.optionsPoint.c_str(),
673 .mountSharedFlag =732 .mountSharedFlag =
674- GetBoolValueFromJsonObj(mntPoint, SandboxCommonDef::g_mountSharedFlag, false) ? MS_SHARED : MS_SLAVE733+ GetBoolValueFromJsonObj(mntPoint, SandboxCommonDef::g_mountSharedFlag, false) ? MS_SHARED : MS_SLAVE,
734+ .pathType = GetSandboxPathType(mntPoint)
675 };735 };
676 int ret = ExecuteMountOnce(mntPoint, arg, params, enableLogging, usingFusePath);736 int ret = ExecuteMountOnce(mntPoint, arg, params, enableLogging, usingFusePath);
677 if (ret != 0) {737 if (ret != 0) {
@@ -1245,6 +1305,19 @@ int32_t SandboxCore::SetPermissionAppSandboxProperty(AppSpawningCtx *appProperty
1245 return ret;1305 return ret;
1246}1306}
1247 1307 
1308+int32_t SandboxCore::SetInvertedPermissionAppSandboxProperty(AppSpawningCtx *appProperty)
1309+{
1310+ int ret = 0;
1311+ SandboxCommonDef::SandboxConfigType type = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ?
1312+ SandboxCommonDef::SANDBOX_ISOLATED_JSON_CONFIG : SandboxCommonDef::SANDBOX_APP_JSON_CONFIG;
1313+ 
1314+ for (auto& config : SandboxCommon::GetCJsonConfig(type)) {
1315+ ret = SetInvertedPermissionAppSandboxProperty_(appProperty, config);
1316+ APPSPAWN_CHECK(ret == 0, return ret, "parse inverted-permission config failed");
1317+ }
1318+ return ret;
1319+}
1320+ 
1248int32_t SandboxCore::SetSandboxProperty(AppSpawningCtx *appProperty, std::string &sandboxPackagePath)1321int32_t SandboxCore::SetSandboxProperty(AppSpawningCtx *appProperty, std::string &sandboxPackagePath)
1249{1322{
1250 int32_t ret = 0;1323 int32_t ret = 0;
@@ -1265,6 +1338,11 @@ int32_t SandboxCore::SetSandboxProperty(AppSpawningCtx *appProperty, std::string
1265 FinishAppspawnTrace();1338 FinishAppspawnTrace();
1266 APPSPAWN_CHECK(ret == 0, return ret, "SetPermissionAppSandboxProperty failed, packagename is %{public}s",1339 APPSPAWN_CHECK(ret == 0, return ret, "SetPermissionAppSandboxProperty failed, packagename is %{public}s",
1267 bundleName.c_str());1340 bundleName.c_str());
1341+ StartAppspawnTrace("SetInvertedPermissionAppSandboxProperty");
1342+ ret = SetInvertedPermissionAppSandboxProperty(appProperty);
1343+ FinishAppspawnTrace();
1344+ APPSPAWN_CHECK(ret == 0, return ret, "SetInvertedPermissionAppSandboxProperty failed, packagename is %{public}s",
1345+ bundleName.c_str());
1268 1346 
1269 ret = SetOverlayAppSandboxProperty(appProperty, sandboxPackagePath);1347 ret = SetOverlayAppSandboxProperty(appProperty, sandboxPackagePath);
1270 APPSPAWN_CHECK(ret == 0, return ret, "SetOverlayAppSandboxProperty failed, packagename is %{public}s",1348 APPSPAWN_CHECK(ret == 0, return ret, "SetOverlayAppSandboxProperty failed, packagename is %{public}s",
@@ -1730,21 +1808,8 @@ int32_t SandboxCore::UninstallDebugSandbox(AppSpawnMgr *content, AppSpawningCtx
1730 }1808 }
1731 DoUninstallDebugSandbox(bundleList, debugCommonConfig);1809 DoUninstallDebugSandbox(bundleList, debugCommonConfig);
1732 1810 
1733- cJSON *debugPermissionConfig = GetFirstSubConfig(debugJson, SandboxCommonDef::g_permissionPrefix);1811+ DoUninstallDebugPermissionPoints(bundleList, debugJson);
1734- if (!debugPermissionConfig) {1812+ DoUninstallDebugInvertedPermissionPoints(bundleList, debugJson);
1735- continue;
1736- }
1737- 
1738- cJSON *permissionChild = debugPermissionConfig->child;
1739- while (permissionChild != nullptr) {
1740- cJSON *permissionMountPaths = cJSON_GetArrayItem(permissionChild, 0);
1741- if (!permissionMountPaths) {
1742- permissionChild = permissionChild->next;
1743- continue;
1744- }
1745- DoUninstallDebugSandbox(bundleList, permissionMountPaths);
1746- permissionChild = permissionChild->next;
1747- }
1748 }1813 }
1749 bundleList.clear();1814 bundleList.clear();
1750 ret = GetPackageList(property, bundleList, false);1815 ret = GetPackageList(property, bundleList, false);
@@ -1800,7 +1865,8 @@ int32_t SandboxCore::DoMountDebugPoints(const AppSpawningCtx *appProperty, cJSON
1800 .mountFlags = SandboxCommon::GetMountFlags(mntPoint),1865 .mountFlags = SandboxCommon::GetMountFlags(mntPoint),
1801 .options = mountConfig.optionsPoint.c_str(),1866 .options = mountConfig.optionsPoint.c_str(),
1802 .mountSharedFlag =1867 .mountSharedFlag =
1803- GetBoolValueFromJsonObj(mntPoint, SandboxCommonDef::g_mountSharedFlag, false) ? MS_SHARED : MS_SLAVE1868+ GetBoolValueFromJsonObj(mntPoint, SandboxCommonDef::g_mountSharedFlag, false) ? MS_SHARED : MS_SLAVE,
1869+ .pathType = GetSandboxPathType(mntPoint)
1804 };1870 };
1805 int ret = SandboxCommon::DoAppSandboxMountOnce(appProperty, &arg);1871 int ret = SandboxCommon::DoAppSandboxMountOnce(appProperty, &arg);
1806 APPSPAWN_CHECK(ret == 0 || !SandboxCommon::IsMountSuccessful(mntPoint), return ret,1872 APPSPAWN_CHECK(ret == 0 || !SandboxCommon::IsMountSuccessful(mntPoint), return ret,
@@ -1876,32 +1942,105 @@ int32_t SandboxCore::InstallDebugSandbox(AppSpawnMgr *content, AppSpawningCtx *p
1876 }1942 }
1877 DoMountDebugPoints(property, debugCommonConfig);1943 DoMountDebugPoints(property, debugCommonConfig);
1878 1944 
1879- cJSON *debugPermissionConfig = GetFirstSubConfig(debugJson, SandboxCommonDef::g_permissionPrefix);1945+ DoInstallDebugPermissionPoints(property, debugJson);
1880- if (!debugPermissionConfig) {1946+ DoInstallDebugInvertedPermissionPoints(property, debugJson);
1881- continue;
1882- }
1883- 
1884- cJSON *permissionChild = debugPermissionConfig->child;
1885- while (permissionChild != nullptr) {
1886- int index = GetPermissionIndex(nullptr, permissionChild->string);
1887- if (CheckAppPermissionFlagSet(property, static_cast<uint32_t>(index)) == 0) {
1888- permissionChild = permissionChild->next;
1889- continue;
1890- }
1891- cJSON *permissionMountPaths = cJSON_GetArrayItem(permissionChild, 0);
1892- if (!permissionMountPaths) {
1893- permissionChild = permissionChild->next;
1894- continue;
1895- }
1896- DoMountDebugPoints(property, permissionMountPaths);
1897- 
1898- permissionChild = permissionChild->next;
1899- }
1900 }1947 }
1901 1948 
1902 MountDebugSharefs(property, ConvertDebugRealPath(property, SandboxCommonDef::g_mntTmpSandboxRoot).c_str(),1949 MountDebugSharefs(property, ConvertDebugRealPath(property, SandboxCommonDef::g_mntTmpSandboxRoot).c_str(),
1903 ConvertDebugRealPath(property, SandboxCommonDef::g_mntShareSandboxRoot).c_str());1950 ConvertDebugRealPath(property, SandboxCommonDef::g_mntShareSandboxRoot).c_str());
1904 return 0;1951 return 0;
1905}1952}
1953+ 
1954+int32_t SandboxCore::DoInstallDebugPermissionPoints(const AppSpawningCtx *property, cJSON *debugJson)
1955+{
1956+ cJSON *debugPermissionConfig = GetFirstSubConfig(debugJson, SandboxCommonDef::g_permissionPrefix);
1957+ if (!debugPermissionConfig) {
1958+ return 0;
1959+ }
1960+ 
1961+ cJSON *permissionChild = debugPermissionConfig->child;
1962+ while (permissionChild != nullptr) {
1963+ int index = GetPermissionIndex(nullptr, permissionChild->string);
1964+ if (CheckAppPermissionFlagSet(property, static_cast<uint32_t>(index)) == 0) {
1965+ permissionChild = permissionChild->next;
1966+ continue;
1967+ }
1968+ cJSON *permissionMountPaths = cJSON_GetArrayItem(permissionChild, 0);
1969+ if (!permissionMountPaths) {
1970+ permissionChild = permissionChild->next;
1971+ continue;
1972+ }
1973+ DoMountDebugPoints(property, permissionMountPaths);
1974+ permissionChild = permissionChild->next;
1975+ }
1976+ return 0;
1977+}
1978+ 
1979+int32_t SandboxCore::DoInstallDebugInvertedPermissionPoints(const AppSpawningCtx *property, cJSON *debugJson)
1980+{
1981+ cJSON *debugPermissionConfig = GetFirstSubConfig(debugJson, SandboxCommonDef::g_invertedPermissionPrefix);
1982+ if (!debugPermissionConfig) {
1983+ return 0;
1984+ }
1985+ 
1986+ cJSON *permissionChild = debugPermissionConfig->child;
1987+ while (permissionChild != nullptr) {
1988+ int index = GetPermissionIndex(nullptr, permissionChild->string);
1989+ if (CheckAppPermissionFlagSet(property, static_cast<uint32_t>(index)) != 0) {
1990+ APPSPAWN_LOGV("Skip debug inverted-permission %{public}s as app has the permission",
1991+ permissionChild->string);
1992+ permissionChild = permissionChild->next;
1993+ continue;
1994+ }
1995+ cJSON *permissionMountPaths = cJSON_GetArrayItem(permissionChild, 0);
1996+ if (!permissionMountPaths) {
1997+ permissionChild = permissionChild->next;
1998+ continue;
1999+ }
2000+ DoMountDebugPoints(property, permissionMountPaths);
2001+ permissionChild = permissionChild->next;
2002+ }
2003+ return 0;
2004+}
2005+ 
2006+int32_t SandboxCore::DoUninstallDebugPermissionPoints(std::vector<std::string> &bundleList, cJSON *debugJson)
2007+{
2008+ cJSON *debugPermissionConfig = GetFirstSubConfig(debugJson, SandboxCommonDef::g_permissionPrefix);
2009+ if (!debugPermissionConfig) {
2010+ return 0;
2011+ }
2012+ 
2013+ cJSON *permissionChild = debugPermissionConfig->child;
2014+ while (permissionChild != nullptr) {
2015+ cJSON *permissionMountPaths = cJSON_GetArrayItem(permissionChild, 0);
2016+ if (!permissionMountPaths) {
2017+ permissionChild = permissionChild->next;
2018+ continue;
2019+ }
2020+ DoUninstallDebugSandbox(bundleList, permissionMountPaths);
2021+ permissionChild = permissionChild->next;
2022+ }
2023+ return 0;
2024+}
2025+ 
2026+int32_t SandboxCore::DoUninstallDebugInvertedPermissionPoints(std::vector<std::string> &bundleList, cJSON *debugJson)
2027+{
2028+ cJSON *debugPermissionConfig = GetFirstSubConfig(debugJson, SandboxCommonDef::g_invertedPermissionPrefix);
2029+ if (!debugPermissionConfig) {
2030+ return 0;
2031+ }
2032+ 
2033+ cJSON *permissionChild = debugPermissionConfig->child;
2034+ while (permissionChild != nullptr) {
2035+ cJSON *permissionMountPaths = cJSON_GetArrayItem(permissionChild, 0);
2036+ if (!permissionMountPaths) {
2037+ permissionChild = permissionChild->next;
2038+ continue;
2039+ }
2040+ DoUninstallDebugSandbox(bundleList, permissionMountPaths);
2041+ permissionChild = permissionChild->next;
2042+ }
2043+ return 0;
2044+}
1906} // namespace AppSpawn2045} // namespace AppSpawn
1907} // namespace OHOS2046} // namespace OHOS
@@ -56,6 +56,7 @@ public:
56 static int32_t SetCommonAppSandboxProperty(const AppSpawningCtx *appProperty, std::string &sandboxPackagePath);56 static int32_t SetCommonAppSandboxProperty(const AppSpawningCtx *appProperty, std::string &sandboxPackagePath);
57 static int32_t SetPrivateAppSandboxProperty(const AppSpawningCtx *appProperty);57 static int32_t SetPrivateAppSandboxProperty(const AppSpawningCtx *appProperty);
58 static int32_t SetPermissionAppSandboxProperty(AppSpawningCtx *appProperty);58 static int32_t SetPermissionAppSandboxProperty(AppSpawningCtx *appProperty);
59+ static int32_t SetInvertedPermissionAppSandboxProperty(AppSpawningCtx *appProperty);
59 static int32_t SetSandboxProperty(AppSpawningCtx *appProperty, std::string &sandboxPackagePath);60 static int32_t SetSandboxProperty(AppSpawningCtx *appProperty, std::string &sandboxPackagePath);
60 static int32_t SetAppSandboxProperty(AppSpawnMgr *content, AppSpawningCtx *appProperty,61 static int32_t SetAppSandboxProperty(AppSpawnMgr *content, AppSpawningCtx *appProperty,
61 uint32_t sandboxNsFlags = CLONE_NEWNS);62 uint32_t sandboxNsFlags = CLONE_NEWNS);
@@ -90,6 +91,7 @@ private:
90 static int32_t UpdatePointFlags(AppSpawningCtx *appProperty);91 static int32_t UpdatePointFlags(AppSpawningCtx *appProperty);
91 static std::string GetSandboxPath(const AppSpawningCtx *appProperty, cJSON *mntPoint,92 static std::string GetSandboxPath(const AppSpawningCtx *appProperty, cJSON *mntPoint,
92 const std::string &section, std::string sandboxRoot);93 const std::string &section, std::string sandboxRoot);
94+ static SandboxPathType GetSandboxPathType(cJSON *mntPoint);
93 95 
94 // 解析挂载信息公共函数96 // 解析挂载信息公共函数
95 static cJSON *GetFirstCommonConfig(cJSON *wholeConfig, const char *prefix);97 static cJSON *GetFirstCommonConfig(cJSON *wholeConfig, const char *prefix);
@@ -112,6 +114,10 @@ private:
112 static int32_t DoSandboxFilePermissionBind(AppSpawningCtx *appProperty, cJSON *wholeConfig);114 static int32_t DoSandboxFilePermissionBind(AppSpawningCtx *appProperty, cJSON *wholeConfig);
113 static int32_t SetPermissionAppSandboxProperty_(AppSpawningCtx *appProperty, cJSON *config);115 static int32_t SetPermissionAppSandboxProperty_(AppSpawningCtx *appProperty, cJSON *config);
114 116 
117+ // 处理应用基于反向权限挂载
118+ static int32_t DoSandboxFileInvertedPermissionBind(AppSpawningCtx *appProperty, cJSON *wholeConfig);
119+ static int32_t SetInvertedPermissionAppSandboxProperty_(AppSpawningCtx *appProperty, cJSON *config);
120+ 
115 // 处理应用公共挂载121 // 处理应用公共挂载
116 static int32_t DoSandboxFileCommonBind(const AppSpawningCtx *appProperty, cJSON *wholeConfig);122 static int32_t DoSandboxFileCommonBind(const AppSpawningCtx *appProperty, cJSON *wholeConfig);
117 static int32_t DoSandboxFileCommonSymlink(const AppSpawningCtx *appProperty, cJSON *wholeConfig);123 static int32_t DoSandboxFileCommonSymlink(const AppSpawningCtx *appProperty, cJSON *wholeConfig);
@@ -137,6 +143,12 @@ private:
137 static int32_t DoMountDebugPoints(const AppSpawningCtx *appProperty, cJSON *appConfig);143 static int32_t DoMountDebugPoints(const AppSpawningCtx *appProperty, cJSON *appConfig);
138 static int32_t MountDebugSharefs(const AppSpawningCtx *property, const char *src, const char *target);144 static int32_t MountDebugSharefs(const AppSpawningCtx *property, const char *src, const char *target);
139 145 
146+ // debug permission and inverted-permission
147+ static int32_t DoInstallDebugPermissionPoints(const AppSpawningCtx *property, cJSON *debugJson);
148+ static int32_t DoInstallDebugInvertedPermissionPoints(const AppSpawningCtx *property, cJSON *debugJson);
149+ static int32_t DoUninstallDebugPermissionPoints(std::vector<std::string> &bundleList, cJSON *debugJson);
150+ static int32_t DoUninstallDebugInvertedPermissionPoints(std::vector<std::string> &bundleList, cJSON *debugJson);
151+ 
140 // 处理拥有沙箱权限应用的挂载152 // 处理拥有沙箱权限应用的挂载
141 static void GetSpecialMountCondition(bool &isPreInstalled, bool &isHaveSandBoxPermission,153 static void GetSpecialMountCondition(bool &isPreInstalled, bool &isHaveSandBoxPermission,
142 const AppSpawningCtx *appProperty);154 const AppSpawningCtx *appProperty);
@@ -52,6 +52,7 @@ const std::string g_ohosRender = "__internal__.com.ohos.render";
52constexpr const char *g_commonPrefix = "common";52constexpr const char *g_commonPrefix = "common";
53constexpr const char *g_privatePrefix = "individual";53constexpr const char *g_privatePrefix = "individual";
54constexpr const char *g_permissionPrefix = "permission";54constexpr const char *g_permissionPrefix = "permission";
55+constexpr const char *g_invertedPermissionPrefix = "inverted-permission";
55constexpr const char *g_appBase = "app-base";56constexpr const char *g_appBase = "app-base";
56constexpr const char *g_appResources = "app-resources";57constexpr const char *g_appResources = "app-resources";
57constexpr const char *g_appNocheck = "app-nocheck";58constexpr const char *g_appNocheck = "app-nocheck";
@@ -82,6 +83,8 @@ constexpr const char *g_sandBoxOptions = "options";
82constexpr const char *g_actionStatuc = "check-action-status";83constexpr const char *g_actionStatuc = "check-action-status";
83constexpr const char *g_destMode = "dest-mode";84constexpr const char *g_destMode = "dest-mode";
84constexpr const char *g_flags = "flags";85constexpr const char *g_flags = "flags";
86+constexpr const char *g_pathType = "path-type";
87+constexpr const char *g_pathTypeFile = "file";
85 88 
86// param参数配置字段89// param参数配置字段
87constexpr const char *g_preParamPath = "pre-param-src-path";90constexpr const char *g_preParamPath = "pre-param-src-path";
@@ -44,6 +44,11 @@ enum {
44 ELX_MAX44 ELX_MAX
45};45};
46 46 
47+enum SandboxPathType {
48+ SANDBOX_DIR_PATH = 0,
49+ SANDBOX_FILE_PATH,
50+};
51+ 
47typedef struct DataGroupSandboxPathTemplate {52typedef struct DataGroupSandboxPathTemplate {
48 const char *elxName;53 const char *elxName;
49 uint32_t category;54 uint32_t category;
@@ -58,6 +63,7 @@ struct SharedMountArgs {
58 unsigned long mountFlags = MS_REC | MS_BIND;63 unsigned long mountFlags = MS_REC | MS_BIND;
59 const char *options = "";64 const char *options = "";
60 mode_t mountSharedFlag = MS_SLAVE;65 mode_t mountSharedFlag = MS_SLAVE;
66+ SandboxPathType pathType = SANDBOX_DIR_PATH;
61};67};
62 68 
63// Lock bundle info structure for _preunlock directory management69// Lock bundle info structure for _preunlock directory management
@@ -1278,4 +1278,118 @@ HWTEST_F(AppSpawnSandboxCommonTest, App_Spawn_SandboxCommon_GetDecReadOnlyPath_0
1278 EXPECT_EQ(result.size(), 0);1278 EXPECT_EQ(result.size(), 0);
1279}1279}
1280 1280 
1281+// ==================== 反向权限相关测试 ====================
1282+ 
1283+/**
1284+ * @tc.name: App_Spawn_SandboxCommon_GetSandboxMountConfig_InvertedPermission_01
1285+ * @tc.desc: Test GetSandboxMountConfig with inverted-permission section
1286+ * @tc.type: FUNC
1287+ */
1288+HWTEST_F(
1289+ AppSpawnSandboxCommonTest, App_Spawn_SandboxCommon_GetSandboxMountConfig_InvertedPermission_01, TestSize.Level0)
1290+{
1291+ AppSpawningCtx *appProperty = AppSpawn::GetTestAppPropertyCore();
1292+ ASSERT_NE(appProperty, nullptr);
1293+ 
1294+ const char *configStr = R"({
1295+ "src-path": "/data/test/src",
1296+ "sandbox-path": "/data/test/dest",
1297+ "fs-type": "ext4",
1298+ "options": "rw",
1299+ "dec-paths": ["/data/dec/path1"],
1300+ "dec-readonly-paths": ["/data/dec/readonly1"]
1301+ })";
1302+ cJSON *mntPoint = cJSON_Parse(configStr);
1303+ ASSERT_NE(mntPoint, nullptr);
1304+ 
1305+ std::string section = "inverted-permission";
1306+ AppSpawn::SandboxMountConfig mountConfig;
1307+ AppSpawn::SandboxCommon::GetSandboxMountConfig(appProperty, section, mntPoint, mountConfig);
1308+ 
1309+ EXPECT_EQ(mountConfig.fsType, "ext4");
1310+ EXPECT_EQ(mountConfig.decPaths.size(), 1);
1311+ EXPECT_EQ(mountConfig.decReadOnlyPaths.size(), 1);
1312+ EXPECT_EQ(mountConfig.optionsPoint, "rw,user_id=100");
1313+ 
1314+ cJSON_Delete(mntPoint);
1315+ DeleteAppSpawningCtx(appProperty);
1316+}
1317+ 
1318+/**
1319+ * @tc.name: App_Spawn_SandboxCommon_CreateDummyPaths_01
1320+ * @tc.desc: Test CreateDummyPaths creates dummy file and dir
1321+ * @tc.type: FUNC
1322+ */
1323+HWTEST_F(AppSpawnSandboxCommonTest, App_Spawn_SandboxCommon_CreateDummyPaths_01, TestSize.Level0)
1324+{
1325+ int32_t ret = AppSpawn::SandboxCommon::CreateDummyPaths(nullptr);
1326+ EXPECT_EQ(ret, 0);
1327+}
1328+ 
1329+/**
1330+ * @tc.name: App_Spawn_SandboxCommon_DoAppSandboxMountOnce_FilePathType_01
1331+ * @tc.desc: Test DoAppSandboxMountOnce with SANDBOX_FILE_PATH path type
1332+ * @tc.type: FUNC
1333+ */
1334+HWTEST_F(AppSpawnSandboxCommonTest, App_Spawn_SandboxCommon_DoAppSandboxMountOnce_FilePathType_01, TestSize.Level0)
1335+{
1336+ SharedMountArgs arg;
1337+ arg.srcPath = "/data/test/src_file";
1338+ arg.destPath = "/data/test/dest_file";
1339+ arg.pathType = SANDBOX_FILE_PATH;
1340+ 
1341+ int32_t ret = AppSpawn::SandboxCommon::DoAppSandboxMountOnce(nullptr, &arg);
1342+ EXPECT_EQ(ret, 0);
1343+}
1344+ 
1345+/**
1346+ * @tc.name: App_Spawn_SandboxCommon_DoAppSandboxMountOnce_DirPathType_01
1347+ * @tc.desc: Test DoAppSandboxMountOnce with SANDBOX_DIR_PATH path type
1348+ * @tc.type: FUNC
1349+ */
1350+HWTEST_F(AppSpawnSandboxCommonTest, App_Spawn_SandboxCommon_DoAppSandboxMountOnce_DirPathType_01, TestSize.Level0)
1351+{
1352+ SharedMountArgs arg;
1353+ arg.srcPath = "/data/test/src_dir";
1354+ arg.destPath = "/data/test/dest_dir";
1355+ arg.pathType = SANDBOX_DIR_PATH;
1356+ 
1357+ int32_t ret = AppSpawn::SandboxCommon::DoAppSandboxMountOnce(nullptr, &arg);
1358+ EXPECT_EQ(ret, 0);
1359+}
1360+ 
1361+/**
1362+ * @tc.name: App_Spawn_SandboxCommon_DoAppSandboxMountOnceNocheck_FilePathType_01
1363+ * @tc.desc: Test DoAppSandboxMountOnceNocheck with SANDBOX_FILE_PATH path type
1364+ * @tc.type: FUNC
1365+ */
1366+HWTEST_F(
1367+ AppSpawnSandboxCommonTest, App_Spawn_SandboxCommon_DoAppSandboxMountOnceNocheck_FilePathType_01, TestSize.Level0)
1368+{
1369+ SharedMountArgs arg;
1370+ arg.srcPath = "/data/test/src_file";
1371+ arg.destPath = "/data/test/dest_file";
1372+ arg.pathType = SANDBOX_FILE_PATH;
1373+ 
1374+ int32_t ret = AppSpawn::SandboxCommon::DoAppSandboxMountOnceNocheck(nullptr, &arg);
1375+ EXPECT_EQ(ret, 0);
1376+}
1377+ 
1378+/**
1379+ * @tc.name: App_Spawn_SandboxCommon_DoAppSandboxMountOnceNocheck_DirPathType_01
1380+ * @tc.desc: Test DoAppSandboxMountOnceNocheck with SANDBOX_DIR_PATH path type
1381+ * @tc.type: FUNC
1382+ */
1383+HWTEST_F(
1384+ AppSpawnSandboxCommonTest, App_Spawn_SandboxCommon_DoAppSandboxMountOnceNocheck_DirPathType_01, TestSize.Level0)
1385+{
1386+ SharedMountArgs arg;
1387+ arg.srcPath = "/data/test/src_dir";
1388+ arg.destPath = "/data/test/dest_dir";
1389+ arg.pathType = SANDBOX_DIR_PATH;
1390+ 
1391+ int32_t ret = AppSpawn::SandboxCommon::DoAppSandboxMountOnceNocheck(nullptr, &arg);
1392+ EXPECT_EQ(ret, 0);
1393+}
1394+ 
1281} // namespace OHOS1395} // namespace OHOS
@@ -541,4 +541,727 @@ HWTEST_F(AppSpawnSandboxCoreTest, SetPermissionAppSandboxProperty_01, TestSize.L
541 DeleteAppSpawningCtx(appProperty);541 DeleteAppSpawningCtx(appProperty);
542}542}
543 543 
544+// ==================== 普通权限 Debug 相关测试 ====================
545+ 
546+/**
547+ * @tc.name: DoInstallDebugPermissionPoints_01
548+ * @tc.desc: Test debug install permission points with null json
549+ * @tc.type: FUNC
550+ * @tc.require: issueI5NTX6
551+ */
552+HWTEST_F(AppSpawnSandboxCoreTest, DoInstallDebugPermissionPoints_01, TestSize.Level0)
553+{
554+ g_testHelperCore.SetProcessName("com.ohos.debug.app");
555+ g_testHelperCore.SetTestApl("normal");
556+ 
557+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
558+ ASSERT_NE(appProperty, nullptr);
559+ 
560+ cJSON *debugJson = nullptr;
561+ int ret = AppSpawn::SandboxCore::DoInstallDebugPermissionPoints(appProperty, debugJson);
562+ EXPECT_EQ(ret, 0);
563+ 
564+ DeleteAppSpawningCtx(appProperty);
565+}
566+ 
567+/**
568+ * @tc.name: DoInstallDebugPermissionPoints_02
569+ * @tc.desc: Test debug install permission points with valid config but app does NOT have
570+ * the permission (unregistered name), should skip mount
571+ * @tc.type: FUNC
572+ * @tc.require: issueI5NTX6
573+ */
574+HWTEST_F(AppSpawnSandboxCoreTest, DoInstallDebugPermissionPoints_02, TestSize.Level0)
575+{
576+ g_testHelperCore.SetProcessName("com.ohos.debug.app");
577+ g_testHelperCore.SetTestApl("normal");
578+ 
579+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
580+ ASSERT_NE(appProperty, nullptr);
581+ 
582+ // Use an unregistered permission name so CheckAppPermissionFlagSet returns 0
583+ // (app does NOT have the permission), the mount is skipped.
584+ const char *configStr = R"({
585+ "permission": [
586+ {
587+ "ohos.permission.UNREGISTERED_TEST": {
588+ "mount-paths": [
589+ {
590+ "src-path": "/data/test/debug/src",
591+ "sandbox-path": "/data/test/debug/dest"
592+ }
593+ ]
594+ }
595+ }
596+ ]
597+ })";
598+ cJSON *debugJson = cJSON_Parse(configStr);
599+ ASSERT_NE(debugJson, nullptr);
600+ int ret = AppSpawn::SandboxCore::DoInstallDebugPermissionPoints(appProperty, debugJson);
601+ EXPECT_EQ(ret, 0);
602+ 
603+ cJSON_Delete(debugJson);
604+ DeleteAppSpawningCtx(appProperty);
605+}
606+ 
607+/**
608+ * @tc.name: DoInstallDebugPermissionPoints_03
609+ * @tc.desc: Test debug install permission points with valid config and app HAS the
610+ * registered permission (FILE_ACCESS_MANAGER), should mount
611+ * @tc.type: FUNC
612+ * @tc.require: issueI5NTX6
613+ */
614+HWTEST_F(AppSpawnSandboxCoreTest, DoInstallDebugPermissionPoints_03, TestSize.Level0)
615+{
616+ g_testHelperCore.SetProcessName("com.ohos.debug.app");
617+ g_testHelperCore.SetTestApl("normal");
618+ 
619+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
620+ ASSERT_NE(appProperty, nullptr);
621+ 
622+ // Set the permission flag for a registered permission so that
623+ // CheckAppPermissionFlagSet returns non-zero (app has the permission).
624+ int index = GetPermissionIndex(nullptr, "ohos.permission.FILE_ACCESS_MANAGER");
625+ ASSERT_GE(index, 0);
626+ int ret = SetAppPermissionFlags(appProperty, static_cast<uint32_t>(index));
627+ EXPECT_EQ(ret, 0);
628+ 
629+ const char *configStr = R"({
630+ "permission": [
631+ {
632+ "ohos.permission.FILE_ACCESS_MANAGER": {
633+ "mount-paths": [
634+ {
635+ "src-path": "/data/test/debug/src",
636+ "sandbox-path": "/data/test/debug/dest"
637+ }
638+ ]
639+ }
640+ }
641+ ]
642+ })";
643+ cJSON *debugJson = cJSON_Parse(configStr);
644+ ASSERT_NE(debugJson, nullptr);
645+ ret = AppSpawn::SandboxCore::DoInstallDebugPermissionPoints(appProperty, debugJson);
646+ EXPECT_EQ(ret, 0);
647+ 
648+ cJSON_Delete(debugJson);
649+ DeleteAppSpawningCtx(appProperty);
650+}
651+ 
652+/**
653+ * @tc.name: DoInstallDebugPermissionPoints_04
654+ * @tc.desc: Test debug install permission points with empty permission child (no array items),
655+ * permissionMountPaths is null, should skip
656+ * @tc.type: FUNC
657+ * @tc.require: issueI5NTX6
658+ */
659+HWTEST_F(AppSpawnSandboxCoreTest, DoInstallDebugPermissionPoints_04, TestSize.Level0)
660+{
661+ g_testHelperCore.SetProcessName("com.ohos.debug.app");
662+ g_testHelperCore.SetTestApl("normal");
663+ 
664+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
665+ ASSERT_NE(appProperty, nullptr);
666+ 
667+ // The permission child value is an empty object {}, so cJSON_GetArrayItem(child, 0)
668+ // returns null and the !permissionMountPaths branch is taken.
669+ // Set the permission flag so that CheckAppPermissionFlagSet returns non-zero,
670+ // allowing the code to reach the !permissionMountPaths check.
671+ int index = GetPermissionIndex(nullptr, "ohos.permission.FILE_ACCESS_MANAGER");
672+ ASSERT_GE(index, 0);
673+ int ret = SetAppPermissionFlags(appProperty, static_cast<uint32_t>(index));
674+ EXPECT_EQ(ret, 0);
675+ 
676+ const char *configStr = R"({
677+ "permission": [
678+ {
679+ "ohos.permission.FILE_ACCESS_MANAGER": {}
680+ }
681+ ]
682+ })";
683+ cJSON *debugJson = cJSON_Parse(configStr);
684+ ASSERT_NE(debugJson, nullptr);
685+ ret = AppSpawn::SandboxCore::DoInstallDebugPermissionPoints(appProperty, debugJson);
686+ EXPECT_EQ(ret, 0);
687+ 
688+ cJSON_Delete(debugJson);
689+ DeleteAppSpawningCtx(appProperty);
690+}
691+ 
692+/**
693+ * @tc.name: DoUninstallDebugPermissionPoints_01
694+ * @tc.desc: Test debug uninstall permission points with null json
695+ * @tc.type: FUNC
696+ * @tc.require: issueI5NTX6
697+ */
698+HWTEST_F(AppSpawnSandboxCoreTest, DoUninstallDebugPermissionPoints_01, TestSize.Level0)
699+{
700+ std::vector<std::string> bundleList;
701+ cJSON *debugJson = nullptr;
702+ int ret = AppSpawn::SandboxCore::DoUninstallDebugPermissionPoints(bundleList, debugJson);
703+ EXPECT_EQ(ret, 0);
704+}
705+ 
706+/**
707+ * @tc.name: DoUninstallDebugPermissionPoints_02
708+ * @tc.desc: Test debug uninstall permission points with valid config and mount-paths,
709+ * should uninstall
710+ * @tc.type: FUNC
711+ * @tc.require: issueI5NTX6
712+ */
713+HWTEST_F(AppSpawnSandboxCoreTest, DoUninstallDebugPermissionPoints_02, TestSize.Level0)
714+{
715+ std::vector<std::string> bundleList;
716+ bundleList.push_back("com.ohos.test.app");
717+ 
718+ const char *configStr = R"({
719+ "permission": [
720+ {
721+ "ohos.permission.FILE_ACCESS_MANAGER": {
722+ "mount-paths": [
723+ {
724+ "src-path": "/data/test/debug/src",
725+ "sandbox-path": "/data/test/debug/dest"
726+ }
727+ ]
728+ }
729+ }
730+ ]
731+ })";
732+ cJSON *debugJson = cJSON_Parse(configStr);
733+ ASSERT_NE(debugJson, nullptr);
734+ int ret = AppSpawn::SandboxCore::DoUninstallDebugPermissionPoints(bundleList, debugJson);
735+ EXPECT_EQ(ret, 0);
736+ 
737+ cJSON_Delete(debugJson);
738+}
739+ 
740+/**
741+ * @tc.name: DoUninstallDebugPermissionPoints_03
742+ * @tc.desc: Test debug uninstall permission points with empty permission child (no array items),
743+ * permissionMountPaths is null, should skip
744+ * @tc.type: FUNC
745+ * @tc.require: issueI5NTX6
746+ */
747+HWTEST_F(AppSpawnSandboxCoreTest, DoUninstallDebugPermissionPoints_03, TestSize.Level0)
748+{
749+ std::vector<std::string> bundleList;
750+ bundleList.push_back("com.ohos.test.app");
751+ 
752+ // The permission child value is an empty object {}, so cJSON_GetArrayItem(child, 0)
753+ // returns null and the !permissionMountPaths branch is taken.
754+ const char *configStr = R"({
755+ "permission": [
756+ {
757+ "ohos.permission.TEST_INVERTED": {}
758+ }
759+ ]
760+ })";
761+ cJSON *debugJson = cJSON_Parse(configStr);
762+ ASSERT_NE(debugJson, nullptr);
763+ int ret = AppSpawn::SandboxCore::DoUninstallDebugPermissionPoints(bundleList, debugJson);
764+ EXPECT_EQ(ret, 0);
765+ 
766+ cJSON_Delete(debugJson);
767+}
768+ 
769+// ==================== 反向权限文件相关测试 ====================
770+ 
771+/**
772+ * @tc.name: DoSandboxFileInvertedPermissionBind_01
773+ * @tc.desc: Test inverted-permission file binding with null config
774+ * @tc.type: FUNC
775+ * @tc.require: issueI5NTX6
776+ */
777+HWTEST_F(AppSpawnSandboxCoreTest, DoSandboxFileInvertedPermissionBind_01, TestSize.Level0)
778+{
779+ g_testHelperCore.SetProcessName("com.ohos.inverted.app");
780+ g_testHelperCore.SetTestApl("normal");
781+ 
782+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
783+ ASSERT_NE(appProperty, nullptr);
784+ 
785+ cJSON *wholeConfig = nullptr;
786+ int ret = AppSpawn::SandboxCore::DoSandboxFileInvertedPermissionBind(appProperty, wholeConfig);
787+ EXPECT_EQ(ret, 0);
788+ 
789+ DeleteAppSpawningCtx(appProperty);
790+}
791+ 
792+/**
793+ * @tc.name: DoSandboxFileInvertedPermissionBind_02
794+ * @tc.desc: Test inverted-permission file binding with valid config (app without permission, should mount)
795+ * @tc.type: FUNC
796+ * @tc.require: issueI5NTX6
797+ */
798+HWTEST_F(AppSpawnSandboxCoreTest, DoSandboxFileInvertedPermissionBind_02, TestSize.Level0)
799+{
800+ g_testHelperCore.SetProcessName("com.ohos.inverted.app");
801+ g_testHelperCore.SetTestApl("normal");
802+ 
803+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
804+ ASSERT_NE(appProperty, nullptr);
805+ 
806+ const char *configStr = R"({
807+ "inverted-permission": [
808+ {
809+ "ohos.permission.TEST_INVERTED": {
810+ "mount-paths": [
811+ {
812+ "src-path": "/data/test/inverted/src",
813+ "sandbox-path": "/data/test/inverted/dest"
814+ }
815+ ]
816+ }
817+ }
818+ ]
819+ })";
820+ cJSON *wholeConfig = cJSON_Parse(configStr);
821+ ASSERT_NE(wholeConfig, nullptr);
822+ int ret = AppSpawn::SandboxCore::DoSandboxFileInvertedPermissionBind(appProperty, wholeConfig);
823+ EXPECT_EQ(ret, 0);
824+ 
825+ cJSON_Delete(wholeConfig);
826+ DeleteAppSpawningCtx(appProperty);
827+}
828+ 
829+/**
830+ * @tc.name: DoSandboxFileInvertedPermissionBind_03
831+ * @tc.desc: Test inverted-permission with app having the permission (should skip mount)
832+ * @tc.type: FUNC
833+ * @tc.require: issueI5NTX6
834+ */
835+HWTEST_F(AppSpawnSandboxCoreTest, DoSandboxFileInvertedPermissionBind_03, TestSize.Level0)
836+{
837+ g_testHelperCore.SetProcessName("com.ohos.inverted.app");
838+ g_testHelperCore.SetTestApl("normal");
839+ std::vector<const char *> &permissions = g_testHelperCore.GetPermissions();
840+ permissions.push_back("ohos.permission.FILE_CROSS_APP");
841+ 
842+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
843+ ASSERT_NE(appProperty, nullptr);
844+ 
845+ const char *configStr = R"({
846+ "inverted-permission": [
847+ {
848+ "ohos.permission.FILE_CROSS_APP": {
849+ "mount-paths": [
850+ {
851+ "src-path": "/data/test/inverted/src",
852+ "sandbox-path": "/data/test/inverted/dest"
853+ }
854+ ]
855+ }
856+ }
857+ ]
858+ })";
859+ cJSON *wholeConfig = cJSON_Parse(configStr);
860+ ASSERT_NE(wholeConfig, nullptr);
861+ int ret = AppSpawn::SandboxCore::DoSandboxFileInvertedPermissionBind(appProperty, wholeConfig);
862+ EXPECT_EQ(ret, 0);
863+ 
864+ cJSON_Delete(wholeConfig);
865+ DeleteAppSpawningCtx(appProperty);
866+}
867+ 
868+/**
869+ * @tc.name: DoSandboxFileInvertedPermissionBind_04
870+ * @tc.desc: Test inverted-permission with app having a registered permission (FILE_ACCESS_MANAGER),
871+ * should skip mount and cover line 366 TRUE branch
872+ * @tc.type: FUNC
873+ * @tc.require: issueI5NTX6
874+ */
875+HWTEST_F(AppSpawnSandboxCoreTest, DoSandboxFileInvertedPermissionBind_04, TestSize.Level0)
876+{
877+ g_testHelperCore.SetProcessName("com.ohos.inverted.app");
878+ g_testHelperCore.SetTestApl("normal");
879+ 
880+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
881+ ASSERT_NE(appProperty, nullptr);
882+ 
883+ // Set the permission flag for a registered permission so that
884+ // CheckAppPermissionFlagSet returns non-zero (app has the permission).
885+ int index = GetPermissionIndex(nullptr, "ohos.permission.FILE_ACCESS_MANAGER");
886+ ASSERT_GE(index, 0);
887+ int ret = SetAppPermissionFlags(appProperty, static_cast<uint32_t>(index));
888+ EXPECT_EQ(ret, 0);
889+ 
890+ const char *configStr = R"({
891+ "inverted-permission": [
892+ {
893+ "ohos.permission.FILE_ACCESS_MANAGER": {
894+ "mount-paths": [
895+ {
896+ "src-path": "/data/test/inverted/src",
897+ "sandbox-path": "/data/test/inverted/dest"
898+ }
899+ ]
900+ }
901+ }
902+ ]
903+ })";
904+ cJSON *wholeConfig = cJSON_Parse(configStr);
905+ ASSERT_NE(wholeConfig, nullptr);
906+ ret = AppSpawn::SandboxCore::DoSandboxFileInvertedPermissionBind(appProperty, wholeConfig);
907+ EXPECT_EQ(ret, 0);
908+ 
909+ cJSON_Delete(wholeConfig);
910+ DeleteAppSpawningCtx(appProperty);
911+}
912+ 
913+/**
914+ * @tc.name: DoSandboxFileInvertedPermissionBind_05
915+ * @tc.desc: Test inverted-permission with empty permission child (no mount-paths array),
916+ * permissionMountPaths is null, cover line 372 TRUE branch
917+ * @tc.type: FUNC
918+ * @tc.require: issueI5NTX6
919+ */
920+HWTEST_F(AppSpawnSandboxCoreTest, DoSandboxFileInvertedPermissionBind_05, TestSize.Level0)
921+{
922+ g_testHelperCore.SetProcessName("com.ohos.inverted.app");
923+ g_testHelperCore.SetTestApl("normal");
924+ 
925+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
926+ ASSERT_NE(appProperty, nullptr);
927+ 
928+ // The permission child value is an empty object {}, so cJSON_GetArrayItem(child, 0)
929+ // returns null and the !permissionMountPaths branch (line 372) is taken.
930+ const char *configStr = R"({
931+ "inverted-permission": [
932+ {
933+ "ohos.permission.TEST_INVERTED": {}
934+ }
935+ ]
936+ })";
937+ cJSON *wholeConfig = cJSON_Parse(configStr);
938+ ASSERT_NE(wholeConfig, nullptr);
939+ int ret = AppSpawn::SandboxCore::DoSandboxFileInvertedPermissionBind(appProperty, wholeConfig);
940+ EXPECT_EQ(ret, 0);
941+ 
942+ cJSON_Delete(wholeConfig);
943+ DeleteAppSpawningCtx(appProperty);
944+}
945+ 
946+/**
947+ * @tc.name: SetInvertedPermissionAppSandboxProperty__01
948+ * @tc.desc: Test inverted-permission app sandbox property setting with null config
949+ * @tc.type: FUNC
950+ * @tc.require: issueI5NTX6
951+ */
952+HWTEST_F(AppSpawnSandboxCoreTest, SetInvertedPermissionAppSandboxProperty__01, TestSize.Level0)
953+{
954+ g_testHelperCore.SetProcessName("com.ohos.inverted.app");
955+ g_testHelperCore.SetTestApl("normal");
956+ 
957+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
958+ ASSERT_NE(appProperty, nullptr);
959+ 
960+ cJSON *config = nullptr;
961+ int ret = AppSpawn::SandboxCore::SetInvertedPermissionAppSandboxProperty_(appProperty, config);
962+ EXPECT_EQ(ret, 0);
963+ 
964+ DeleteAppSpawningCtx(appProperty);
965+}
966+ 
967+/**
968+ * @tc.name: SetInvertedPermissionAppSandboxProperty_01
969+ * @tc.desc: Test inverted-permission app sandbox property setting
970+ * @tc.type: FUNC
971+ * @tc.require: issueI5NTX6
972+ */
973+HWTEST_F(AppSpawnSandboxCoreTest, SetInvertedPermissionAppSandboxProperty_01, TestSize.Level0)
974+{
975+ g_testHelperCore.SetProcessName("com.ohos.inverted.app");
976+ g_testHelperCore.SetTestApl("normal");
977+ 
978+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
979+ ASSERT_NE(appProperty, nullptr);
980+ 
981+ int ret = AppSpawn::SandboxCore::SetInvertedPermissionAppSandboxProperty(appProperty);
982+ EXPECT_EQ(ret, 0);
983+ 
984+ DeleteAppSpawningCtx(appProperty);
985+}
986+ 
987+/**
988+ * @tc.name: GetSandboxPathType_01
989+ * @tc.desc: Test GetSandboxPathType with no path-type field (default dir)
990+ * @tc.type: FUNC
991+ * @tc.require: issueI5NTX6
992+ */
993+HWTEST_F(AppSpawnSandboxCoreTest, GetSandboxPathType_01, TestSize.Level0)
994+{
995+ const char *configStr = R"({"src-path": "/data/test/src"})";
996+ cJSON *mntPoint = cJSON_Parse(configStr);
997+ ASSERT_NE(mntPoint, nullptr);
998+ 
999+ auto pathType = AppSpawn::SandboxCore::GetSandboxPathType(mntPoint);
1000+ EXPECT_EQ(pathType, SANDBOX_DIR_PATH);
1001+ 
1002+ cJSON_Delete(mntPoint);
1003+}
1004+ 
1005+/**
1006+ * @tc.name: GetSandboxPathType_02
1007+ * @tc.desc: Test GetSandboxPathType with path-type "file"
1008+ * @tc.type: FUNC
1009+ * @tc.require: issueI5NTX6
1010+ */
1011+HWTEST_F(AppSpawnSandboxCoreTest, GetSandboxPathType_02, TestSize.Level0)
1012+{
1013+ const char *configStr = R"({"src-path": "/data/test/src", "path-type": "file"})";
1014+ cJSON *mntPoint = cJSON_Parse(configStr);
1015+ ASSERT_NE(mntPoint, nullptr);
1016+ 
1017+ auto pathType = AppSpawn::SandboxCore::GetSandboxPathType(mntPoint);
1018+ EXPECT_EQ(pathType, SANDBOX_FILE_PATH);
1019+ 
1020+ cJSON_Delete(mntPoint);
1021+}
1022+ 
1023+/**
1024+ * @tc.name: GetSandboxPathType_03
1025+ * @tc.desc: Test GetSandboxPathType with path-type set to a non-"file" string (covers the fall-through return
1026+ * SANDBOX_DIR_PATH at L713 when pathTypeStr is not null but not "file")
1027+ * @tc.type: FUNC
1028+ * @tc.require: issueI5NTX6
1029+ */
1030+HWTEST_F(AppSpawnSandboxCoreTest, GetSandboxPathType_03, TestSize.Level0)
1031+{
1032+ const char *configStr = R"({"src-path": "/data/test/src", "path-type": "directory"})";
1033+ cJSON *mntPoint = cJSON_Parse(configStr);
1034+ ASSERT_NE(mntPoint, nullptr);
1035+ 
1036+ auto pathType = AppSpawn::SandboxCore::GetSandboxPathType(mntPoint);
1037+ // pathTypeStr is not null and not "file", should return SANDBOX_DIR_PATH
1038+ EXPECT_EQ(pathType, SANDBOX_DIR_PATH);
1039+ 
1040+ cJSON_Delete(mntPoint);
1041+}
1042+ 
1043+/**
1044+ * @tc.name: DoInstallDebugInvertedPermissionPoints_01
1045+ * @tc.desc: Test debug install inverted-permission points with null json
1046+ * @tc.type: FUNC
1047+ * @tc.require: issueI5NTX6
1048+ */
1049+HWTEST_F(AppSpawnSandboxCoreTest, DoInstallDebugInvertedPermissionPoints_01, TestSize.Level0)
1050+{
1051+ g_testHelperCore.SetProcessName("com.ohos.debug.app");
1052+ g_testHelperCore.SetTestApl("normal");
1053+ 
1054+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
1055+ ASSERT_NE(appProperty, nullptr);
1056+ 
1057+ cJSON *debugJson = nullptr;
1058+ int ret = AppSpawn::SandboxCore::DoInstallDebugInvertedPermissionPoints(appProperty, debugJson);
1059+ EXPECT_EQ(ret, 0);
1060+ 
1061+ DeleteAppSpawningCtx(appProperty);
1062+}
1063+ 
1064+/**
1065+ * @tc.name: DoInstallDebugInvertedPermissionPoints_02
1066+ * @tc.desc: Test debug install inverted-permission points with valid config but app does NOT
1067+ * have the permission (unregistered name), should mount (inverted logic)
1068+ * @tc.type: FUNC
1069+ * @tc.require: issueI5NTX6
1070+ */
1071+HWTEST_F(AppSpawnSandboxCoreTest, DoInstallDebugInvertedPermissionPoints_02, TestSize.Level0)
1072+{
1073+ g_testHelperCore.SetProcessName("com.ohos.debug.app");
1074+ g_testHelperCore.SetTestApl("normal");
1075+ 
1076+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
1077+ ASSERT_NE(appProperty, nullptr);
1078+ 
1079+ // Use an unregistered permission name so CheckAppPermissionFlagSet returns 0
1080+ // (app does NOT have the permission), inverted-permission proceeds to mount.
1081+ const char *configStr = R"({
1082+ "inverted-permission": [
1083+ {
1084+ "ohos.permission.UNREGISTERED_TEST": {
1085+ "mount-paths": [
1086+ {
1087+ "src-path": "/data/test/debug/src",
1088+ "sandbox-path": "/data/test/debug/dest"
1089+ }
1090+ ]
1091+ }
1092+ }
1093+ ]
1094+ })";
1095+ cJSON *debugJson = cJSON_Parse(configStr);
1096+ ASSERT_NE(debugJson, nullptr);
1097+ int ret = AppSpawn::SandboxCore::DoInstallDebugInvertedPermissionPoints(appProperty, debugJson);
1098+ EXPECT_EQ(ret, 0);
1099+ 
1100+ cJSON_Delete(debugJson);
1101+ DeleteAppSpawningCtx(appProperty);
1102+}
1103+ 
1104+/**
1105+ * @tc.name: DoInstallDebugInvertedPermissionPoints_03
1106+ * @tc.desc: Test debug install inverted-permission points with valid config and app HAS the
1107+ * registered permission (FILE_ACCESS_MANAGER), should skip (inverted logic)
1108+ * @tc.type: FUNC
1109+ * @tc.require: issueI5NTX6
1110+ */
1111+HWTEST_F(AppSpawnSandboxCoreTest, DoInstallDebugInvertedPermissionPoints_03, TestSize.Level0)
1112+{
1113+ g_testHelperCore.SetProcessName("com.ohos.debug.app");
1114+ g_testHelperCore.SetTestApl("normal");
1115+ 
1116+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
1117+ ASSERT_NE(appProperty, nullptr);
1118+ 
1119+ // Set the permission flag for a registered permission so that
1120+ // CheckAppPermissionFlagSet returns non-zero (app has the permission),
1121+ // inverted-permission skips the mount.
1122+ int index = GetPermissionIndex(nullptr, "ohos.permission.FILE_ACCESS_MANAGER");
1123+ ASSERT_GE(index, 0);
1124+ int ret = SetAppPermissionFlags(appProperty, static_cast<uint32_t>(index));
1125+ EXPECT_EQ(ret, 0);
1126+ 
1127+ const char *configStr = R"({
1128+ "inverted-permission": [
1129+ {
1130+ "ohos.permission.FILE_ACCESS_MANAGER": {
1131+ "mount-paths": [
1132+ {
1133+ "src-path": "/data/test/debug/src",
1134+ "sandbox-path": "/data/test/debug/dest"
1135+ }
1136+ ]
1137+ }
1138+ }
1139+ ]
1140+ })";
1141+ cJSON *debugJson = cJSON_Parse(configStr);
1142+ ASSERT_NE(debugJson, nullptr);
1143+ ret = AppSpawn::SandboxCore::DoInstallDebugInvertedPermissionPoints(appProperty, debugJson);
1144+ EXPECT_EQ(ret, 0);
1145+ 
1146+ cJSON_Delete(debugJson);
1147+ DeleteAppSpawningCtx(appProperty);
1148+}
1149+ 
1150+/**
1151+ * @tc.name: DoInstallDebugInvertedPermissionPoints_04
1152+ * @tc.desc: Test debug install inverted-permission points with empty permission child (no array
1153+ * items), permissionMountPaths is null, should skip
1154+ * @tc.type: FUNC
1155+ * @tc.require: issueI5NTX6
1156+ */
1157+HWTEST_F(AppSpawnSandboxCoreTest, DoInstallDebugInvertedPermissionPoints_04, TestSize.Level0)
1158+{
1159+ g_testHelperCore.SetProcessName("com.ohos.debug.app");
1160+ g_testHelperCore.SetTestApl("normal");
1161+ 
1162+ AppSpawningCtx *appProperty = GetTestAppPropertyCore();
1163+ ASSERT_NE(appProperty, nullptr);
1164+ 
1165+ // The permission child value is an empty object {}, so cJSON_GetArrayItem(child, 0)
1166+ // returns null and the !permissionMountPaths branch is taken.
1167+ // Set the permission flag so that CheckAppPermissionFlagSet returns non-zero,
1168+ // allowing the code to reach the !permissionMountPaths check.
1169+ int index = GetPermissionIndex(nullptr, "ohos.permission.FILE_ACCESS_MANAGER");
1170+ ASSERT_GE(index, 0);
1171+ int ret = SetAppPermissionFlags(appProperty, static_cast<uint32_t>(index));
1172+ EXPECT_EQ(ret, 0);
1173+ 
1174+ const char *configStr = R"({
1175+ "inverted-permission": [
1176+ {
1177+ "ohos.permission.FILE_ACCESS_MANAGER": {}
1178+ }
1179+ ]
1180+ })";
1181+ cJSON *debugJson = cJSON_Parse(configStr);
1182+ ASSERT_NE(debugJson, nullptr);
1183+ ret = AppSpawn::SandboxCore::DoInstallDebugInvertedPermissionPoints(appProperty, debugJson);
1184+ EXPECT_EQ(ret, 0);
1185+ 
1186+ cJSON_Delete(debugJson);
1187+ DeleteAppSpawningCtx(appProperty);
1188+}
1189+ 
1190+/**
1191+ * @tc.name: DoUninstallDebugInvertedPermissionPoints_01
1192+ * @tc.desc: Test debug uninstall inverted-permission points with null json
1193+ * @tc.type: FUNC
1194+ * @tc.require: issueI5NTX6
1195+ */
1196+HWTEST_F(AppSpawnSandboxCoreTest, DoUninstallDebugInvertedPermissionPoints_01, TestSize.Level0)
1197+{
1198+ std::vector<std::string> bundleList;
1199+ cJSON *debugJson = nullptr;
1200+ int ret = AppSpawn::SandboxCore::DoUninstallDebugInvertedPermissionPoints(bundleList, debugJson);
1201+ EXPECT_EQ(ret, 0);
1202+}
1203+ 
1204+/**
1205+ * @tc.name: DoUninstallDebugInvertedPermissionPoints_02
1206+ * @tc.desc: Test debug uninstall inverted-permission points with valid config and mount-paths,
1207+ * should uninstall
1208+ * @tc.type: FUNC
1209+ * @tc.require: issueI5NTX6
1210+ */
1211+HWTEST_F(AppSpawnSandboxCoreTest, DoUninstallDebugInvertedPermissionPoints_02, TestSize.Level0)
1212+{
1213+ std::vector<std::string> bundleList;
1214+ bundleList.push_back("com.ohos.test.app");
1215+ 
1216+ const char *configStr = R"({
1217+ "inverted-permission": [
1218+ {
1219+ "ohos.permission.FILE_ACCESS_MANAGER": {
1220+ "mount-paths": [
1221+ {
1222+ "src-path": "/data/test/debug/src",
1223+ "sandbox-path": "/data/test/debug/dest"
1224+ }
1225+ ]
1226+ }
1227+ }
1228+ ]
1229+ })";
1230+ cJSON *debugJson = cJSON_Parse(configStr);
1231+ ASSERT_NE(debugJson, nullptr);
1232+ int ret = AppSpawn::SandboxCore::DoUninstallDebugInvertedPermissionPoints(bundleList, debugJson);
1233+ EXPECT_EQ(ret, 0);
1234+ 
1235+ cJSON_Delete(debugJson);
1236+}
1237+ 
1238+/**
1239+ * @tc.name: DoUninstallDebugInvertedPermissionPoints_03
1240+ * @tc.desc: Test debug uninstall inverted-permission points with empty permission child (no
1241+ * array items), permissionMountPaths is null, should skip
1242+ * @tc.type: FUNC
1243+ * @tc.require: issueI5NTX6
1244+ */
1245+HWTEST_F(AppSpawnSandboxCoreTest, DoUninstallDebugInvertedPermissionPoints_03, TestSize.Level0)
1246+{
1247+ std::vector<std::string> bundleList;
1248+ bundleList.push_back("com.ohos.test.app");
1249+ 
1250+ // The permission child value is an empty object {}, so cJSON_GetArrayItem(child, 0)
1251+ // returns null and the !permissionMountPaths branch is taken.
1252+ const char *configStr = R"({
1253+ "inverted-permission": [
1254+ {
1255+ "ohos.permission.TEST_INVERTED": {}
1256+ }
1257+ ]
1258+ })";
1259+ cJSON *debugJson = cJSON_Parse(configStr);
1260+ ASSERT_NE(debugJson, nullptr);
1261+ int ret = AppSpawn::SandboxCore::DoUninstallDebugInvertedPermissionPoints(bundleList, debugJson);
1262+ EXPECT_EQ(ret, 0);
1263+ 
1264+ cJSON_Delete(debugJson);
1265+}
1266+ 
544} // namespace OHOS1267} // namespace OHOS