/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <pthread.h> #include <stdlib.h> #ifndef APPSPAWN_CLIENT #include "appspawn_sandbox.h" #endif #include "appspawn_client.h" #include "appspawn_mount_permission.h" #include "appspawn_msg.h" #include "appspawn_permission.h" #include "appspawn_utils.h" #include "json_utils.h" #include "securec.h" typedef struct TagParseJsonContext { SandboxQueue permissionQueue; int32_t maxPermissionIndex; uint32_t inited; AppSpawnClientType type; } ParseJsonContext, PermissionManager; static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; static PermissionManager g_permissionMgr[CLIENT_MAX] = {}; #ifdef APPSPAWN_SANDBOX_NEW static int ParseAppSandboxConfig(const cJSON *root, PermissionManager *mgr) { // conditional cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "conditional"); APPSPAWN_CHECK(json != NULL, return 0, "No found conditional in config"); // permission cJSON *config = cJSON_GetObjectItemCaseSensitive(json, "permission"); APPSPAWN_CHECK(config != NULL && cJSON_IsArray(config), return 0, "No found permission in config"); uint32_t configSize = cJSON_GetArraySize(config); for (uint32_t i = 0; i < configSize; i++) { json = cJSON_GetArrayItem(config, i); char *name = GetStringFromJsonObj(json, "name"); APPSPAWN_CHECK(name != NULL, break, "No found name in config"); int ret = AddSandboxPermissionNode(name, &mgr->permissionQueue); APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); } return 0; } static PermissionManager *GetPermissionMgrByType(AppSpawnClientType type) { APPSPAWN_CHECK_ONLY_EXPER(type < CLIENT_MAX, return NULL); g_permissionMgr[type].type = type; return &g_permissionMgr[type]; } #else static int ParsePermissionConfig(const cJSON *permissionConfigs, PermissionManager *mgr) { cJSON *config = NULL; cJSON_ArrayForEach(config, permissionConfigs) { const char *name = config->string; int ret = AddSandboxPermissionNode(name, &mgr->permissionQueue); APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); } return 0; } static int ParseAppSandboxConfig(const cJSON *appSandboxConfig, PermissionManager *mgr) { cJSON *configs = cJSON_GetObjectItemCaseSensitive(appSandboxConfig, "permission"); APPSPAWN_CHECK(configs != NULL && cJSON_IsArray(configs), return 0, "No permission in json"); int ret = 0; uint32_t configSize = (uint32_t)cJSON_GetArraySize(configs); for (uint32_t i = 0; i < configSize; i++) { cJSON *json = cJSON_GetArrayItem(configs, i); ret = ParsePermissionConfig(json, mgr); APPSPAWN_CHECK(ret == 0, return ret, "Parse permission config fail result: %{public}d ", ret); } return ret; } static PermissionManager *GetPermissionMgrByType(AppSpawnClientType type) { APPSPAWN_CHECK_ONLY_EXPER(type < CLIENT_MAX, return NULL); g_permissionMgr[0].type = CLIENT_FOR_APPSPAWN; return &g_permissionMgr[0]; } #endif static int LoadPermissionConfig(PermissionManager *mgr) { int ret = ParseJsonConfig("etc/sandbox", mgr->type == CLIENT_FOR_APPSPAWN ? APP_SANDBOX_FILE_NAME : WEB_SANDBOX_FILE_NAME, ParseAppSandboxConfig, mgr); APPSPAWN_CHECK(ret == 0, return ret, "Load sandbox fail %{public}d", ret); mgr->maxPermissionIndex = PermissionRenumber(&mgr->permissionQueue); return 0; } static inline int32_t CheckPermissionManager(PermissionManager *mgr) { if (mgr != NULL && mgr->inited) { return 1; } return 0; } static int32_t PMGetPermissionIndex(AppSpawnClientType type, const char *permission) { PermissionManager *mgr = GetPermissionMgrByType(type); APPSPAWN_CHECK_ONLY_EXPER(CheckPermissionManager(mgr), return INVALID_PERMISSION_INDEX); return GetPermissionIndexInQueue((SandboxQueue *)&mgr->permissionQueue, permission); } static int32_t PMGetMaxPermissionIndex(AppSpawnClientType type) { PermissionManager *mgr = GetPermissionMgrByType(type); APPSPAWN_CHECK_ONLY_EXPER(CheckPermissionManager(mgr), return INVALID_PERMISSION_INDEX); return mgr->maxPermissionIndex; } static const char *PMGetPermissionByIndex(AppSpawnClientType type, int32_t index) { PermissionManager *mgr = GetPermissionMgrByType(type); APPSPAWN_CHECK_ONLY_EXPER(CheckPermissionManager(mgr), return NULL); if (mgr->maxPermissionIndex <= index) { return NULL; } const SandboxPermissionNode *node = GetPermissionNodeInQueueByIndex((SandboxQueue *)&mgr->permissionQueue, index); return PERMISSION_NAME(node); } APPSPAWN_STATIC int LoadPermission(AppSpawnClientType type) { APPSPAWN_LOGW("LoadPermission %{public}d", type); pthread_mutex_lock(&g_mutex); PermissionManager *mgr = GetPermissionMgrByType(type); if (mgr == NULL) { pthread_mutex_unlock(&g_mutex); return APPSPAWN_ARG_INVALID; } if (mgr->inited) { pthread_mutex_unlock(&g_mutex); return 0; } mgr->maxPermissionIndex = -1; mgr->permissionQueue.type = 0; OH_ListInit(&mgr->permissionQueue.front); int ret = LoadPermissionConfig(mgr); if (ret == 0) { mgr->inited = 1; } pthread_mutex_unlock(&g_mutex); return ret; } APPSPAWN_STATIC void DeletePermission(AppSpawnClientType type) { pthread_mutex_lock(&g_mutex); PermissionManager *mgr = GetPermissionMgrByType(type); if (mgr == NULL || !mgr->inited) { pthread_mutex_unlock(&g_mutex); return; } DeleteSandboxPermissions(&mgr->permissionQueue); mgr->maxPermissionIndex = -1; mgr->inited = 0; pthread_mutex_unlock(&g_mutex); } int32_t GetPermissionMaxCount() { int32_t maxCount = 0; for (uint32_t i = 0; i < CLIENT_MAX; i++) { int32_t max = PMGetMaxPermissionIndex(i); if (max > maxCount) { maxCount = max; } } return maxCount; } int32_t GetPermissionIndex(AppSpawnClientHandle handle, const char *permission) { APPSPAWN_CHECK(permission != NULL, return INVALID_PERMISSION_INDEX, "Invalid permission name"); if (handle == NULL) { return PMGetPermissionIndex(CLIENT_FOR_APPSPAWN, permission); } AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle; return PMGetPermissionIndex(reqMgr->type, permission); } int32_t GetMaxPermissionIndex(AppSpawnClientHandle handle) { if (handle == NULL) { return PMGetMaxPermissionIndex(CLIENT_FOR_APPSPAWN); } AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle; return PMGetMaxPermissionIndex(reqMgr->type); } const char *GetPermissionByIndex(AppSpawnClientHandle handle, int32_t index) { if (handle == NULL) { return PMGetPermissionByIndex(CLIENT_FOR_APPSPAWN, index); } AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle; return PMGetPermissionByIndex(reqMgr->type, index); } __attribute__((constructor)) static void LoadPermissionModule(void) { (void)LoadPermission(CLIENT_FOR_APPSPAWN); (void)LoadPermission(CLIENT_FOR_NWEBSPAWN); } __attribute__((destructor)) static void DeletePermissionModule(void) { DeletePermission(CLIENT_FOR_APPSPAWN); DeletePermission(CLIENT_FOR_NWEBSPAWN); }