1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci#include "param_base.h" 16d9f0492fSopenharmony_ci 17d9f0492fSopenharmony_ci#include <ctype.h> 18d9f0492fSopenharmony_ci#include <errno.h> 19d9f0492fSopenharmony_ci#include <limits.h> 20d9f0492fSopenharmony_ci 21d9f0492fSopenharmony_ci#include "init_param.h" 22d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 23d9f0492fSopenharmony_ci#include "param_include.h" 24d9f0492fSopenharmony_ci#endif 25d9f0492fSopenharmony_ci#include "param_manager.h" 26d9f0492fSopenharmony_ci#include "param_security.h" 27d9f0492fSopenharmony_ci#include "param_trie.h" 28d9f0492fSopenharmony_ci 29d9f0492fSopenharmony_ci#define PUBLIC_APP_BEGIN_UID 10000 30d9f0492fSopenharmony_ci 31d9f0492fSopenharmony_cistatic ParamWorkSpace g_paramWorkSpace = {0}; 32d9f0492fSopenharmony_ci 33d9f0492fSopenharmony_cistatic int CheckParamPermission_(const ParamLabelIndex *labelIndex, 34d9f0492fSopenharmony_ci const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode); 35d9f0492fSopenharmony_ciSTATIC_INLINE int CheckAndExtendSpace(ParamWorkSpace *workSpace, const char *name, uint32_t labelIndex); 36d9f0492fSopenharmony_ciSTATIC_INLINE ParamTrieNode *BaseFindTrieNode(WorkSpace *workSpace, 37d9f0492fSopenharmony_ci const char *key, uint32_t keyLen, uint32_t *matchLabel); 38d9f0492fSopenharmony_ciSTATIC_INLINE const char *CachedParameterCheck(CachedParameter *param, int *changed); 39d9f0492fSopenharmony_ci 40d9f0492fSopenharmony_cistatic int InitParamSecurity(ParamWorkSpace *workSpace, 41d9f0492fSopenharmony_ci RegisterSecurityOpsPtr registerOps, ParamSecurityType type, int isInit, int op) 42d9f0492fSopenharmony_ci{ 43d9f0492fSopenharmony_ci PARAM_CHECK(workSpace != NULL && type < PARAM_SECURITY_MAX, return -1, "Invalid param"); 44d9f0492fSopenharmony_ci registerOps(&workSpace->paramSecurityOps[type], isInit); 45d9f0492fSopenharmony_ci PARAM_CHECK(workSpace->paramSecurityOps[type].securityInitLabel != NULL, 46d9f0492fSopenharmony_ci return -1, "Invalid securityInitLabel"); 47d9f0492fSopenharmony_ci int ret = workSpace->paramSecurityOps[type].securityInitLabel(&workSpace->securityLabel, isInit); 48d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Failed to init security"); 49d9f0492fSopenharmony_ci 50d9f0492fSopenharmony_ci ParamSecurityOps *paramSecurityOps = GetParamSecurityOps(type); 51d9f0492fSopenharmony_ci PARAM_CHECK(paramSecurityOps != NULL, return -1, "Invalid paramSecurityOps"); 52d9f0492fSopenharmony_ci PARAM_CHECK(paramSecurityOps->securityFreeLabel != NULL, return -1, "Invalid securityFreeLabel"); 53d9f0492fSopenharmony_ci PARAM_CHECK(paramSecurityOps->securityCheckFilePermission != NULL, return -1, "Invalid securityCheck"); 54d9f0492fSopenharmony_ci if (isInit == LABEL_INIT_FOR_INIT) { 55d9f0492fSopenharmony_ci PARAM_CHECK(paramSecurityOps->securityGetLabel != NULL, return -1, "Invalid securityGetLabel"); 56d9f0492fSopenharmony_ci } 57d9f0492fSopenharmony_ci ret = paramSecurityOps->securityCheckFilePermission(&workSpace->securityLabel, PARAM_STORAGE_PATH, op); 58d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "No permission to read file %s", PARAM_STORAGE_PATH); 59d9f0492fSopenharmony_ci PARAM_LOGV("Init parameter %s success", paramSecurityOps->name); 60d9f0492fSopenharmony_ci return 0; 61d9f0492fSopenharmony_ci} 62d9f0492fSopenharmony_ci 63d9f0492fSopenharmony_ciINIT_LOCAL_API int RegisterSecurityOps(int onlyRead) 64d9f0492fSopenharmony_ci{ 65d9f0492fSopenharmony_ci int isInit = 0; 66d9f0492fSopenharmony_ci int op = DAC_READ; 67d9f0492fSopenharmony_ci if (onlyRead == 0) { 68d9f0492fSopenharmony_ci isInit = LABEL_INIT_FOR_INIT; 69d9f0492fSopenharmony_ci op = DAC_WRITE; 70d9f0492fSopenharmony_ci } 71d9f0492fSopenharmony_ci int ret = InitParamSecurity(&g_paramWorkSpace, RegisterSecurityDacOps, PARAM_SECURITY_DAC, isInit, op); 72d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to get security operations"); 73d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 74d9f0492fSopenharmony_ci ret = InitParamSecurity(&g_paramWorkSpace, RegisterSecuritySelinuxOps, PARAM_SECURITY_SELINUX, isInit, op); 75d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to get security operations"); 76d9f0492fSopenharmony_ci#endif 77d9f0492fSopenharmony_ci return ret; 78d9f0492fSopenharmony_ci} 79d9f0492fSopenharmony_ci 80d9f0492fSopenharmony_cistatic int CheckNeedInit(int onlyRead, const PARAM_WORKSPACE_OPS *ops) 81d9f0492fSopenharmony_ci{ 82d9f0492fSopenharmony_ci if (ops != NULL) { 83d9f0492fSopenharmony_ci g_paramWorkSpace.ops.updaterMode = ops->updaterMode; 84d9f0492fSopenharmony_ci if (ops->getServiceGroupIdByPid != NULL) { 85d9f0492fSopenharmony_ci g_paramWorkSpace.ops.getServiceGroupIdByPid = ops->getServiceGroupIdByPid; 86d9f0492fSopenharmony_ci } 87d9f0492fSopenharmony_ci if (ops->logFunc != NULL) { 88d9f0492fSopenharmony_ci if (onlyRead == 0) { 89d9f0492fSopenharmony_ci g_paramWorkSpace.ops.logFunc = ops->logFunc; 90d9f0492fSopenharmony_ci } else if (g_paramWorkSpace.ops.logFunc == NULL) { 91d9f0492fSopenharmony_ci g_paramWorkSpace.ops.logFunc = ops->logFunc; 92d9f0492fSopenharmony_ci } 93d9f0492fSopenharmony_ci } 94d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 95d9f0492fSopenharmony_ci g_paramWorkSpace.ops.setfilecon = ops->setfilecon; 96d9f0492fSopenharmony_ci#endif 97d9f0492fSopenharmony_ci } 98d9f0492fSopenharmony_ci if (PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT)) { 99d9f0492fSopenharmony_ci PARAM_LOGV("Param workspace has been init"); 100d9f0492fSopenharmony_ci if (PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_FOR_INIT)) { 101d9f0492fSopenharmony_ci return 0; // init has been init workspace, do not init 102d9f0492fSopenharmony_ci } 103d9f0492fSopenharmony_ci if (onlyRead == 0) { // init not init workspace, do init it 104d9f0492fSopenharmony_ci CloseParamWorkSpace(); 105d9f0492fSopenharmony_ci return 1; 106d9f0492fSopenharmony_ci } 107d9f0492fSopenharmony_ci return 0; 108d9f0492fSopenharmony_ci } 109d9f0492fSopenharmony_ci if (onlyRead == 0) { 110d9f0492fSopenharmony_ci return 1; 111d9f0492fSopenharmony_ci } 112d9f0492fSopenharmony_ci#ifdef STARTUP_INIT_TEST 113d9f0492fSopenharmony_ci // for ut, do not init workspace 114d9f0492fSopenharmony_ci char path[PATH_MAX] = { 0 }; 115d9f0492fSopenharmony_ci (void)readlink("/proc/self/exe", path, sizeof(path) - 1); 116d9f0492fSopenharmony_ci char *name = strstr(path, "/init_unittest"); 117d9f0492fSopenharmony_ci if (name != NULL) { 118d9f0492fSopenharmony_ci PARAM_LOGW("Can not init client for init_test"); 119d9f0492fSopenharmony_ci return 0; 120d9f0492fSopenharmony_ci } 121d9f0492fSopenharmony_ci#endif 122d9f0492fSopenharmony_ci return 1; 123d9f0492fSopenharmony_ci} 124d9f0492fSopenharmony_ci 125d9f0492fSopenharmony_cistatic int AllocSpaceMemory(uint32_t maxLabel) 126d9f0492fSopenharmony_ci{ 127d9f0492fSopenharmony_ci WorkSpace *workSpace = GetWorkSpace(WORKSPACE_INDEX_SIZE); 128d9f0492fSopenharmony_ci PARAM_CHECK(workSpace != NULL, return PARAM_CODE_ERROR, "Invalid dac workspace"); 129d9f0492fSopenharmony_ci if (workSpace->area->spaceSizeOffset != 0) { 130d9f0492fSopenharmony_ci return 0; 131d9f0492fSopenharmony_ci } 132d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 133d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return -1, "Invalid workspace"); 134d9f0492fSopenharmony_ci uint32_t realLen = PARAM_ALIGN(sizeof(WorkSpaceSize) + sizeof(uint32_t) * maxLabel); 135d9f0492fSopenharmony_ci PARAM_CHECK((workSpace->area->currOffset + realLen) < workSpace->area->dataSize, return 0, 136d9f0492fSopenharmony_ci "Failed to allocate currOffset %u, dataSize %u datalen %u", 137d9f0492fSopenharmony_ci workSpace->area->currOffset, workSpace->area->dataSize, realLen); 138d9f0492fSopenharmony_ci WorkSpaceSize *node = (WorkSpaceSize *)(workSpace->area->data + workSpace->area->currOffset); 139d9f0492fSopenharmony_ci node->maxLabelIndex = maxLabel; 140d9f0492fSopenharmony_ci node->spaceSize[WORKSPACE_INDEX_DAC] = PARAM_WORKSPACE_DAC; 141d9f0492fSopenharmony_ci node->spaceSize[WORKSPACE_INDEX_BASE] = PARAM_WORKSPACE_MAX; 142d9f0492fSopenharmony_ci for (uint32_t i = WORKSPACE_INDEX_BASE + 1; i < maxLabel; i++) { 143d9f0492fSopenharmony_ci node->spaceSize[i] = PARAM_WORKSPACE_MIN; 144d9f0492fSopenharmony_ci PARAM_LOGV("AllocSpaceMemory spaceSize index %u %u", i, node->spaceSize[i]); 145d9f0492fSopenharmony_ci if (paramSpace->workSpace[i] != NULL) { 146d9f0492fSopenharmony_ci paramSpace->workSpace[i]->spaceSize = PARAM_WORKSPACE_MIN; 147d9f0492fSopenharmony_ci } 148d9f0492fSopenharmony_ci } 149d9f0492fSopenharmony_ci workSpace->area->spaceSizeOffset = workSpace->area->currOffset; 150d9f0492fSopenharmony_ci workSpace->area->currOffset += realLen; 151d9f0492fSopenharmony_ci return 0; 152d9f0492fSopenharmony_ci} 153d9f0492fSopenharmony_ci 154d9f0492fSopenharmony_cistatic int CreateWorkSpace(int onlyRead) 155d9f0492fSopenharmony_ci{ 156d9f0492fSopenharmony_ci int ret = 0; 157d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 158d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return -1, "Invalid workspace"); 159d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 160d9f0492fSopenharmony_ci ret = AddWorkSpace(WORKSPACE_NAME_DAC, WORKSPACE_INDEX_DAC, 0, PARAM_WORKSPACE_DAC); 161d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to add dac workspace"); 162d9f0492fSopenharmony_ci ret = AddWorkSpace(WORKSPACE_NAME_DEF_SELINUX, WORKSPACE_INDEX_BASE, onlyRead, PARAM_WORKSPACE_MAX); 163d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to add default workspace"); 164d9f0492fSopenharmony_ci 165d9f0492fSopenharmony_ci // open dac workspace 166d9f0492fSopenharmony_ci ret = OpenWorkSpace(WORKSPACE_INDEX_DAC, onlyRead); 167d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to open dac workspace"); 168d9f0492fSopenharmony_ci 169d9f0492fSopenharmony_ci // for other workspace 170d9f0492fSopenharmony_ci ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); 171d9f0492fSopenharmony_ci if (ops != NULL && ops->securityGetLabel != NULL) { 172d9f0492fSopenharmony_ci ret = ops->securityGetLabel("create"); 173d9f0492fSopenharmony_ci } 174d9f0492fSopenharmony_ci paramSpace->maxLabelIndex++; 175d9f0492fSopenharmony_ci#else 176d9f0492fSopenharmony_ci ret = AddWorkSpace(WORKSPACE_NAME_NORMAL, WORKSPACE_INDEX_DAC, onlyRead, PARAM_WORKSPACE_MAX); 177d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to add dac workspace"); 178d9f0492fSopenharmony_ci ret = OpenWorkSpace(WORKSPACE_INDEX_DAC, onlyRead); 179d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to open dac workspace"); 180d9f0492fSopenharmony_ci paramSpace->maxLabelIndex = 1; 181d9f0492fSopenharmony_ci#endif 182d9f0492fSopenharmony_ci return ret; 183d9f0492fSopenharmony_ci} 184d9f0492fSopenharmony_ci 185d9f0492fSopenharmony_ciINIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *ops) 186d9f0492fSopenharmony_ci{ 187d9f0492fSopenharmony_ci PARAM_ONLY_CHECK(CheckNeedInit(onlyRead, ops) != 0, return 0); 188d9f0492fSopenharmony_ci 189d9f0492fSopenharmony_ci paramMutexEnvInit(); 190d9f0492fSopenharmony_ci if (!PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT)) { 191d9f0492fSopenharmony_ci g_paramWorkSpace.maxSpaceCount = PARAM_DEF_SELINUX_LABEL; 192d9f0492fSopenharmony_ci g_paramWorkSpace.workSpace = (WorkSpace **)calloc(g_paramWorkSpace.maxSpaceCount, sizeof(WorkSpace *)); 193d9f0492fSopenharmony_ci PARAM_CHECK(g_paramWorkSpace.workSpace != NULL, return -1, "Failed to alloc memory for workSpace"); 194d9f0492fSopenharmony_ci } 195d9f0492fSopenharmony_ci PARAM_SET_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT); 196d9f0492fSopenharmony_ci 197d9f0492fSopenharmony_ci int ret = RegisterSecurityOps(onlyRead); 198d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to get security operations"); 199d9f0492fSopenharmony_ci g_paramWorkSpace.checkParamPermission = CheckParamPermission_; 200d9f0492fSopenharmony_ci ret = CreateWorkSpace(onlyRead); 201d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to create workspace"); 202d9f0492fSopenharmony_ci 203d9f0492fSopenharmony_ci if (onlyRead == 0) { 204d9f0492fSopenharmony_ci PARAM_LOGI("Max selinux label %u %u", g_paramWorkSpace.maxSpaceCount, g_paramWorkSpace.maxLabelIndex); 205d9f0492fSopenharmony_ci // alloc space size memory from dac 206d9f0492fSopenharmony_ci ret = AllocSpaceMemory(g_paramWorkSpace.maxLabelIndex); 207d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to alloc space size"); 208d9f0492fSopenharmony_ci 209d9f0492fSopenharmony_ci // add default dac policy 210d9f0492fSopenharmony_ci ParamAuditData auditData = {0}; 211d9f0492fSopenharmony_ci auditData.name = "#"; 212d9f0492fSopenharmony_ci auditData.dacData.gid = DAC_DEFAULT_GROUP; 213d9f0492fSopenharmony_ci auditData.dacData.uid = DAC_DEFAULT_USER; 214d9f0492fSopenharmony_ci auditData.dacData.mode = DAC_DEFAULT_MODE; // 0774 default mode 215d9f0492fSopenharmony_ci auditData.dacData.paramType = PARAM_TYPE_STRING; 216d9f0492fSopenharmony_ci auditData.memberNum = 1; 217d9f0492fSopenharmony_ci auditData.members[0] = DAC_DEFAULT_GROUP; 218d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 219d9f0492fSopenharmony_ci auditData.selinuxIndex = INVALID_SELINUX_INDEX; 220d9f0492fSopenharmony_ci#endif 221d9f0492fSopenharmony_ci ret = AddSecurityLabel(&auditData); 222d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Failed to add default dac label"); 223d9f0492fSopenharmony_ci PARAM_SET_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_FOR_INIT); 224d9f0492fSopenharmony_ci } 225d9f0492fSopenharmony_ci return ret; 226d9f0492fSopenharmony_ci} 227d9f0492fSopenharmony_ci 228d9f0492fSopenharmony_ciINIT_LOCAL_API void CloseParamWorkSpace(void) 229d9f0492fSopenharmony_ci{ 230d9f0492fSopenharmony_ci PARAM_LOGI("CloseParamWorkSpace %x", g_paramWorkSpace.flags); 231d9f0492fSopenharmony_ci if (!PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT)) { 232d9f0492fSopenharmony_ci return; 233d9f0492fSopenharmony_ci } 234d9f0492fSopenharmony_ci for (uint32_t i = 0; i < g_paramWorkSpace.maxSpaceCount; i++) { 235d9f0492fSopenharmony_ci if (g_paramWorkSpace.workSpace[i] != NULL) { 236d9f0492fSopenharmony_ci CloseWorkSpace(g_paramWorkSpace.workSpace[i]); 237d9f0492fSopenharmony_ci free(g_paramWorkSpace.workSpace[i]); 238d9f0492fSopenharmony_ci } 239d9f0492fSopenharmony_ci g_paramWorkSpace.workSpace[i] = NULL; 240d9f0492fSopenharmony_ci } 241d9f0492fSopenharmony_ci free(g_paramWorkSpace.workSpace); 242d9f0492fSopenharmony_ci g_paramWorkSpace.workSpace = NULL; 243d9f0492fSopenharmony_ci for (int i = 0; i < PARAM_SECURITY_MAX; i++) { 244d9f0492fSopenharmony_ci if (g_paramWorkSpace.paramSecurityOps[i].securityFreeLabel != NULL) { 245d9f0492fSopenharmony_ci g_paramWorkSpace.paramSecurityOps[i].securityFreeLabel(&g_paramWorkSpace.securityLabel); 246d9f0492fSopenharmony_ci } 247d9f0492fSopenharmony_ci } 248d9f0492fSopenharmony_ci g_paramWorkSpace.flags = 0; 249d9f0492fSopenharmony_ci} 250d9f0492fSopenharmony_ci 251d9f0492fSopenharmony_ciINIT_LOCAL_API void ParamWorBaseLog(InitLogLevel logLevel, uint32_t domain, const char *tag, const char *fmt, ...) 252d9f0492fSopenharmony_ci{ 253d9f0492fSopenharmony_ci if (g_paramWorkSpace.ops.logFunc != NULL) { 254d9f0492fSopenharmony_ci va_list vargs; 255d9f0492fSopenharmony_ci va_start(vargs, fmt); 256d9f0492fSopenharmony_ci g_paramWorkSpace.ops.logFunc(logLevel, domain, tag, fmt, vargs); 257d9f0492fSopenharmony_ci va_end(vargs); 258d9f0492fSopenharmony_ci } 259d9f0492fSopenharmony_ci} 260d9f0492fSopenharmony_ci 261d9f0492fSopenharmony_ciINIT_INNER_API ParamWorkSpace *GetParamWorkSpace(void) 262d9f0492fSopenharmony_ci{ 263d9f0492fSopenharmony_ci return &g_paramWorkSpace; 264d9f0492fSopenharmony_ci} 265d9f0492fSopenharmony_ci 266d9f0492fSopenharmony_civoid InitParameterClient(void) 267d9f0492fSopenharmony_ci{ 268d9f0492fSopenharmony_ci PARAM_WORKSPACE_OPS ops = {0}; 269d9f0492fSopenharmony_ci ops.updaterMode = 0; 270d9f0492fSopenharmony_ci InitParamWorkSpace(1, &ops); 271d9f0492fSopenharmony_ci} 272d9f0492fSopenharmony_ci 273d9f0492fSopenharmony_ciINIT_LOCAL_API int AddWorkSpace(const char *name, uint32_t labelIndex, int onlyRead, uint32_t spaceSize) 274d9f0492fSopenharmony_ci{ 275d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 276d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return -1, "Invalid workspace"); 277d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 278d9f0492fSopenharmony_ci const char *realName = name; 279d9f0492fSopenharmony_ci#else 280d9f0492fSopenharmony_ci const char *realName = WORKSPACE_NAME_NORMAL; 281d9f0492fSopenharmony_ci labelIndex = 0; 282d9f0492fSopenharmony_ci#endif 283d9f0492fSopenharmony_ci int ret = CheckAndExtendSpace(paramSpace, name, labelIndex); 284d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Not enough memory for %s", realName); 285d9f0492fSopenharmony_ci if (paramSpace->workSpace[labelIndex] != NULL) { 286d9f0492fSopenharmony_ci return 0; 287d9f0492fSopenharmony_ci } 288d9f0492fSopenharmony_ci const size_t size = strlen(realName) + 1; 289d9f0492fSopenharmony_ci WorkSpace *workSpace = (WorkSpace *)malloc(sizeof(WorkSpace) + size); 290d9f0492fSopenharmony_ci PARAM_CHECK(workSpace != NULL, return -1, "Failed to create workspace for %s", realName); 291d9f0492fSopenharmony_ci workSpace->flags = 0; 292d9f0492fSopenharmony_ci workSpace->spaceSize = spaceSize; 293d9f0492fSopenharmony_ci workSpace->area = NULL; 294d9f0492fSopenharmony_ci workSpace->spaceIndex = labelIndex; 295d9f0492fSopenharmony_ci ATOMIC_INIT(&workSpace->rwSpaceLock, 0); 296d9f0492fSopenharmony_ci PARAMSPACE_AREA_INIT_LOCK(workSpace); 297d9f0492fSopenharmony_ci ret = PARAM_STRCPY(workSpace->fileName, size, realName); 298d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, free(workSpace); 299d9f0492fSopenharmony_ci return -1, "Failed to copy file name %s", realName); 300d9f0492fSopenharmony_ci paramSpace->workSpace[labelIndex] = workSpace; 301d9f0492fSopenharmony_ci PARAM_LOGV("AddWorkSpace %s index %d onlyRead %s", paramSpace->workSpace[labelIndex]->fileName, 302d9f0492fSopenharmony_ci paramSpace->workSpace[labelIndex]->spaceIndex, onlyRead ? "true" : "false"); 303d9f0492fSopenharmony_ci 304d9f0492fSopenharmony_ci if (spaceSize != 0) { 305d9f0492fSopenharmony_ci return ret; 306d9f0492fSopenharmony_ci } 307d9f0492fSopenharmony_ci // get size 308d9f0492fSopenharmony_ci WorkSpaceSize *workSpaceSize = GetWorkSpaceSize(GetWorkSpace(WORKSPACE_INDEX_SIZE)); 309d9f0492fSopenharmony_ci if (workSpaceSize != NULL) { 310d9f0492fSopenharmony_ci paramSpace->workSpace[labelIndex]->spaceSize = workSpaceSize->spaceSize[labelIndex]; 311d9f0492fSopenharmony_ci } 312d9f0492fSopenharmony_ci return ret; 313d9f0492fSopenharmony_ci} 314d9f0492fSopenharmony_ci 315d9f0492fSopenharmony_ciSTATIC_INLINE int CheckAndExtendSpace(ParamWorkSpace *paramSpace, const char *name, uint32_t labelIndex) 316d9f0492fSopenharmony_ci{ 317d9f0492fSopenharmony_ci if (paramSpace->maxSpaceCount > labelIndex) { 318d9f0492fSopenharmony_ci return 0; 319d9f0492fSopenharmony_ci } 320d9f0492fSopenharmony_ci if (labelIndex >= PARAM_MAX_SELINUX_LABEL) { 321d9f0492fSopenharmony_ci PARAM_LOGE("Not enough memory for label index %u", labelIndex); 322d9f0492fSopenharmony_ci return -1; 323d9f0492fSopenharmony_ci } 324d9f0492fSopenharmony_ci PARAM_LOGW("Not enough memory for label index %u need to extend memory %u", labelIndex, paramSpace->maxSpaceCount); 325d9f0492fSopenharmony_ci WorkSpace **space = (WorkSpace **)calloc(sizeof(WorkSpace *), 326d9f0492fSopenharmony_ci paramSpace->maxSpaceCount + PARAM_DEF_SELINUX_LABEL); 327d9f0492fSopenharmony_ci PARAM_CHECK(space != NULL, return -1, "Failed to realloc memory for %s", name); 328d9f0492fSopenharmony_ci int ret = PARAM_MEMCPY(space, sizeof(WorkSpace *) * paramSpace->maxSpaceCount, 329d9f0492fSopenharmony_ci paramSpace->workSpace, sizeof(WorkSpace *) * paramSpace->maxSpaceCount); 330d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, free(space); 331d9f0492fSopenharmony_ci return -1, "Failed to copy memory for %s", name); 332d9f0492fSopenharmony_ci paramSpace->maxSpaceCount += PARAM_DEF_SELINUX_LABEL; 333d9f0492fSopenharmony_ci free(paramSpace->workSpace); 334d9f0492fSopenharmony_ci paramSpace->workSpace = space; 335d9f0492fSopenharmony_ci return 0; 336d9f0492fSopenharmony_ci} 337d9f0492fSopenharmony_ci 338d9f0492fSopenharmony_ciINIT_LOCAL_API int OpenWorkSpace(uint32_t index, int readOnly) 339d9f0492fSopenharmony_ci{ 340d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 341d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL && paramSpace->workSpace != NULL, return -1, "Invalid workspace index %u", index); 342d9f0492fSopenharmony_ci WorkSpace *workSpace = NULL; 343d9f0492fSopenharmony_ci PARAM_ONLY_CHECK(index >= paramSpace->maxSpaceCount, workSpace = paramSpace->workSpace[index]); 344d9f0492fSopenharmony_ci PARAM_CHECK(workSpace != NULL, return 0, "Invalid index %d", index); 345d9f0492fSopenharmony_ci int ret = 0; 346d9f0492fSopenharmony_ci uint32_t rwSpaceLock = ATOMIC_LOAD_EXPLICIT(&workSpace->rwSpaceLock, MEMORY_ORDER_ACQUIRE); 347d9f0492fSopenharmony_ci while (rwSpaceLock & WORKSPACE_STATUS_IN_PROCESS) { 348d9f0492fSopenharmony_ci futex_wait_private(&workSpace->rwSpaceLock, rwSpaceLock); 349d9f0492fSopenharmony_ci rwSpaceLock = ATOMIC_LOAD_EXPLICIT(&workSpace->rwSpaceLock, MEMORY_ORDER_ACQUIRE); 350d9f0492fSopenharmony_ci } 351d9f0492fSopenharmony_ci 352d9f0492fSopenharmony_ci ATOMIC_STORE_EXPLICIT(&workSpace->rwSpaceLock, rwSpaceLock | WORKSPACE_STATUS_IN_PROCESS, MEMORY_ORDER_RELEASE); 353d9f0492fSopenharmony_ci if (workSpace->area == NULL) { 354d9f0492fSopenharmony_ci ret = InitWorkSpace(workSpace, readOnly, workSpace->spaceSize); 355d9f0492fSopenharmony_ci if (ret != 0) { 356d9f0492fSopenharmony_ci PARAM_LOGE("Forbid to open workspace for %s error %d", workSpace->fileName, errno); 357d9f0492fSopenharmony_ci } 358d9f0492fSopenharmony_ci#ifndef PARAM_SUPPORT_SELINUX 359d9f0492fSopenharmony_ci } 360d9f0492fSopenharmony_ci ATOMIC_STORE_EXPLICIT(&workSpace->rwSpaceLock, rwSpaceLock & ~WORKSPACE_STATUS_IN_PROCESS, MEMORY_ORDER_RELEASE); 361d9f0492fSopenharmony_ci#else 362d9f0492fSopenharmony_ci } else if (readOnly) { 363d9f0492fSopenharmony_ci if ((rwSpaceLock & WORKSPACE_STATUS_VALID) == WORKSPACE_STATUS_VALID) { 364d9f0492fSopenharmony_ci ret = 0; 365d9f0492fSopenharmony_ci } else if ((paramSpace->flags & WORKSPACE_FLAGS_NEED_ACCESS) == WORKSPACE_FLAGS_NEED_ACCESS) { 366d9f0492fSopenharmony_ci char buffer[FILENAME_LEN_MAX] = {0}; 367d9f0492fSopenharmony_ci int size = PARAM_SPRINTF(buffer, sizeof(buffer), "%s/%s", PARAM_STORAGE_PATH, workSpace->fileName); 368d9f0492fSopenharmony_ci if (size > 0 && access(buffer, R_OK) == 0) { 369d9f0492fSopenharmony_ci PARAM_LOGW("Open workspace %s access ok ", workSpace->fileName); 370d9f0492fSopenharmony_ci rwSpaceLock |= WORKSPACE_STATUS_VALID; 371d9f0492fSopenharmony_ci ret = 0; 372d9f0492fSopenharmony_ci } else { 373d9f0492fSopenharmony_ci ret = -1; 374d9f0492fSopenharmony_ci PARAM_LOGE("Forbid to open workspace for %s error %d", workSpace->fileName, errno); 375d9f0492fSopenharmony_ci rwSpaceLock &= ~WORKSPACE_STATUS_VALID; 376d9f0492fSopenharmony_ci } 377d9f0492fSopenharmony_ci } 378d9f0492fSopenharmony_ci } 379d9f0492fSopenharmony_ci ATOMIC_STORE_EXPLICIT(&workSpace->rwSpaceLock, rwSpaceLock & ~WORKSPACE_STATUS_IN_PROCESS, MEMORY_ORDER_RELEASE); 380d9f0492fSopenharmony_ci futex_wake_private(&workSpace->rwSpaceLock, INT_MAX); 381d9f0492fSopenharmony_ci#endif 382d9f0492fSopenharmony_ci return ret; 383d9f0492fSopenharmony_ci} 384d9f0492fSopenharmony_ci 385d9f0492fSopenharmony_ciSTATIC_INLINE int ReadParamWithCheck(WorkSpace **workspace, const char *name, uint32_t op, ParamTrieNode **node) 386d9f0492fSopenharmony_ci{ 387d9f0492fSopenharmony_ci ParamLabelIndex labelIndex = {0}; 388d9f0492fSopenharmony_ci WorkSpace *dacSpace = g_paramWorkSpace.workSpace[0]; 389d9f0492fSopenharmony_ci PARAM_CHECK(dacSpace != NULL && dacSpace->area != NULL, 390d9f0492fSopenharmony_ci return DAC_RESULT_FORBIDED, "Invalid workSpace for %s", name); 391d9f0492fSopenharmony_ci *node = BaseFindTrieNode(dacSpace, name, strlen(name), &labelIndex.dacLabelIndex); 392d9f0492fSopenharmony_ci labelIndex.workspace = GetWorkSpaceByName(name); 393d9f0492fSopenharmony_ci PARAM_CHECK(labelIndex.workspace != NULL, return DAC_RESULT_FORBIDED, "Invalid workSpace for %s", name); 394d9f0492fSopenharmony_ci labelIndex.selinuxLabelIndex = labelIndex.workspace->spaceIndex; 395d9f0492fSopenharmony_ci 396d9f0492fSopenharmony_ci int ret = CheckParamPermission_(&labelIndex, &g_paramWorkSpace.securityLabel, name, op); 397d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Forbid to read parameter %s", name); 398d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 399d9f0492fSopenharmony_ci // search from real workspace 400d9f0492fSopenharmony_ci *node = BaseFindTrieNode(labelIndex.workspace, name, strlen(name), NULL); 401d9f0492fSopenharmony_ci#endif 402d9f0492fSopenharmony_ci *workspace = labelIndex.workspace; 403d9f0492fSopenharmony_ci return ret; 404d9f0492fSopenharmony_ci} 405d9f0492fSopenharmony_ci 406d9f0492fSopenharmony_cistatic int CheckUserInGroup(WorkSpace *space, const ParamSecurityNode *node, uid_t uid) 407d9f0492fSopenharmony_ci{ 408d9f0492fSopenharmony_ci for (uint32_t i = 0; i < node->memberNum; i++) { 409d9f0492fSopenharmony_ci if (node->members[i] == uid) { 410d9f0492fSopenharmony_ci return 0; 411d9f0492fSopenharmony_ci } 412d9f0492fSopenharmony_ci } 413d9f0492fSopenharmony_ci return -1; 414d9f0492fSopenharmony_ci} 415d9f0492fSopenharmony_ci 416d9f0492fSopenharmony_ciSTATIC_INLINE int DacCheckGroupPermission(const ParamSecurityLabel *srcLabel, uint32_t mode, ParamSecurityNode *node) 417d9f0492fSopenharmony_ci{ 418d9f0492fSopenharmony_ci uint32_t localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START; 419d9f0492fSopenharmony_ci if (srcLabel->cred.gid == node->gid) { 420d9f0492fSopenharmony_ci if ((node->mode & localMode) != 0) { 421d9f0492fSopenharmony_ci return DAC_RESULT_PERMISSION; 422d9f0492fSopenharmony_ci } 423d9f0492fSopenharmony_ci } 424d9f0492fSopenharmony_ci if (mode != DAC_WRITE || g_paramWorkSpace.ops.getServiceGroupIdByPid == NULL) { 425d9f0492fSopenharmony_ci return DAC_RESULT_FORBIDED; 426d9f0492fSopenharmony_ci } 427d9f0492fSopenharmony_ci gid_t gids[64] = { 0 }; // max gid number 428d9f0492fSopenharmony_ci const uint32_t gidNumber = (uint32_t)g_paramWorkSpace.ops.getServiceGroupIdByPid( 429d9f0492fSopenharmony_ci srcLabel->cred.pid, gids, sizeof(gids) / sizeof(gids[0])); 430d9f0492fSopenharmony_ci for (uint32_t index = 0; index < gidNumber; index++) { 431d9f0492fSopenharmony_ci PARAM_LOGV("DacCheckGroupPermission gid %u", gids[index]); 432d9f0492fSopenharmony_ci if (gids[index] != node->gid) { 433d9f0492fSopenharmony_ci continue; 434d9f0492fSopenharmony_ci } 435d9f0492fSopenharmony_ci if ((node->mode & localMode) != 0) { 436d9f0492fSopenharmony_ci return DAC_RESULT_PERMISSION; 437d9f0492fSopenharmony_ci } 438d9f0492fSopenharmony_ci } 439d9f0492fSopenharmony_ci return DAC_RESULT_FORBIDED; 440d9f0492fSopenharmony_ci} 441d9f0492fSopenharmony_ci 442d9f0492fSopenharmony_ciSTATIC_INLINE int DacCheckParamPermission(const ParamLabelIndex *labelIndex, 443d9f0492fSopenharmony_ci const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) 444d9f0492fSopenharmony_ci{ 445d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 446d9f0492fSopenharmony_ci if (srcLabel->cred.uid == 0) { 447d9f0492fSopenharmony_ci return DAC_RESULT_PERMISSION; 448d9f0492fSopenharmony_ci } 449d9f0492fSopenharmony_ci#endif 450d9f0492fSopenharmony_ci // get dac label 451d9f0492fSopenharmony_ci WorkSpace *space = g_paramWorkSpace.workSpace[WORKSPACE_INDEX_DAC]; 452d9f0492fSopenharmony_ci ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, labelIndex->dacLabelIndex); 453d9f0492fSopenharmony_ci PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %u selinuxLabelIndex %u for %s", 454d9f0492fSopenharmony_ci labelIndex->dacLabelIndex, labelIndex->selinuxLabelIndex, name); 455d9f0492fSopenharmony_ci /** 456d9f0492fSopenharmony_ci * DAC group 457d9f0492fSopenharmony_ci * user:group:read|write|watch 458d9f0492fSopenharmony_ci */ 459d9f0492fSopenharmony_ci uint32_t localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_OTHER_START; 460d9f0492fSopenharmony_ci // 1, check other 461d9f0492fSopenharmony_ci if ((node->mode & localMode) != 0) { 462d9f0492fSopenharmony_ci return DAC_RESULT_PERMISSION; 463d9f0492fSopenharmony_ci } 464d9f0492fSopenharmony_ci // 2, check uid 465d9f0492fSopenharmony_ci if (srcLabel->cred.uid == node->uid) { 466d9f0492fSopenharmony_ci localMode = mode & (DAC_READ | DAC_WRITE | DAC_WATCH); 467d9f0492fSopenharmony_ci if ((node->mode & localMode) != 0) { 468d9f0492fSopenharmony_ci return DAC_RESULT_PERMISSION; 469d9f0492fSopenharmony_ci } 470d9f0492fSopenharmony_ci } 471d9f0492fSopenharmony_ci // 3, check gid 472d9f0492fSopenharmony_ci if (DacCheckGroupPermission(srcLabel, mode, node) == DAC_RESULT_PERMISSION) { 473d9f0492fSopenharmony_ci return DAC_RESULT_PERMISSION; 474d9f0492fSopenharmony_ci } 475d9f0492fSopenharmony_ci // 4, check user in group 476d9f0492fSopenharmony_ci if (CheckUserInGroup(space, node, srcLabel->cred.uid) == 0) { 477d9f0492fSopenharmony_ci localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START; 478d9f0492fSopenharmony_ci if ((node->mode & localMode) != 0) { 479d9f0492fSopenharmony_ci return DAC_RESULT_PERMISSION; 480d9f0492fSopenharmony_ci } 481d9f0492fSopenharmony_ci } 482d9f0492fSopenharmony_ci // forbid 483d9f0492fSopenharmony_ci PARAM_LOGW("Param '%s' label gid:%d uid:%d mode 0%x", name, srcLabel->cred.gid, srcLabel->cred.uid, mode); 484d9f0492fSopenharmony_ci PARAM_LOGW("Cfg label %u gid:%d uid:%d mode 0%x ", labelIndex->dacLabelIndex, node->gid, node->uid, node->mode); 485d9f0492fSopenharmony_ci 486d9f0492fSopenharmony_ci int ret = DAC_RESULT_FORBIDED; 487d9f0492fSopenharmony_ci#ifndef __MUSL__ 488d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 489d9f0492fSopenharmony_ci ret = DAC_RESULT_PERMISSION; 490d9f0492fSopenharmony_ci#endif 491d9f0492fSopenharmony_ci#endif 492d9f0492fSopenharmony_ci return ret; 493d9f0492fSopenharmony_ci} 494d9f0492fSopenharmony_ci 495d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 496d9f0492fSopenharmony_ciSTATIC_INLINE const char *GetSelinuxContent(const char *name) 497d9f0492fSopenharmony_ci{ 498d9f0492fSopenharmony_ci SelinuxSpace *selinuxSpace = &g_paramWorkSpace.selinuxSpace; 499d9f0492fSopenharmony_ci const char *content = WORKSPACE_NAME_DEF_SELINUX; 500d9f0492fSopenharmony_ci if (selinuxSpace->getParamLabel != NULL) { 501d9f0492fSopenharmony_ci content = selinuxSpace->getParamLabel(name); 502d9f0492fSopenharmony_ci } 503d9f0492fSopenharmony_ci return content; 504d9f0492fSopenharmony_ci} 505d9f0492fSopenharmony_ci 506d9f0492fSopenharmony_ciSTATIC_INLINE int SelinuxCheckParamPermission(const ParamLabelIndex *labelIndex, 507d9f0492fSopenharmony_ci const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) 508d9f0492fSopenharmony_ci{ 509d9f0492fSopenharmony_ci SelinuxSpace *selinuxSpace = &g_paramWorkSpace.selinuxSpace; 510d9f0492fSopenharmony_ci int ret = SELINUX_RESULT_FORBIDED; 511d9f0492fSopenharmony_ci if (mode == DAC_WRITE) { 512d9f0492fSopenharmony_ci PARAM_CHECK(selinuxSpace->setParamCheck != NULL, return ret, "Invalid setParamCheck"); 513d9f0492fSopenharmony_ci // check 514d9f0492fSopenharmony_ci SrcInfo info; 515d9f0492fSopenharmony_ci info.uc.pid = srcLabel->cred.pid; 516d9f0492fSopenharmony_ci info.uc.uid = srcLabel->cred.uid; 517d9f0492fSopenharmony_ci info.uc.gid = srcLabel->cred.gid; 518d9f0492fSopenharmony_ci info.sockFd = srcLabel->sockFd; 519d9f0492fSopenharmony_ci const char *context = GetSelinuxContent(name); 520d9f0492fSopenharmony_ci ret = selinuxSpace->setParamCheck(name, context, &info); 521d9f0492fSopenharmony_ci } else { 522d9f0492fSopenharmony_ci#ifdef STARTUP_INIT_TEST 523d9f0492fSopenharmony_ci return selinuxSpace->readParamCheck(name); 524d9f0492fSopenharmony_ci#endif 525d9f0492fSopenharmony_ci ret = OpenWorkSpace(labelIndex->selinuxLabelIndex, 1); 526d9f0492fSopenharmony_ci } 527d9f0492fSopenharmony_ci if (ret != 0) { 528d9f0492fSopenharmony_ci ret = SELINUX_RESULT_FORBIDED; 529d9f0492fSopenharmony_ci PARAM_LOGE("Selinux check name %s in %s info [%d %d %d] failed!", 530d9f0492fSopenharmony_ci name, GetSelinuxContent(name), srcLabel->cred.pid, srcLabel->cred.uid, srcLabel->cred.gid); 531d9f0492fSopenharmony_ci } 532d9f0492fSopenharmony_ci return ret; 533d9f0492fSopenharmony_ci} 534d9f0492fSopenharmony_ci#endif 535d9f0492fSopenharmony_ci 536d9f0492fSopenharmony_ci#if defined(STARTUP_INIT_TEST) || defined(__LITEOS_A__) || defined(__LITEOS_M__) 537d9f0492fSopenharmony_cistatic int CheckParamPermission_(const ParamLabelIndex *labelIndex, 538d9f0492fSopenharmony_ci const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) 539d9f0492fSopenharmony_ci{ 540d9f0492fSopenharmony_ci // for root, all permission, but for appspawn must to check 541d9f0492fSopenharmony_ci if (srcLabel->cred.uid == 0 && srcLabel->cred.pid == 1) { 542d9f0492fSopenharmony_ci return DAC_RESULT_PERMISSION; 543d9f0492fSopenharmony_ci } 544d9f0492fSopenharmony_ci int ret = DAC_RESULT_PERMISSION; 545d9f0492fSopenharmony_ci for (int i = 0; i < PARAM_SECURITY_MAX; i++) { 546d9f0492fSopenharmony_ci if (PARAM_TEST_FLAG(g_paramWorkSpace.securityLabel.flags[i], LABEL_ALL_PERMISSION)) { 547d9f0492fSopenharmony_ci continue; 548d9f0492fSopenharmony_ci } 549d9f0492fSopenharmony_ci ParamSecurityOps *ops = &g_paramWorkSpace.paramSecurityOps[i]; 550d9f0492fSopenharmony_ci if (ops->securityCheckParamPermission == NULL) { 551d9f0492fSopenharmony_ci continue; 552d9f0492fSopenharmony_ci } 553d9f0492fSopenharmony_ci ret = ops->securityCheckParamPermission(labelIndex, srcLabel, name, mode); 554d9f0492fSopenharmony_ci if (ret == DAC_RESULT_FORBIDED) { 555d9f0492fSopenharmony_ci PARAM_LOGW("CheckParamPermission %s %s FORBID", ops->name, name); 556d9f0492fSopenharmony_ci break; 557d9f0492fSopenharmony_ci } 558d9f0492fSopenharmony_ci } 559d9f0492fSopenharmony_ci return ret; 560d9f0492fSopenharmony_ci} 561d9f0492fSopenharmony_ci#else 562d9f0492fSopenharmony_cistatic int CheckParamPermission_(const ParamLabelIndex *labelIndex, 563d9f0492fSopenharmony_ci const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) 564d9f0492fSopenharmony_ci{ 565d9f0492fSopenharmony_ci // only for root and write, all permission, but for appspawn must to check 566d9f0492fSopenharmony_ci // for clod start in new namespace, pid==1 and uid==root 567d9f0492fSopenharmony_ci if (srcLabel->cred.uid == 0 && srcLabel->cred.pid == 1 && mode == DAC_WRITE) { 568d9f0492fSopenharmony_ci return DAC_RESULT_PERMISSION; 569d9f0492fSopenharmony_ci } 570d9f0492fSopenharmony_ci int ret = 0; 571d9f0492fSopenharmony_ci if (srcLabel->cred.uid < PUBLIC_APP_BEGIN_UID) { 572d9f0492fSopenharmony_ci ret = DacCheckParamPermission(labelIndex, srcLabel, name, mode); 573d9f0492fSopenharmony_ci } 574d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 575d9f0492fSopenharmony_ci if (ret == DAC_RESULT_PERMISSION) { 576d9f0492fSopenharmony_ci ret = SelinuxCheckParamPermission(labelIndex, srcLabel, name, mode); 577d9f0492fSopenharmony_ci } 578d9f0492fSopenharmony_ci#endif 579d9f0492fSopenharmony_ci return ret; 580d9f0492fSopenharmony_ci} 581d9f0492fSopenharmony_ci#endif 582d9f0492fSopenharmony_ci 583d9f0492fSopenharmony_ciSTATIC_INLINE ParamTrieNode *BaseFindTrieNode(WorkSpace *workSpace, 584d9f0492fSopenharmony_ci const char *key, uint32_t keyLen, uint32_t *matchLabel) 585d9f0492fSopenharmony_ci{ 586d9f0492fSopenharmony_ci PARAM_CHECK(key != NULL && keyLen > 0, return NULL, "Invalid key "); 587d9f0492fSopenharmony_ci uint32_t tmpMatchLen = 0; 588d9f0492fSopenharmony_ci ParamTrieNode *node = FindTrieNode_(workSpace, key, keyLen, &tmpMatchLen); 589d9f0492fSopenharmony_ci if (matchLabel != NULL) { 590d9f0492fSopenharmony_ci *matchLabel = tmpMatchLen; 591d9f0492fSopenharmony_ci } 592d9f0492fSopenharmony_ci if (node != NULL && node->dataIndex != 0) { 593d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, node->dataIndex); 594d9f0492fSopenharmony_ci if (entry != NULL && entry->keyLength == keyLen) { 595d9f0492fSopenharmony_ci return node; 596d9f0492fSopenharmony_ci } 597d9f0492fSopenharmony_ci return NULL; 598d9f0492fSopenharmony_ci } 599d9f0492fSopenharmony_ci return node; 600d9f0492fSopenharmony_ci} 601d9f0492fSopenharmony_ci 602d9f0492fSopenharmony_ciCachedHandle CachedParameterCreate(const char *name, const char *defValue) 603d9f0492fSopenharmony_ci{ 604d9f0492fSopenharmony_ci if (name == NULL || defValue == NULL) { 605d9f0492fSopenharmony_ci return NULL; 606d9f0492fSopenharmony_ci } 607d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return NULL, "Invalid param workspace"); 608d9f0492fSopenharmony_ci uint32_t nameLen = strlen(name); 609d9f0492fSopenharmony_ci PARAM_CHECK(nameLen < PARAM_NAME_LEN_MAX, return NULL, "Invalid name %s", name); 610d9f0492fSopenharmony_ci uint32_t valueLen = strlen(defValue); 611d9f0492fSopenharmony_ci if (IS_READY_ONLY(name)) { 612d9f0492fSopenharmony_ci PARAM_CHECK(valueLen < PARAM_CONST_VALUE_LEN_MAX, return NULL, "Illegal param value %s", defValue); 613d9f0492fSopenharmony_ci } else { 614d9f0492fSopenharmony_ci PARAM_CHECK(valueLen < PARAM_VALUE_LEN_MAX, return NULL, "Illegal param value %s length", defValue); 615d9f0492fSopenharmony_ci } 616d9f0492fSopenharmony_ci 617d9f0492fSopenharmony_ci ParamTrieNode *node = NULL; 618d9f0492fSopenharmony_ci WorkSpace *workspace = NULL; 619d9f0492fSopenharmony_ci int ret = ReadParamWithCheck(&workspace, name, DAC_READ, &node); 620d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return NULL, "Forbid to access parameter %s", name); 621d9f0492fSopenharmony_ci PARAM_CHECK(workspace != NULL && workspace->area != NULL, return NULL, "Forbid to access parameter %s", name); 622d9f0492fSopenharmony_ci 623d9f0492fSopenharmony_ci CachedParameter *param = (CachedParameter *)malloc( 624d9f0492fSopenharmony_ci sizeof(CachedParameter) + PARAM_ALIGN(nameLen) + 1 + PARAM_VALUE_LEN_MAX); 625d9f0492fSopenharmony_ci PARAM_CHECK(param != NULL, return NULL, "Failed to create CachedParameter for %s", name); 626d9f0492fSopenharmony_ci ret = PARAM_STRCPY(param->data, nameLen + 1, name); 627d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, free(param); 628d9f0492fSopenharmony_ci return NULL, "Failed to copy name %s", name); 629d9f0492fSopenharmony_ci param->cachedParameterCheck = CachedParameterCheck; 630d9f0492fSopenharmony_ci param->workspace = workspace; 631d9f0492fSopenharmony_ci param->nameLen = nameLen; 632d9f0492fSopenharmony_ci param->paramValue = ¶m->data[PARAM_ALIGN(nameLen) + 1]; 633d9f0492fSopenharmony_ci param->bufferLen = PARAM_VALUE_LEN_MAX; 634d9f0492fSopenharmony_ci param->dataCommitId = (uint32_t)-1; 635d9f0492fSopenharmony_ci if (node != NULL && node->dataIndex != 0) { 636d9f0492fSopenharmony_ci param->dataIndex = node->dataIndex; 637d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(workspace, node->dataIndex); 638d9f0492fSopenharmony_ci PARAM_CHECK(entry != NULL, free(param); 639d9f0492fSopenharmony_ci return NULL, "Failed to get trie node %s", name); 640d9f0492fSopenharmony_ci uint32_t length = param->bufferLen; 641d9f0492fSopenharmony_ci param->dataCommitId = ReadCommitId(entry); 642d9f0492fSopenharmony_ci ret = ReadParamValue_(entry, ¶m->dataCommitId, param->paramValue, &length); 643d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, free(param); 644d9f0492fSopenharmony_ci return NULL, "Failed to read parameter value %s", name); 645d9f0492fSopenharmony_ci } else { 646d9f0492fSopenharmony_ci param->dataIndex = 0; 647d9f0492fSopenharmony_ci ret = PARAM_STRCPY(param->paramValue, param->bufferLen, defValue); 648d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, free(param); 649d9f0492fSopenharmony_ci return NULL, "Failed to copy name %s", name); 650d9f0492fSopenharmony_ci } 651d9f0492fSopenharmony_ci param->spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(&workspace->area->commitId, MEMORY_ORDER_ACQUIRE); 652d9f0492fSopenharmony_ci PARAM_LOGV("CachedParameterCreate %u %u %lld \n", param->dataIndex, param->dataCommitId, param->spaceCommitId); 653d9f0492fSopenharmony_ci return (CachedHandle)param; 654d9f0492fSopenharmony_ci} 655d9f0492fSopenharmony_ci 656d9f0492fSopenharmony_ciSTATIC_INLINE const char *CachedParameterCheck(CachedParameter *param, int *changed) 657d9f0492fSopenharmony_ci{ 658d9f0492fSopenharmony_ci *changed = 0; 659d9f0492fSopenharmony_ci if (param->dataIndex == 0) { 660d9f0492fSopenharmony_ci ParamTrieNode *node = BaseFindTrieNode(param->workspace, param->data, param->nameLen, NULL); 661d9f0492fSopenharmony_ci if (node != NULL) { 662d9f0492fSopenharmony_ci param->dataIndex = node->dataIndex; 663d9f0492fSopenharmony_ci } else { 664d9f0492fSopenharmony_ci return param->paramValue; 665d9f0492fSopenharmony_ci } 666d9f0492fSopenharmony_ci } 667d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(param->workspace, param->dataIndex); 668d9f0492fSopenharmony_ci PARAM_CHECK(entry != NULL, return param->paramValue, "Failed to get trie node %s", param->data); 669d9f0492fSopenharmony_ci uint32_t dataCommitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE); 670d9f0492fSopenharmony_ci dataCommitId &= PARAM_FLAGS_COMMITID; 671d9f0492fSopenharmony_ci if (param->dataCommitId == dataCommitId) { 672d9f0492fSopenharmony_ci return param->paramValue; 673d9f0492fSopenharmony_ci } 674d9f0492fSopenharmony_ci uint32_t length = param->bufferLen; 675d9f0492fSopenharmony_ci param->dataCommitId = dataCommitId; 676d9f0492fSopenharmony_ci int ret = ReadParamValue_(entry, ¶m->dataCommitId, param->paramValue, &length); 677d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return NULL, "Failed to copy value %s", param->data); 678d9f0492fSopenharmony_ci PARAM_LOGV("CachedParameterCheck %u", param->dataCommitId); 679d9f0492fSopenharmony_ci *changed = 1; 680d9f0492fSopenharmony_ci return param->paramValue; 681d9f0492fSopenharmony_ci} 682d9f0492fSopenharmony_ci 683d9f0492fSopenharmony_civoid CachedParameterDestroy(CachedHandle handle) 684d9f0492fSopenharmony_ci{ 685d9f0492fSopenharmony_ci if (handle != NULL) { 686d9f0492fSopenharmony_ci free(handle); 687d9f0492fSopenharmony_ci } 688d9f0492fSopenharmony_ci} 689