169570cc8Sopenharmony_ci/*
269570cc8Sopenharmony_ci * Copyright (C) 2024 Huawei Device Co., Ltd.
369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License.
569570cc8Sopenharmony_ci * You may obtain a copy of the License at
669570cc8Sopenharmony_ci *
769570cc8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
869570cc8Sopenharmony_ci *
969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and
1369570cc8Sopenharmony_ci * limitations under the License.
1469570cc8Sopenharmony_ci */
1569570cc8Sopenharmony_ci#include <ctype.h>
1669570cc8Sopenharmony_ci#include <stdbool.h>
1769570cc8Sopenharmony_ci#include <stdlib.h>
1869570cc8Sopenharmony_ci#ifndef _GNU_SOURCE
1969570cc8Sopenharmony_ci#define _GNU_SOURCE
2069570cc8Sopenharmony_ci#endif
2169570cc8Sopenharmony_ci#include <errno.h>
2269570cc8Sopenharmony_ci#include <fcntl.h>
2369570cc8Sopenharmony_ci#include <sched.h>
2469570cc8Sopenharmony_ci#include <stdio.h>
2569570cc8Sopenharmony_ci#include <unistd.h>
2669570cc8Sopenharmony_ci
2769570cc8Sopenharmony_ci#include <sys/mount.h>
2869570cc8Sopenharmony_ci#include <sys/types.h>
2969570cc8Sopenharmony_ci
3069570cc8Sopenharmony_ci#include "appspawn_msg.h"
3169570cc8Sopenharmony_ci#include "appspawn_permission.h"
3269570cc8Sopenharmony_ci#include "appspawn_sandbox.h"
3369570cc8Sopenharmony_ci#include "appspawn_utils.h"
3469570cc8Sopenharmony_ci#include "cJSON.h"
3569570cc8Sopenharmony_ci#include "init_utils.h"
3669570cc8Sopenharmony_ci#include "json_utils.h"
3769570cc8Sopenharmony_ci#include "parameter.h"
3869570cc8Sopenharmony_ci#include "securec.h"
3969570cc8Sopenharmony_ci
4069570cc8Sopenharmony_cistatic const SandboxFlagInfo NAMESPACE_FLAGS_MAP[] = {
4169570cc8Sopenharmony_ci    {"pid", CLONE_NEWPID}, {"net", CLONE_NEWNET}
4269570cc8Sopenharmony_ci};
4369570cc8Sopenharmony_ci
4469570cc8Sopenharmony_cistatic const SandboxFlagInfo FLAGE_POINT_MAP[] = {
4569570cc8Sopenharmony_ci    {"0", 0},
4669570cc8Sopenharmony_ci    {"START_FLAGS_BACKUP", (unsigned long)APP_FLAGS_BACKUP_EXTENSION},
4769570cc8Sopenharmony_ci    {"DLP_MANAGER", (unsigned long)APP_FLAGS_DLP_MANAGER},
4869570cc8Sopenharmony_ci    {"DEVELOPER_MODE", (unsigned long)APP_FLAGS_DEVELOPER_MODE}
4969570cc8Sopenharmony_ci};
5069570cc8Sopenharmony_ci
5169570cc8Sopenharmony_cistatic const SandboxFlagInfo MOUNT_MODE_MAP[] = {
5269570cc8Sopenharmony_ci    {"not-exists", (unsigned long)MOUNT_MODE_NOT_EXIST},
5369570cc8Sopenharmony_ci    {"always", (unsigned long)MOUNT_MODE_ALWAYS}
5469570cc8Sopenharmony_ci};
5569570cc8Sopenharmony_ci
5669570cc8Sopenharmony_cistatic const SandboxFlagInfo NAME_GROUP_TYPE_MAP[] = {
5769570cc8Sopenharmony_ci    {"system-const", (unsigned long)SANDBOX_TAG_SYSTEM_CONST},
5869570cc8Sopenharmony_ci    {"app-variable", (unsigned long)SANDBOX_TAG_APP_VARIABLE}
5969570cc8Sopenharmony_ci};
6069570cc8Sopenharmony_ci
6169570cc8Sopenharmony_cistatic inline PathMountNode *CreatePathMountNode(uint32_t type, uint32_t hasDemandInfo)
6269570cc8Sopenharmony_ci{
6369570cc8Sopenharmony_ci    uint32_t len = hasDemandInfo ? sizeof(PathDemandInfo) : 0;
6469570cc8Sopenharmony_ci    return (PathMountNode *)CreateSandboxMountNode(sizeof(PathMountNode) + len, type);
6569570cc8Sopenharmony_ci}
6669570cc8Sopenharmony_ci
6769570cc8Sopenharmony_cistatic inline SymbolLinkNode *CreateSymbolLinkNode(void)
6869570cc8Sopenharmony_ci{
6969570cc8Sopenharmony_ci    return (SymbolLinkNode *)CreateSandboxMountNode(sizeof(SymbolLinkNode), SANDBOX_TAG_SYMLINK);
7069570cc8Sopenharmony_ci}
7169570cc8Sopenharmony_ci
7269570cc8Sopenharmony_cistatic inline SandboxPackageNameNode *CreateSandboxPackageNameNode(const char *name)
7369570cc8Sopenharmony_ci{
7469570cc8Sopenharmony_ci    return (SandboxPackageNameNode *)CreateSandboxSection(name,
7569570cc8Sopenharmony_ci        sizeof(SandboxPackageNameNode), SANDBOX_TAG_PACKAGE_NAME);
7669570cc8Sopenharmony_ci}
7769570cc8Sopenharmony_ci
7869570cc8Sopenharmony_cistatic inline SandboxFlagsNode *CreateSandboxFlagsNode(const char *name)
7969570cc8Sopenharmony_ci{
8069570cc8Sopenharmony_ci    return (SandboxFlagsNode *)CreateSandboxSection(name, sizeof(SandboxFlagsNode), SANDBOX_TAG_SPAWN_FLAGS);
8169570cc8Sopenharmony_ci}
8269570cc8Sopenharmony_ci
8369570cc8Sopenharmony_cistatic inline SandboxNameGroupNode *CreateSandboxNameGroupNode(const char *name)
8469570cc8Sopenharmony_ci{
8569570cc8Sopenharmony_ci    return (SandboxNameGroupNode *)CreateSandboxSection(name, sizeof(SandboxNameGroupNode), SANDBOX_TAG_NAME_GROUP);
8669570cc8Sopenharmony_ci}
8769570cc8Sopenharmony_ci
8869570cc8Sopenharmony_cistatic inline SandboxPermissionNode *CreateSandboxPermissionNode(const char *name)
8969570cc8Sopenharmony_ci{
9069570cc8Sopenharmony_ci    size_t len = sizeof(SandboxPermissionNode);
9169570cc8Sopenharmony_ci    SandboxPermissionNode *node = (SandboxPermissionNode *)CreateSandboxSection(name, len, SANDBOX_TAG_PERMISSION);
9269570cc8Sopenharmony_ci    APPSPAWN_CHECK(node != NULL, return NULL, "Failed to create permission node");
9369570cc8Sopenharmony_ci    node->permissionIndex = 0;
9469570cc8Sopenharmony_ci    return node;
9569570cc8Sopenharmony_ci}
9669570cc8Sopenharmony_ci
9769570cc8Sopenharmony_cistatic inline bool GetBoolParameter(const char *param, bool value)
9869570cc8Sopenharmony_ci{
9969570cc8Sopenharmony_ci    char tmp[32] = {0};  // 32 max
10069570cc8Sopenharmony_ci    int ret = GetParameter(param, "", tmp, sizeof(tmp));
10169570cc8Sopenharmony_ci    APPSPAWN_LOGV("GetBoolParameter key %{public}s ret %{public}d result: %{public}s", param, ret, tmp);
10269570cc8Sopenharmony_ci    if (ret > 0 && strcmp(tmp, "false") == 0) {
10369570cc8Sopenharmony_ci        return false;
10469570cc8Sopenharmony_ci    }
10569570cc8Sopenharmony_ci    if (ret > 0 && strcmp(tmp, "true") == 0) {
10669570cc8Sopenharmony_ci        return true;
10769570cc8Sopenharmony_ci    }
10869570cc8Sopenharmony_ci    return value;
10969570cc8Sopenharmony_ci}
11069570cc8Sopenharmony_ci
11169570cc8Sopenharmony_cistatic inline bool AppSandboxPidNsIsSupport(void)
11269570cc8Sopenharmony_ci{
11369570cc8Sopenharmony_ci    // only set false, return false
11469570cc8Sopenharmony_ci    return GetBoolParameter("const.sandbox.pidns.support", true);
11569570cc8Sopenharmony_ci}
11669570cc8Sopenharmony_ci
11769570cc8Sopenharmony_cistatic inline bool CheckAppFullMountEnable(void)
11869570cc8Sopenharmony_ci{
11969570cc8Sopenharmony_ci    return GetBoolParameter("const.filemanager.full_mount.enable", false);
12069570cc8Sopenharmony_ci}
12169570cc8Sopenharmony_ci
12269570cc8Sopenharmony_ciAPPSPAWN_STATIC unsigned long GetMountModeFromConfig(const cJSON *config, const char *key, unsigned long def)
12369570cc8Sopenharmony_ci{
12469570cc8Sopenharmony_ci    char *value = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(config, key));
12569570cc8Sopenharmony_ci    if (value == NULL) {
12669570cc8Sopenharmony_ci        return def;
12769570cc8Sopenharmony_ci    }
12869570cc8Sopenharmony_ci    const SandboxFlagInfo *info = GetSandboxFlagInfo(value, MOUNT_MODE_MAP, ARRAY_LENGTH(MOUNT_MODE_MAP));
12969570cc8Sopenharmony_ci    if (info != NULL) {
13069570cc8Sopenharmony_ci        return info->flags;
13169570cc8Sopenharmony_ci    }
13269570cc8Sopenharmony_ci    return def;
13369570cc8Sopenharmony_ci}
13469570cc8Sopenharmony_ci
13569570cc8Sopenharmony_cistatic uint32_t GetNameGroupTypeFromConfig(const cJSON *config, const char *key, unsigned long def)
13669570cc8Sopenharmony_ci{
13769570cc8Sopenharmony_ci    char *value = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(config, key));
13869570cc8Sopenharmony_ci    if (value == NULL) {
13969570cc8Sopenharmony_ci        return def;
14069570cc8Sopenharmony_ci    }
14169570cc8Sopenharmony_ci    const SandboxFlagInfo *info = GetSandboxFlagInfo(value, NAME_GROUP_TYPE_MAP, ARRAY_LENGTH(NAME_GROUP_TYPE_MAP));
14269570cc8Sopenharmony_ci    if (info != NULL) {
14369570cc8Sopenharmony_ci        return (uint32_t)info->flags;
14469570cc8Sopenharmony_ci    }
14569570cc8Sopenharmony_ci    return def;
14669570cc8Sopenharmony_ci}
14769570cc8Sopenharmony_ci
14869570cc8Sopenharmony_cistatic uint32_t GetSandboxNsFlags(const cJSON *appConfig)
14969570cc8Sopenharmony_ci{
15069570cc8Sopenharmony_ci    uint32_t nsFlags = 0;
15169570cc8Sopenharmony_ci    cJSON *obj = cJSON_GetObjectItemCaseSensitive(appConfig, "sandbox-ns-flags");
15269570cc8Sopenharmony_ci    if (obj == NULL || !cJSON_IsArray(obj)) {
15369570cc8Sopenharmony_ci        return nsFlags;
15469570cc8Sopenharmony_ci    }
15569570cc8Sopenharmony_ci    int count = cJSON_GetArraySize(obj);
15669570cc8Sopenharmony_ci    for (int i = 0; i < count; i++) {
15769570cc8Sopenharmony_ci        char *value = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i));
15869570cc8Sopenharmony_ci        const SandboxFlagInfo *info = GetSandboxFlagInfo(value, NAMESPACE_FLAGS_MAP, ARRAY_LENGTH(NAMESPACE_FLAGS_MAP));
15969570cc8Sopenharmony_ci        if (info != NULL) {
16069570cc8Sopenharmony_ci            nsFlags |= info->flags;
16169570cc8Sopenharmony_ci        }
16269570cc8Sopenharmony_ci    }
16369570cc8Sopenharmony_ci    return nsFlags;
16469570cc8Sopenharmony_ci}
16569570cc8Sopenharmony_ci
16669570cc8Sopenharmony_cistatic int SetMode(const char *str, void *context)
16769570cc8Sopenharmony_ci{
16869570cc8Sopenharmony_ci    mode_t *mode = (mode_t *)context;
16969570cc8Sopenharmony_ci    *mode |= GetPathMode(str);
17069570cc8Sopenharmony_ci    return 0;
17169570cc8Sopenharmony_ci}
17269570cc8Sopenharmony_ci
17369570cc8Sopenharmony_cistatic mode_t GetChmodFromJson(const cJSON *config)
17469570cc8Sopenharmony_ci{
17569570cc8Sopenharmony_ci    mode_t mode = 0;
17669570cc8Sopenharmony_ci    char *modeStrs = GetStringFromJsonObj(config, "dest-mode");
17769570cc8Sopenharmony_ci    if (modeStrs == NULL) {
17869570cc8Sopenharmony_ci        return mode;
17969570cc8Sopenharmony_ci    }
18069570cc8Sopenharmony_ci    (void)StringSplit(modeStrs, "|", (void *)&mode, SetMode);
18169570cc8Sopenharmony_ci    return mode;
18269570cc8Sopenharmony_ci}
18369570cc8Sopenharmony_ci
18469570cc8Sopenharmony_ciAPPSPAWN_STATIC uint32_t GetFlagIndexFromJson(const cJSON *config)
18569570cc8Sopenharmony_ci{
18669570cc8Sopenharmony_ci    char *flagStr = GetStringFromJsonObj(config, "name");
18769570cc8Sopenharmony_ci    if (flagStr == NULL) {
18869570cc8Sopenharmony_ci        return 0;
18969570cc8Sopenharmony_ci    }
19069570cc8Sopenharmony_ci    const SandboxFlagInfo *info = GetSandboxFlagInfo(flagStr, FLAGE_POINT_MAP, ARRAY_LENGTH(FLAGE_POINT_MAP));
19169570cc8Sopenharmony_ci    if (info != NULL) {
19269570cc8Sopenharmony_ci        return info->flags;
19369570cc8Sopenharmony_ci    }
19469570cc8Sopenharmony_ci    return 0;
19569570cc8Sopenharmony_ci}
19669570cc8Sopenharmony_ci
19769570cc8Sopenharmony_cistatic void FillPathDemandInfo(const cJSON *config, PathMountNode *sandboxNode)
19869570cc8Sopenharmony_ci{
19969570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(config != NULL, return);
20069570cc8Sopenharmony_ci    sandboxNode->demandInfo->uid = GetIntValueFromJsonObj(config, "uid", -1);
20169570cc8Sopenharmony_ci    sandboxNode->demandInfo->gid = GetIntValueFromJsonObj(config, "gid", -1);
20269570cc8Sopenharmony_ci    sandboxNode->demandInfo->mode = GetIntValueFromJsonObj(config, "ugo", -1);
20369570cc8Sopenharmony_ci}
20469570cc8Sopenharmony_ci
20569570cc8Sopenharmony_cistatic PathMountNode *DecodeMountPathConfig(const SandboxSection *section, const cJSON *config, uint32_t type)
20669570cc8Sopenharmony_ci{
20769570cc8Sopenharmony_ci    char *srcPath = GetStringFromJsonObj(config, "src-path");
20869570cc8Sopenharmony_ci    char *dstPath = GetStringFromJsonObj(config, "sandbox-path");
20969570cc8Sopenharmony_ci    if (srcPath == NULL || dstPath == NULL) {
21069570cc8Sopenharmony_ci        return NULL;
21169570cc8Sopenharmony_ci    }
21269570cc8Sopenharmony_ci
21369570cc8Sopenharmony_ci    PathMountNode *tmp = GetPathMountNode(section, type, srcPath, dstPath);
21469570cc8Sopenharmony_ci    if (tmp != NULL) { // 删除老的节点,保存新的节点
21569570cc8Sopenharmony_ci        DeleteSandboxMountNode((SandboxMountNode *)tmp);
21669570cc8Sopenharmony_ci        APPSPAWN_LOGW("path %{public}s %{public}s repeat config, delete old", srcPath, dstPath);
21769570cc8Sopenharmony_ci    }
21869570cc8Sopenharmony_ci
21969570cc8Sopenharmony_ci    cJSON *demandInfo = cJSON_GetObjectItemCaseSensitive(config, "create-on-demand");
22069570cc8Sopenharmony_ci    PathMountNode *sandboxNode = CreatePathMountNode(type, demandInfo != NULL);
22169570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, return NULL);
22269570cc8Sopenharmony_ci    sandboxNode->createDemand = demandInfo != NULL;
22369570cc8Sopenharmony_ci    sandboxNode->source = strdup(srcPath);
22469570cc8Sopenharmony_ci    sandboxNode->target = strdup(dstPath);
22569570cc8Sopenharmony_ci
22669570cc8Sopenharmony_ci    sandboxNode->destMode = GetChmodFromJson(config);
22769570cc8Sopenharmony_ci    sandboxNode->mountSharedFlag = GetBoolValueFromJsonObj(config, "mount-shared-flag", false);
22869570cc8Sopenharmony_ci    sandboxNode->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false);
22969570cc8Sopenharmony_ci
23069570cc8Sopenharmony_ci    sandboxNode->category = GetMountCategory(GetStringFromJsonObj(config, "category"));
23169570cc8Sopenharmony_ci    const char *value = GetStringFromJsonObj(config, "app-apl-name");
23269570cc8Sopenharmony_ci    if (value != NULL) {
23369570cc8Sopenharmony_ci        sandboxNode->appAplName = strdup(value);
23469570cc8Sopenharmony_ci    }
23569570cc8Sopenharmony_ci    FillPathDemandInfo(demandInfo, sandboxNode);
23669570cc8Sopenharmony_ci
23769570cc8Sopenharmony_ci    if (sandboxNode->source == NULL || sandboxNode->target == NULL) {
23869570cc8Sopenharmony_ci        APPSPAWN_LOGE("Failed to get sourc or target path");
23969570cc8Sopenharmony_ci        DeleteSandboxMountNode((SandboxMountNode *)sandboxNode);
24069570cc8Sopenharmony_ci        return NULL;
24169570cc8Sopenharmony_ci    }
24269570cc8Sopenharmony_ci    return sandboxNode;
24369570cc8Sopenharmony_ci}
24469570cc8Sopenharmony_ci
24569570cc8Sopenharmony_ciAPPSPAWN_STATIC int ParseMountPathsConfig(AppSpawnSandboxCfg *sandbox,
24669570cc8Sopenharmony_ci    const cJSON *mountConfigs, SandboxSection *section, uint32_t type)
24769570cc8Sopenharmony_ci{
24869570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(mountConfigs != NULL && cJSON_IsArray(mountConfigs), return -1);
24969570cc8Sopenharmony_ci
25069570cc8Sopenharmony_ci    uint32_t mountPointSize = cJSON_GetArraySize(mountConfigs);
25169570cc8Sopenharmony_ci    for (uint32_t i = 0; i < mountPointSize; i++) {
25269570cc8Sopenharmony_ci        cJSON *mntJson = cJSON_GetArrayItem(mountConfigs, i);
25369570cc8Sopenharmony_ci        if (mntJson == NULL) {
25469570cc8Sopenharmony_ci            continue;
25569570cc8Sopenharmony_ci        }
25669570cc8Sopenharmony_ci        PathMountNode *sandboxNode = DecodeMountPathConfig(section, mntJson, type);
25769570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(sandboxNode != NULL, continue);
25869570cc8Sopenharmony_ci        AddSandboxMountNode(&sandboxNode->sandboxNode, section);
25969570cc8Sopenharmony_ci    }
26069570cc8Sopenharmony_ci    return 0;
26169570cc8Sopenharmony_ci}
26269570cc8Sopenharmony_ci
26369570cc8Sopenharmony_cistatic SymbolLinkNode *DecodeSymbolLinksConfig(const SandboxSection *section, const cJSON *config)
26469570cc8Sopenharmony_ci{
26569570cc8Sopenharmony_ci    const char *target = GetStringFromJsonObj(config, "target-name");
26669570cc8Sopenharmony_ci    const char *linkName = GetStringFromJsonObj(config, "link-name");
26769570cc8Sopenharmony_ci    if (target == NULL || linkName == NULL) {
26869570cc8Sopenharmony_ci        return NULL;
26969570cc8Sopenharmony_ci    }
27069570cc8Sopenharmony_ci
27169570cc8Sopenharmony_ci    SymbolLinkNode *tmp = GetSymbolLinkNode(section, target, linkName);
27269570cc8Sopenharmony_ci    if (tmp != NULL) { // 删除老的节点,保存新的节点
27369570cc8Sopenharmony_ci        DeleteSandboxMountNode((SandboxMountNode *)tmp);
27469570cc8Sopenharmony_ci        APPSPAWN_LOGW("SymbolLink %{public}s %{public}s repeat config, delete old", target, linkName);
27569570cc8Sopenharmony_ci    }
27669570cc8Sopenharmony_ci
27769570cc8Sopenharmony_ci    SymbolLinkNode *node = CreateSymbolLinkNode();
27869570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL);
27969570cc8Sopenharmony_ci    node->destMode = GetChmodFromJson(config);
28069570cc8Sopenharmony_ci    node->checkErrorFlag = GetBoolValueFromJsonObj(config, "check-action-status", false);
28169570cc8Sopenharmony_ci    node->target = strdup(target);
28269570cc8Sopenharmony_ci    node->linkName = strdup(linkName);
28369570cc8Sopenharmony_ci    if (node->target == NULL || node->linkName == NULL) {
28469570cc8Sopenharmony_ci        APPSPAWN_LOGE("Failed to get sourc or target path");
28569570cc8Sopenharmony_ci        DeleteSandboxMountNode((SandboxMountNode *)node);
28669570cc8Sopenharmony_ci        return NULL;
28769570cc8Sopenharmony_ci    }
28869570cc8Sopenharmony_ci    return node;
28969570cc8Sopenharmony_ci}
29069570cc8Sopenharmony_ci
29169570cc8Sopenharmony_ciAPPSPAWN_STATIC int ParseSymbolLinksConfig(AppSpawnSandboxCfg *sandbox, const cJSON *symbolLinkConfigs,
29269570cc8Sopenharmony_ci    SandboxSection *section)
29369570cc8Sopenharmony_ci{
29469570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(symbolLinkConfigs != NULL && cJSON_IsArray(symbolLinkConfigs), return -1);
29569570cc8Sopenharmony_ci    uint32_t symlinkPointSize = cJSON_GetArraySize(symbolLinkConfigs);
29669570cc8Sopenharmony_ci    for (uint32_t i = 0; i < symlinkPointSize; i++) {
29769570cc8Sopenharmony_ci        cJSON *symConfig = cJSON_GetArrayItem(symbolLinkConfigs, i);
29869570cc8Sopenharmony_ci        if (symConfig == NULL) {
29969570cc8Sopenharmony_ci            continue;
30069570cc8Sopenharmony_ci        }
30169570cc8Sopenharmony_ci        SymbolLinkNode *node = DecodeSymbolLinksConfig(section, symConfig);
30269570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
30369570cc8Sopenharmony_ci        AddSandboxMountNode(&node->sandboxNode, section);
30469570cc8Sopenharmony_ci    }
30569570cc8Sopenharmony_ci    return 0;
30669570cc8Sopenharmony_ci}
30769570cc8Sopenharmony_ci
30869570cc8Sopenharmony_ciAPPSPAWN_STATIC int ParseGidTableConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, SandboxSection *section)
30969570cc8Sopenharmony_ci{
31069570cc8Sopenharmony_ci    APPSPAWN_CHECK(cJSON_IsArray(configs), return 0, "json is not array.");
31169570cc8Sopenharmony_ci    uint32_t arrayLen = (uint32_t)cJSON_GetArraySize(configs);
31269570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(arrayLen > 0, return 0);
31369570cc8Sopenharmony_ci    APPSPAWN_CHECK(arrayLen < APP_MAX_GIDS, arrayLen = APP_MAX_GIDS, "More gid in gids json.");
31469570cc8Sopenharmony_ci
31569570cc8Sopenharmony_ci    // 配置存在,以后面的配置为准
31669570cc8Sopenharmony_ci    if (section->gidTable) {
31769570cc8Sopenharmony_ci        free(section->gidTable);
31869570cc8Sopenharmony_ci        section->gidTable = NULL;
31969570cc8Sopenharmony_ci        section->gidCount = 0;
32069570cc8Sopenharmony_ci    }
32169570cc8Sopenharmony_ci    section->gidTable = (gid_t *)calloc(1, sizeof(gid_t) * arrayLen);
32269570cc8Sopenharmony_ci    APPSPAWN_CHECK(section->gidTable != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory.");
32369570cc8Sopenharmony_ci
32469570cc8Sopenharmony_ci    for (uint32_t i = 0; i < arrayLen; i++) {
32569570cc8Sopenharmony_ci        cJSON *item = cJSON_GetArrayItem(configs, i);
32669570cc8Sopenharmony_ci        gid_t gid = 0;
32769570cc8Sopenharmony_ci        if (cJSON_IsNumber(item)) {
32869570cc8Sopenharmony_ci            gid = (gid_t)cJSON_GetNumberValue(item);
32969570cc8Sopenharmony_ci        } else {
33069570cc8Sopenharmony_ci            char *value = cJSON_GetStringValue(item);
33169570cc8Sopenharmony_ci            gid = DecodeGid(value);
33269570cc8Sopenharmony_ci        }
33369570cc8Sopenharmony_ci        if (gid <= 0) {
33469570cc8Sopenharmony_ci            continue;
33569570cc8Sopenharmony_ci        }
33669570cc8Sopenharmony_ci        section->gidTable[section->gidCount++] = gid;
33769570cc8Sopenharmony_ci    }
33869570cc8Sopenharmony_ci    return 0;
33969570cc8Sopenharmony_ci}
34069570cc8Sopenharmony_ci
34169570cc8Sopenharmony_cistatic int ParseMountGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig, SandboxSection *section)
34269570cc8Sopenharmony_ci{
34369570cc8Sopenharmony_ci    APPSPAWN_CHECK(cJSON_IsArray(groupConfig),
34469570cc8Sopenharmony_ci        return APPSPAWN_SANDBOX_INVALID, "Invalid mount-groups config %{public}s", section->name);
34569570cc8Sopenharmony_ci
34669570cc8Sopenharmony_ci    // 合并name-group
34769570cc8Sopenharmony_ci    uint32_t count = (uint32_t)cJSON_GetArraySize(groupConfig);
34869570cc8Sopenharmony_ci    APPSPAWN_LOGV("mount-group in section %{public}s  %{public}u", section->name, count);
34969570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0);
35069570cc8Sopenharmony_ci    count += section->number;
35169570cc8Sopenharmony_ci    SandboxMountNode **nameGroups = (SandboxMountNode **)calloc(1, sizeof(SandboxMountNode *) * count);
35269570cc8Sopenharmony_ci    APPSPAWN_CHECK(nameGroups != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to alloc memory for group name");
35369570cc8Sopenharmony_ci
35469570cc8Sopenharmony_ci    uint32_t j = 0;
35569570cc8Sopenharmony_ci    uint32_t number = 0;
35669570cc8Sopenharmony_ci    for (j = 0; j < section->number; j++) { // copy old
35769570cc8Sopenharmony_ci        if (section->nameGroups[j] == NULL) {
35869570cc8Sopenharmony_ci            continue;
35969570cc8Sopenharmony_ci        }
36069570cc8Sopenharmony_ci        nameGroups[number++] = section->nameGroups[j];
36169570cc8Sopenharmony_ci    }
36269570cc8Sopenharmony_ci
36369570cc8Sopenharmony_ci    SandboxNameGroupNode *mountNode = NULL;
36469570cc8Sopenharmony_ci    for (uint32_t i = 0; i < count; i++) {
36569570cc8Sopenharmony_ci        nameGroups[number] = NULL;
36669570cc8Sopenharmony_ci
36769570cc8Sopenharmony_ci        char *name = cJSON_GetStringValue(cJSON_GetArrayItem(groupConfig, i));
36869570cc8Sopenharmony_ci        mountNode = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name);
36969570cc8Sopenharmony_ci        if (mountNode == NULL) {
37069570cc8Sopenharmony_ci            APPSPAWN_LOGE("Can not find name-group %{public}s", name);
37169570cc8Sopenharmony_ci            continue;
37269570cc8Sopenharmony_ci        }
37369570cc8Sopenharmony_ci        // check type
37469570cc8Sopenharmony_ci        if (strcmp(section->name, "system-const") == 0 && mountNode->destType != SANDBOX_TAG_SYSTEM_CONST) {
37569570cc8Sopenharmony_ci            APPSPAWN_LOGE("Invalid name-group %{public}s", name);
37669570cc8Sopenharmony_ci            continue;
37769570cc8Sopenharmony_ci        }
37869570cc8Sopenharmony_ci        // 过滤重复的节点
37969570cc8Sopenharmony_ci        for (j = 0; j < section->number; j++) {
38069570cc8Sopenharmony_ci            if (section->nameGroups[j] != NULL && section->nameGroups[j] == (SandboxMountNode *)mountNode) {
38169570cc8Sopenharmony_ci                APPSPAWN_LOGE("Name-group %{public}s bas been set", name);
38269570cc8Sopenharmony_ci                break;
38369570cc8Sopenharmony_ci            }
38469570cc8Sopenharmony_ci        }
38569570cc8Sopenharmony_ci        if (j < section->number) {
38669570cc8Sopenharmony_ci            continue;
38769570cc8Sopenharmony_ci        }
38869570cc8Sopenharmony_ci        nameGroups[number++] = (SandboxMountNode *)mountNode;
38969570cc8Sopenharmony_ci        APPSPAWN_LOGV("Name-group %{public}d %{public}s set", section->number, name);
39069570cc8Sopenharmony_ci    }
39169570cc8Sopenharmony_ci    if (section->nameGroups != NULL) {
39269570cc8Sopenharmony_ci        free(section->nameGroups);
39369570cc8Sopenharmony_ci    }
39469570cc8Sopenharmony_ci    section->nameGroups = nameGroups;
39569570cc8Sopenharmony_ci    section->number = number;
39669570cc8Sopenharmony_ci    APPSPAWN_LOGV("mount-group in section %{public}s  %{public}u", section->name, section->number);
39769570cc8Sopenharmony_ci    return 0;
39869570cc8Sopenharmony_ci}
39969570cc8Sopenharmony_ci
40069570cc8Sopenharmony_cistatic int ParseBaseConfig(AppSpawnSandboxCfg *sandbox, SandboxSection *section, const cJSON *configs)
40169570cc8Sopenharmony_ci{
40269570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
40369570cc8Sopenharmony_ci    APPSPAWN_CHECK(cJSON_IsObject(configs),
40469570cc8Sopenharmony_ci        return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", section->name);
40569570cc8Sopenharmony_ci    APPSPAWN_LOGV("Parse sandbox %{public}s", section->name);
40669570cc8Sopenharmony_ci
40769570cc8Sopenharmony_ci    // "sandbox-switch": "ON", default sandbox switch is on
40869570cc8Sopenharmony_ci    section->sandboxSwitch = GetBoolValueFromJsonObj(configs, "sandbox-switch", true);
40969570cc8Sopenharmony_ci    // "sandbox-shared"
41069570cc8Sopenharmony_ci    section->sandboxShared = GetBoolValueFromJsonObj(configs, "sandbox-shared", false);
41169570cc8Sopenharmony_ci
41269570cc8Sopenharmony_ci    int ret = 0;
41369570cc8Sopenharmony_ci    cJSON *gidTabJson = cJSON_GetObjectItemCaseSensitive(configs, "gids");
41469570cc8Sopenharmony_ci    if (gidTabJson) {
41569570cc8Sopenharmony_ci        ret = ParseGidTableConfig(sandbox, gidTabJson, section);
41669570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, return ret, "Parse gids for %{public}s", section->name);
41769570cc8Sopenharmony_ci    }
41869570cc8Sopenharmony_ci
41969570cc8Sopenharmony_ci    cJSON *pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-paths");
42069570cc8Sopenharmony_ci    if (pathConfigs != NULL) {  // mount-paths
42169570cc8Sopenharmony_ci        ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_PATH);
42269570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name);
42369570cc8Sopenharmony_ci    }
42469570cc8Sopenharmony_ci
42569570cc8Sopenharmony_ci    pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "mount-files");
42669570cc8Sopenharmony_ci    if (pathConfigs != NULL) {  // mount-files
42769570cc8Sopenharmony_ci        ret = ParseMountPathsConfig(sandbox, pathConfigs, section, SANDBOX_TAG_MOUNT_FILE);
42869570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-paths for %{public}s", section->name);
42969570cc8Sopenharmony_ci    }
43069570cc8Sopenharmony_ci
43169570cc8Sopenharmony_ci    pathConfigs = cJSON_GetObjectItemCaseSensitive(configs, "symbol-links");
43269570cc8Sopenharmony_ci    if (pathConfigs != NULL) {  // symbol-links
43369570cc8Sopenharmony_ci        ret = ParseSymbolLinksConfig(sandbox, pathConfigs, section);
43469570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, return ret, "Parse symbol-links for %{public}s", section->name);
43569570cc8Sopenharmony_ci    }
43669570cc8Sopenharmony_ci
43769570cc8Sopenharmony_ci    cJSON *groupConfig = cJSON_GetObjectItemCaseSensitive(configs, "mount-groups");
43869570cc8Sopenharmony_ci    if (groupConfig != NULL) {
43969570cc8Sopenharmony_ci        ret = ParseMountGroupsConfig(sandbox, groupConfig, section);
44069570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, return ret, "Parse mount-groups for %{public}s", section->name);
44169570cc8Sopenharmony_ci    }
44269570cc8Sopenharmony_ci    return 0;
44369570cc8Sopenharmony_ci}
44469570cc8Sopenharmony_ci
44569570cc8Sopenharmony_cistatic int ParsePackageNameConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *packageNameConfigs)
44669570cc8Sopenharmony_ci{
44769570cc8Sopenharmony_ci    APPSPAWN_LOGV("Parse package-name config %{public}s", name);
44869570cc8Sopenharmony_ci    SandboxPackageNameNode *node = (SandboxPackageNameNode *)GetSandboxSection(&sandbox->packageNameQueue, name);
44969570cc8Sopenharmony_ci    if (node == NULL) {
45069570cc8Sopenharmony_ci        node = CreateSandboxPackageNameNode(name);
45169570cc8Sopenharmony_ci    }
45269570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
45369570cc8Sopenharmony_ci
45469570cc8Sopenharmony_ci    int ret = ParseBaseConfig(sandbox, &node->section, packageNameConfigs);
45569570cc8Sopenharmony_ci    if (ret != 0) {
45669570cc8Sopenharmony_ci        DeleteSandboxSection((SandboxSection *)node);
45769570cc8Sopenharmony_ci        return ret;
45869570cc8Sopenharmony_ci    }
45969570cc8Sopenharmony_ci    // success, insert section
46069570cc8Sopenharmony_ci    AddSandboxSection(&node->section, &sandbox->packageNameQueue);
46169570cc8Sopenharmony_ci    return 0;
46269570cc8Sopenharmony_ci}
46369570cc8Sopenharmony_ci
46469570cc8Sopenharmony_cistatic int ParseSpawnFlagsConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *flagsConfig)
46569570cc8Sopenharmony_ci{
46669570cc8Sopenharmony_ci    uint32_t flagIndex = GetFlagIndexFromJson(flagsConfig);
46769570cc8Sopenharmony_ci    APPSPAWN_LOGV("Parse spawn-flags config %{public}s flagIndex %{public}u", name, flagIndex);
46869570cc8Sopenharmony_ci    SandboxFlagsNode *node = (SandboxFlagsNode *)GetSandboxSection(&sandbox->spawnFlagsQueue, name);
46969570cc8Sopenharmony_ci    if (node == NULL) {
47069570cc8Sopenharmony_ci        node = CreateSandboxFlagsNode(name);
47169570cc8Sopenharmony_ci    }
47269570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
47369570cc8Sopenharmony_ci    node->flagIndex = flagIndex;
47469570cc8Sopenharmony_ci
47569570cc8Sopenharmony_ci    int ret = ParseBaseConfig(sandbox, &node->section, flagsConfig);
47669570cc8Sopenharmony_ci    if (ret != 0) {
47769570cc8Sopenharmony_ci        DeleteSandboxSection((SandboxSection *)node);
47869570cc8Sopenharmony_ci        return ret;
47969570cc8Sopenharmony_ci    }
48069570cc8Sopenharmony_ci    // success, insert section
48169570cc8Sopenharmony_ci    AddSandboxSection(&node->section, &sandbox->spawnFlagsQueue);
48269570cc8Sopenharmony_ci    return 0;
48369570cc8Sopenharmony_ci}
48469570cc8Sopenharmony_ci
48569570cc8Sopenharmony_cistatic int ParsePermissionConfig(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *permissionConfig)
48669570cc8Sopenharmony_ci{
48769570cc8Sopenharmony_ci    APPSPAWN_LOGV("Parse permission config %{public}s", name);
48869570cc8Sopenharmony_ci    SandboxPermissionNode *node = (SandboxPermissionNode *)GetSandboxSection(&sandbox->permissionQueue, name);
48969570cc8Sopenharmony_ci    if (node == NULL) {
49069570cc8Sopenharmony_ci        node = CreateSandboxPermissionNode(name);
49169570cc8Sopenharmony_ci    }
49269570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
49369570cc8Sopenharmony_ci
49469570cc8Sopenharmony_ci    int ret = ParseBaseConfig(sandbox, &node->section, permissionConfig);
49569570cc8Sopenharmony_ci    if (ret != 0) {
49669570cc8Sopenharmony_ci        DeleteSandboxSection((SandboxSection *)node);
49769570cc8Sopenharmony_ci        return ret;
49869570cc8Sopenharmony_ci    }
49969570cc8Sopenharmony_ci    // success, insert section
50069570cc8Sopenharmony_ci    AddSandboxSection(&node->section, &sandbox->permissionQueue);
50169570cc8Sopenharmony_ci    return 0;
50269570cc8Sopenharmony_ci}
50369570cc8Sopenharmony_ci
50469570cc8Sopenharmony_cistatic SandboxNameGroupNode *ParseNameGroup(AppSpawnSandboxCfg *sandbox, const cJSON *groupConfig)
50569570cc8Sopenharmony_ci{
50669570cc8Sopenharmony_ci    char *name = GetStringFromJsonObj(groupConfig, "name");
50769570cc8Sopenharmony_ci    APPSPAWN_CHECK(name != NULL, return NULL, "No name in name group config");
50869570cc8Sopenharmony_ci    APPSPAWN_LOGV("Parse name-group config %{public}s", name);
50969570cc8Sopenharmony_ci    SandboxNameGroupNode *node = (SandboxNameGroupNode *)GetSandboxSection(&sandbox->nameGroupsQueue, name);
51069570cc8Sopenharmony_ci    if (node == NULL) {
51169570cc8Sopenharmony_ci        node = CreateSandboxNameGroupNode(name);
51269570cc8Sopenharmony_ci    }
51369570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL);
51469570cc8Sopenharmony_ci
51569570cc8Sopenharmony_ci    cJSON *obj = cJSON_GetObjectItemCaseSensitive(groupConfig, "mount-paths-deps");
51669570cc8Sopenharmony_ci    if (obj) {
51769570cc8Sopenharmony_ci        if (node->depNode) { // free repeat
51869570cc8Sopenharmony_ci            DeleteSandboxMountNode((SandboxMountNode *)node->depNode);
51969570cc8Sopenharmony_ci        }
52069570cc8Sopenharmony_ci        node->depNode = DecodeMountPathConfig(NULL, obj, SANDBOX_TAG_MOUNT_PATH);
52169570cc8Sopenharmony_ci        if (node->depNode == NULL) {
52269570cc8Sopenharmony_ci            DeleteSandboxSection((SandboxSection *)node);
52369570cc8Sopenharmony_ci            return NULL;
52469570cc8Sopenharmony_ci        }
52569570cc8Sopenharmony_ci        // "deps-mode": "not-exists"
52669570cc8Sopenharmony_ci        node->depMode = GetMountModeFromConfig(groupConfig, "deps-mode", MOUNT_MODE_ALWAYS);
52769570cc8Sopenharmony_ci    }
52869570cc8Sopenharmony_ci
52969570cc8Sopenharmony_ci    int ret = ParseBaseConfig(sandbox, &node->section, groupConfig);
53069570cc8Sopenharmony_ci    if (ret != 0) {
53169570cc8Sopenharmony_ci        DeleteSandboxSection((SandboxSection *)node);
53269570cc8Sopenharmony_ci        return NULL;
53369570cc8Sopenharmony_ci    }
53469570cc8Sopenharmony_ci    // "type": "system-const",
53569570cc8Sopenharmony_ci    // "caps": ["shared"],
53669570cc8Sopenharmony_ci    node->destType = GetNameGroupTypeFromConfig(groupConfig, "type", SANDBOX_TAG_INVALID);
53769570cc8Sopenharmony_ci    node->depMounted = 0;
53869570cc8Sopenharmony_ci    // success, insert section
53969570cc8Sopenharmony_ci    AddSandboxSection(&node->section, &sandbox->nameGroupsQueue);
54069570cc8Sopenharmony_ci    return node;
54169570cc8Sopenharmony_ci}
54269570cc8Sopenharmony_ci
54369570cc8Sopenharmony_cistatic int ParseNameGroupsConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)
54469570cc8Sopenharmony_ci{
54569570cc8Sopenharmony_ci    APPSPAWN_CHECK(root != NULL, return APPSPAWN_SANDBOX_INVALID, "Invalid config ");
54669570cc8Sopenharmony_ci    cJSON *configs = cJSON_GetObjectItemCaseSensitive(root, "name-groups");
54769570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
54869570cc8Sopenharmony_ci    APPSPAWN_CHECK(cJSON_IsArray(configs), return APPSPAWN_SANDBOX_INVALID, "Invalid config ");
54969570cc8Sopenharmony_ci    int count = cJSON_GetArraySize(configs);
55069570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(count > 0, return 0);
55169570cc8Sopenharmony_ci
55269570cc8Sopenharmony_ci    sandbox->depNodeCount = 0;
55369570cc8Sopenharmony_ci    for (int i = 0; i < count; i++) {
55469570cc8Sopenharmony_ci        cJSON *json = cJSON_GetArrayItem(configs, i);
55569570cc8Sopenharmony_ci        if (json == NULL) {
55669570cc8Sopenharmony_ci            continue;
55769570cc8Sopenharmony_ci        }
55869570cc8Sopenharmony_ci        SandboxNameGroupNode *node = ParseNameGroup(sandbox, json);
55969570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return APPSPAWN_SANDBOX_INVALID);
56069570cc8Sopenharmony_ci        if (node->depNode) {
56169570cc8Sopenharmony_ci            sandbox->depNodeCount++;
56269570cc8Sopenharmony_ci        }
56369570cc8Sopenharmony_ci    }
56469570cc8Sopenharmony_ci    APPSPAWN_LOGV("ParseNameGroupsConfig depNodeCount %{public}d", sandbox->depNodeCount);
56569570cc8Sopenharmony_ci    return 0;
56669570cc8Sopenharmony_ci}
56769570cc8Sopenharmony_ci
56869570cc8Sopenharmony_cistatic int ParseConditionalConfig(AppSpawnSandboxCfg *sandbox, const cJSON *configs, const char *configName,
56969570cc8Sopenharmony_ci    int (*parseConfig)(AppSpawnSandboxCfg *sandbox, const char *name, const cJSON *configs))
57069570cc8Sopenharmony_ci{
57169570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(configs != NULL, return 0);
57269570cc8Sopenharmony_ci    APPSPAWN_CHECK(cJSON_IsArray(configs),
57369570cc8Sopenharmony_ci        return APPSPAWN_SANDBOX_INVALID, "Invalid config %{public}s", configName);
57469570cc8Sopenharmony_ci    int ret = 0;
57569570cc8Sopenharmony_ci    int count = cJSON_GetArraySize(configs);
57669570cc8Sopenharmony_ci    for (int i = 0; i < count; i++) {
57769570cc8Sopenharmony_ci        cJSON *json = cJSON_GetArrayItem(configs, i);
57869570cc8Sopenharmony_ci        if (json == NULL) {
57969570cc8Sopenharmony_ci            continue;
58069570cc8Sopenharmony_ci        }
58169570cc8Sopenharmony_ci        char *name = GetStringFromJsonObj(json, "name");
58269570cc8Sopenharmony_ci        if (name == NULL) {
58369570cc8Sopenharmony_ci            APPSPAWN_LOGE("No name in %{public}s configs", configName);
58469570cc8Sopenharmony_ci            continue;
58569570cc8Sopenharmony_ci        }
58669570cc8Sopenharmony_ci        ret = parseConfig(sandbox, name, json);
58769570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
58869570cc8Sopenharmony_ci    }
58969570cc8Sopenharmony_ci    return 0;
59069570cc8Sopenharmony_ci}
59169570cc8Sopenharmony_ci
59269570cc8Sopenharmony_cistatic int ParseGlobalSandboxConfig(AppSpawnSandboxCfg *sandbox, const cJSON *root)
59369570cc8Sopenharmony_ci{
59469570cc8Sopenharmony_ci    cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "global");
59569570cc8Sopenharmony_ci    if (json) {
59669570cc8Sopenharmony_ci        sandbox->sandboxNsFlags = GetSandboxNsFlags(json);
59769570cc8Sopenharmony_ci        char *rootPath = GetStringFromJsonObj(json, "sandbox-root");
59869570cc8Sopenharmony_ci        APPSPAWN_CHECK(rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "No root path in config");
59969570cc8Sopenharmony_ci        if (sandbox->rootPath) {
60069570cc8Sopenharmony_ci            free(sandbox->rootPath);
60169570cc8Sopenharmony_ci        }
60269570cc8Sopenharmony_ci        sandbox->rootPath = strdup(rootPath);
60369570cc8Sopenharmony_ci        APPSPAWN_CHECK(sandbox->rootPath != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to copy root path");
60469570cc8Sopenharmony_ci        sandbox->topSandboxSwitch = GetBoolValueFromJsonObj(json, "top-sandbox-switch", true);
60569570cc8Sopenharmony_ci    }
60669570cc8Sopenharmony_ci    return 0;
60769570cc8Sopenharmony_ci}
60869570cc8Sopenharmony_ci
60969570cc8Sopenharmony_citypedef struct TagParseJsonContext {
61069570cc8Sopenharmony_ci    AppSpawnSandboxCfg *sandboxCfg;
61169570cc8Sopenharmony_ci}ParseJsonContext;
61269570cc8Sopenharmony_ci
61369570cc8Sopenharmony_ciAPPSPAWN_STATIC int ParseAppSandboxConfig(const cJSON *root, ParseJsonContext *context)
61469570cc8Sopenharmony_ci{
61569570cc8Sopenharmony_ci    APPSPAWN_CHECK(root != NULL && context != NULL && context->sandboxCfg != NULL,
61669570cc8Sopenharmony_ci        return APPSPAWN_SYSTEM_ERROR, "Invalid json");
61769570cc8Sopenharmony_ci    AppSpawnSandboxCfg *sandbox = context->sandboxCfg;
61869570cc8Sopenharmony_ci    int ret = ParseGlobalSandboxConfig(sandbox, root);  // "global":
61969570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID);
62069570cc8Sopenharmony_ci    ret = ParseNameGroupsConfig(sandbox, root);  // name-groups
62169570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return APPSPAWN_SANDBOX_INVALID);
62269570cc8Sopenharmony_ci
62369570cc8Sopenharmony_ci    // "required"
62469570cc8Sopenharmony_ci    cJSON *required = cJSON_GetObjectItemCaseSensitive(root, "required");
62569570cc8Sopenharmony_ci    if (required) {
62669570cc8Sopenharmony_ci        cJSON *config = NULL;
62769570cc8Sopenharmony_ci        cJSON_ArrayForEach(config, required)
62869570cc8Sopenharmony_ci        {
62969570cc8Sopenharmony_ci            APPSPAWN_LOGI("Sandbox required config: %{public}s", config->string);
63069570cc8Sopenharmony_ci            SandboxSection *section = GetSandboxSection(&sandbox->requiredQueue, config->string);
63169570cc8Sopenharmony_ci            if (section == NULL) {
63269570cc8Sopenharmony_ci                section = CreateSandboxSection(config->string, sizeof(SandboxSection), SANDBOX_TAG_REQUIRED);
63369570cc8Sopenharmony_ci            }
63469570cc8Sopenharmony_ci            APPSPAWN_CHECK_ONLY_EXPER(section != NULL, return -1);
63569570cc8Sopenharmony_ci
63669570cc8Sopenharmony_ci            ret = ParseBaseConfig(sandbox, section, config);
63769570cc8Sopenharmony_ci            if (ret != 0) {
63869570cc8Sopenharmony_ci                DeleteSandboxSection(section);
63969570cc8Sopenharmony_ci                return ret;
64069570cc8Sopenharmony_ci            }
64169570cc8Sopenharmony_ci            // success, insert section
64269570cc8Sopenharmony_ci            AddSandboxSection(section, &sandbox->requiredQueue);
64369570cc8Sopenharmony_ci        }
64469570cc8Sopenharmony_ci    }
64569570cc8Sopenharmony_ci
64669570cc8Sopenharmony_ci    // conditional
64769570cc8Sopenharmony_ci    cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "conditional");
64869570cc8Sopenharmony_ci    if (json != NULL) {
64969570cc8Sopenharmony_ci        // permission
65069570cc8Sopenharmony_ci        cJSON *config = cJSON_GetObjectItemCaseSensitive(json, "permission");
65169570cc8Sopenharmony_ci        ret = ParseConditionalConfig(sandbox, config, "permission", ParsePermissionConfig);
65269570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
65369570cc8Sopenharmony_ci        // spawn-flag
65469570cc8Sopenharmony_ci        config = cJSON_GetObjectItemCaseSensitive(json, "spawn-flag");
65569570cc8Sopenharmony_ci        ret = ParseConditionalConfig(sandbox, config, "spawn-flag", ParseSpawnFlagsConfig);
65669570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
65769570cc8Sopenharmony_ci        // package-name
65869570cc8Sopenharmony_ci        config = cJSON_GetObjectItemCaseSensitive(json, "package-name");
65969570cc8Sopenharmony_ci        ret = ParseConditionalConfig(sandbox, config, "package-name", ParsePackageNameConfig);
66069570cc8Sopenharmony_ci        APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
66169570cc8Sopenharmony_ci    }
66269570cc8Sopenharmony_ci    return ret;
66369570cc8Sopenharmony_ci}
66469570cc8Sopenharmony_ci
66569570cc8Sopenharmony_ciAPPSPAWN_STATIC const char *GetSandboxNameByMode(RunMode mode)
66669570cc8Sopenharmony_ci{
66769570cc8Sopenharmony_ci    if (mode == MODE_FOR_NATIVE_SPAWN) {
66869570cc8Sopenharmony_ci        return ISOLATED_SANDBOX_FILE_NAME;
66969570cc8Sopenharmony_ci    }
67069570cc8Sopenharmony_ci    if (mode == MODE_FOR_NWEB_SPAWN || mode == MODE_FOR_NWEB_COLD_RUN) {
67169570cc8Sopenharmony_ci        return WEB_SANDBOX_FILE_NAME;
67269570cc8Sopenharmony_ci    }
67369570cc8Sopenharmony_ci    return APP_SANDBOX_FILE_NAME;
67469570cc8Sopenharmony_ci}
67569570cc8Sopenharmony_ci
67669570cc8Sopenharmony_ciint LoadAppSandboxConfig(AppSpawnSandboxCfg *sandbox, RunMode mode)
67769570cc8Sopenharmony_ci{
67869570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(sandbox != NULL, return APPSPAWN_ARG_INVALID);
67969570cc8Sopenharmony_ci    const char *sandboxName = GetSandboxNameByMode(mode);
68069570cc8Sopenharmony_ci    if (sandbox->depGroupNodes != NULL) {
68169570cc8Sopenharmony_ci        APPSPAWN_LOGW("Sandbox has been load");
68269570cc8Sopenharmony_ci        return 0;
68369570cc8Sopenharmony_ci    }
68469570cc8Sopenharmony_ci    ParseJsonContext context = {};
68569570cc8Sopenharmony_ci    context.sandboxCfg = sandbox;
68669570cc8Sopenharmony_ci    int ret = ParseJsonConfig("etc/sandbox", sandboxName, ParseAppSandboxConfig, &context);
68769570cc8Sopenharmony_ci    if (ret == APPSPAWN_SANDBOX_NONE) {
68869570cc8Sopenharmony_ci        APPSPAWN_LOGW("No sandbox config");
68969570cc8Sopenharmony_ci        ret = 0;
69069570cc8Sopenharmony_ci    }
69169570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
69269570cc8Sopenharmony_ci    sandbox->pidNamespaceSupport = AppSandboxPidNsIsSupport();
69369570cc8Sopenharmony_ci    sandbox->appFullMountEnable = CheckAppFullMountEnable();
69469570cc8Sopenharmony_ci    APPSPAWN_LOGI("Sandbox pidNamespaceSupport: %{public}d appFullMountEnable: %{public}d",
69569570cc8Sopenharmony_ci        sandbox->pidNamespaceSupport, sandbox->appFullMountEnable);
69669570cc8Sopenharmony_ci
69769570cc8Sopenharmony_ci    uint32_t depNodeCount = sandbox->depNodeCount;
69869570cc8Sopenharmony_ci    APPSPAWN_CHECK_ONLY_EXPER(depNodeCount > 0, return ret);
69969570cc8Sopenharmony_ci
70069570cc8Sopenharmony_ci    sandbox->depGroupNodes = (SandboxNameGroupNode **)calloc(1, sizeof(SandboxNameGroupNode *) * depNodeCount);
70169570cc8Sopenharmony_ci    APPSPAWN_CHECK(sandbox->depGroupNodes != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed alloc memory ");
70269570cc8Sopenharmony_ci    sandbox->depNodeCount = 0;
70369570cc8Sopenharmony_ci    ListNode *node = sandbox->nameGroupsQueue.front.next;
70469570cc8Sopenharmony_ci    while (node != &sandbox->nameGroupsQueue.front) {
70569570cc8Sopenharmony_ci        SandboxNameGroupNode *groupNode = (SandboxNameGroupNode *)ListEntry(node, SandboxMountNode, node);
70669570cc8Sopenharmony_ci        if (groupNode->depNode) {
70769570cc8Sopenharmony_ci            sandbox->depGroupNodes[sandbox->depNodeCount++] = groupNode;
70869570cc8Sopenharmony_ci        }
70969570cc8Sopenharmony_ci        node = node->next;
71069570cc8Sopenharmony_ci    }
71169570cc8Sopenharmony_ci    APPSPAWN_LOGI("LoadAppSandboxConfig depNodeCount %{public}d", sandbox->depNodeCount);
71269570cc8Sopenharmony_ci
71369570cc8Sopenharmony_ci    return 0;
71469570cc8Sopenharmony_ci}
715