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 16d9f0492fSopenharmony_ci#include "param_manager.h" 17d9f0492fSopenharmony_ci 18d9f0492fSopenharmony_ci#include <ctype.h> 19d9f0492fSopenharmony_ci#include <inttypes.h> 20d9f0492fSopenharmony_ci#include <limits.h> 21d9f0492fSopenharmony_ci 22d9f0492fSopenharmony_ci#include "init_cmds.h" 23d9f0492fSopenharmony_ci#include "init_hook.h" 24d9f0492fSopenharmony_ci#include "param_base.h" 25d9f0492fSopenharmony_ci#include "param_trie.h" 26d9f0492fSopenharmony_ci#include "param_utils.h" 27d9f0492fSopenharmony_ci#include "securec.h" 28d9f0492fSopenharmony_cistatic DUMP_PRINTF g_printf = printf; 29d9f0492fSopenharmony_ci 30d9f0492fSopenharmony_cistatic int ReadParamName(ParamHandle handle, char *name, uint32_t length); 31d9f0492fSopenharmony_ci 32d9f0492fSopenharmony_ciParamNode *SystemCheckMatchParamWait(const char *name, const char *value) 33d9f0492fSopenharmony_ci{ 34d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 35d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace"); 36d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return NULL, "Invalid space"); 37d9f0492fSopenharmony_ci 38d9f0492fSopenharmony_ci WorkSpace *workspace = GetWorkSpaceByName(name); 39d9f0492fSopenharmony_ci PARAM_CHECK(workspace != NULL, return NULL, "Failed to get workspace %s", name); 40d9f0492fSopenharmony_ci PARAM_LOGV("SystemCheckMatchParamWait name %s", name); 41d9f0492fSopenharmony_ci uint32_t nameLength = strlen(name); 42d9f0492fSopenharmony_ci ParamTrieNode *node = FindTrieNode(workspace, name, nameLength, NULL); 43d9f0492fSopenharmony_ci if (node == NULL || node->dataIndex == 0) { 44d9f0492fSopenharmony_ci return NULL; 45d9f0492fSopenharmony_ci } 46d9f0492fSopenharmony_ci ParamNode *param = (ParamNode *)GetTrieNode(workspace, node->dataIndex); 47d9f0492fSopenharmony_ci if (param == NULL) { 48d9f0492fSopenharmony_ci return NULL; 49d9f0492fSopenharmony_ci } 50d9f0492fSopenharmony_ci if ((param->keyLength != nameLength) || (strncmp(param->data, name, nameLength) != 0)) { // compare name 51d9f0492fSopenharmony_ci return NULL; 52d9f0492fSopenharmony_ci } 53d9f0492fSopenharmony_ci ATOMIC_SYNC_OR_AND_FETCH(¶m->commitId, PARAM_FLAGS_WAITED, MEMORY_ORDER_RELEASE); 54d9f0492fSopenharmony_ci if ((strncmp(value, "*", 1) == 0) || (strcmp(param->data + nameLength + 1, value) == 0)) { // compare value 55d9f0492fSopenharmony_ci return param; 56d9f0492fSopenharmony_ci } 57d9f0492fSopenharmony_ci char *tmp = strstr(value, "*"); 58d9f0492fSopenharmony_ci if (tmp != NULL && (strncmp(param->data + nameLength + 1, value, tmp - value) == 0)) { 59d9f0492fSopenharmony_ci return param; 60d9f0492fSopenharmony_ci } 61d9f0492fSopenharmony_ci return NULL; 62d9f0492fSopenharmony_ci} 63d9f0492fSopenharmony_ci 64d9f0492fSopenharmony_cistatic int ProcessParamTraversal(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie) 65d9f0492fSopenharmony_ci{ 66d9f0492fSopenharmony_ci ParamTraversalContext *context = (ParamTraversalContext *)cookie; 67d9f0492fSopenharmony_ci ParamTrieNode *current = (ParamTrieNode *)node; 68d9f0492fSopenharmony_ci if (current == NULL) { 69d9f0492fSopenharmony_ci return 0; 70d9f0492fSopenharmony_ci } 71d9f0492fSopenharmony_ci if (current->dataIndex == 0) { 72d9f0492fSopenharmony_ci return 0; 73d9f0492fSopenharmony_ci } 74d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex); 75d9f0492fSopenharmony_ci if (entry == NULL) { 76d9f0492fSopenharmony_ci return 0; 77d9f0492fSopenharmony_ci } 78d9f0492fSopenharmony_ci if ((strcmp("#", context->prefix) != 0) && (strncmp(entry->data, context->prefix, strlen(context->prefix)) != 0)) { 79d9f0492fSopenharmony_ci return 0; 80d9f0492fSopenharmony_ci } 81d9f0492fSopenharmony_ci uint32_t index = PARAM_HANDLE(workSpace, current->dataIndex); 82d9f0492fSopenharmony_ci context->traversalParamPtr(index, context->context); 83d9f0492fSopenharmony_ci return 0; 84d9f0492fSopenharmony_ci} 85d9f0492fSopenharmony_ci 86d9f0492fSopenharmony_ciint SystemTraversalParameter(const char *prefix, TraversalParamPtr traversalParameter, void *cookie) 87d9f0492fSopenharmony_ci{ 88d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 89d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace"); 90d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space"); 91d9f0492fSopenharmony_ci PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null"); 92d9f0492fSopenharmony_ci 93d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX // load security label 94d9f0492fSopenharmony_ci ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); 95d9f0492fSopenharmony_ci if (ops != NULL && ops->securityGetLabel != NULL) { 96d9f0492fSopenharmony_ci ops->securityGetLabel("open"); 97d9f0492fSopenharmony_ci } 98d9f0492fSopenharmony_ci#endif 99d9f0492fSopenharmony_ci ParamTraversalContext context = {traversalParameter, cookie, "#"}; 100d9f0492fSopenharmony_ci if (!(prefix == NULL || strlen(prefix) == 0)) { 101d9f0492fSopenharmony_ci int ret = CheckParamPermission(GetParamSecurityLabel(), prefix, DAC_READ); 102d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Forbid to traversal parameters %s", prefix); 103d9f0492fSopenharmony_ci context.prefix = (char *)prefix; 104d9f0492fSopenharmony_ci } 105d9f0492fSopenharmony_ci 106d9f0492fSopenharmony_ci WorkSpace *workSpace = GetNextWorkSpace(NULL); 107d9f0492fSopenharmony_ci if (workSpace != NULL && strcmp(workSpace->fileName, WORKSPACE_NAME_DAC) == 0) { 108d9f0492fSopenharmony_ci workSpace = GetNextWorkSpace(workSpace); 109d9f0492fSopenharmony_ci } 110d9f0492fSopenharmony_ci while (workSpace != NULL) { 111d9f0492fSopenharmony_ci WorkSpace *next = GetNextWorkSpace(workSpace); 112d9f0492fSopenharmony_ci ParamTrieNode *root = NULL; 113d9f0492fSopenharmony_ci if (prefix != NULL && strlen(prefix) != 0) { 114d9f0492fSopenharmony_ci root = FindTrieNode(workSpace, prefix, strlen(prefix), NULL); 115d9f0492fSopenharmony_ci } 116d9f0492fSopenharmony_ci PARAMSPACE_AREA_RD_LOCK(workSpace); 117d9f0492fSopenharmony_ci TraversalTrieNode(workSpace, root, ProcessParamTraversal, (const void *)&context); 118d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_UNLOCK(workSpace); 119d9f0492fSopenharmony_ci workSpace = next; 120d9f0492fSopenharmony_ci } 121d9f0492fSopenharmony_ci return 0; 122d9f0492fSopenharmony_ci} 123d9f0492fSopenharmony_ci 124d9f0492fSopenharmony_cistatic int DumpTrieDataNodeTraversal(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie) 125d9f0492fSopenharmony_ci{ 126d9f0492fSopenharmony_ci int verbose = *(int *)cookie; 127d9f0492fSopenharmony_ci ParamTrieNode *current = (ParamTrieNode *)node; 128d9f0492fSopenharmony_ci if (current == NULL) { 129d9f0492fSopenharmony_ci return 0; 130d9f0492fSopenharmony_ci } 131d9f0492fSopenharmony_ci if (verbose) { 132d9f0492fSopenharmony_ci PARAM_DUMP("\tTrie node info [%u,%u,%u] data: %u label: %u key length:%u \n\t key: %s \n", 133d9f0492fSopenharmony_ci current->left, current->right, current->child, 134d9f0492fSopenharmony_ci current->dataIndex, current->labelIndex, current->length, current->key); 135d9f0492fSopenharmony_ci } 136d9f0492fSopenharmony_ci if (current->dataIndex != 0) { 137d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex); 138d9f0492fSopenharmony_ci if (entry != NULL) { 139d9f0492fSopenharmony_ci PARAM_DUMP("\tparameter length info [%d] [%u, %u] \n\t param: %s \n", 140d9f0492fSopenharmony_ci entry->commitId, entry->keyLength, entry->valueLength, entry->data); 141d9f0492fSopenharmony_ci } 142d9f0492fSopenharmony_ci } 143d9f0492fSopenharmony_ci if (current->labelIndex == 0) { 144d9f0492fSopenharmony_ci return 0; 145d9f0492fSopenharmony_ci } 146d9f0492fSopenharmony_ci ParamSecurityNode *label = (ParamSecurityNode *)GetTrieNode(workSpace, current->labelIndex); 147d9f0492fSopenharmony_ci if (label == NULL) { 148d9f0492fSopenharmony_ci return 0; 149d9f0492fSopenharmony_ci } 150d9f0492fSopenharmony_ci PARAM_DUMP("\tparameter label dac %u %u 0%o \n", label->uid, label->gid, label->mode); 151d9f0492fSopenharmony_ci PARAM_DUMP("\tparameter label dac member [%u] ", label->memberNum); 152d9f0492fSopenharmony_ci for (uint32_t i = 0; i < label->memberNum; i++) { 153d9f0492fSopenharmony_ci PARAM_DUMP(" %u", label->members[i]); 154d9f0492fSopenharmony_ci } 155d9f0492fSopenharmony_ci if (label->memberNum > 0) { 156d9f0492fSopenharmony_ci PARAM_DUMP("\n"); 157d9f0492fSopenharmony_ci } 158d9f0492fSopenharmony_ci return 0; 159d9f0492fSopenharmony_ci} 160d9f0492fSopenharmony_ci 161d9f0492fSopenharmony_cistatic void HashNodeTraverseForDump(WorkSpace *workSpace, int verbose) 162d9f0492fSopenharmony_ci{ 163d9f0492fSopenharmony_ci PARAM_DUMP(" map file: %s \n", workSpace->fileName); 164d9f0492fSopenharmony_ci PARAM_DUMP(" space index : %d \n", workSpace->spaceIndex); 165d9f0492fSopenharmony_ci PARAM_DUMP(" space size : %d \n", workSpace->spaceSize); 166d9f0492fSopenharmony_ci if (workSpace->area != NULL) { 167d9f0492fSopenharmony_ci PARAM_DUMP(" total size: %u \n", workSpace->area->dataSize); 168d9f0492fSopenharmony_ci PARAM_DUMP(" first offset: %u \n", workSpace->area->firstNode); 169d9f0492fSopenharmony_ci PARAM_DUMP(" current offset: %u \n", workSpace->area->currOffset); 170d9f0492fSopenharmony_ci PARAM_DUMP(" total node: %u \n", workSpace->area->trieNodeCount); 171d9f0492fSopenharmony_ci PARAM_DUMP(" total param node: %u \n", workSpace->area->paramNodeCount); 172d9f0492fSopenharmony_ci PARAM_DUMP(" total security node: %u\n", workSpace->area->securityNodeCount); 173d9f0492fSopenharmony_ci if (verbose) { 174d9f0492fSopenharmony_ci PARAM_DUMP(" commitId : %" PRId64 "\n", workSpace->area->commitId); 175d9f0492fSopenharmony_ci PARAM_DUMP(" commitPersistId : %" PRId64 "\n", workSpace->area->commitPersistId); 176d9f0492fSopenharmony_ci } 177d9f0492fSopenharmony_ci } 178d9f0492fSopenharmony_ci PARAM_DUMP(" node info: \n"); 179d9f0492fSopenharmony_ci PARAMSPACE_AREA_RD_LOCK(workSpace); 180d9f0492fSopenharmony_ci TraversalTrieNode(workSpace, NULL, DumpTrieDataNodeTraversal, (const void *)&verbose); 181d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_UNLOCK(workSpace); 182d9f0492fSopenharmony_ci} 183d9f0492fSopenharmony_ci 184d9f0492fSopenharmony_civoid SystemDumpParameters(int verbose, int index, int (*dump)(const char *fmt, ...)) 185d9f0492fSopenharmony_ci{ 186d9f0492fSopenharmony_ci if (dump != NULL) { 187d9f0492fSopenharmony_ci g_printf = dump; 188d9f0492fSopenharmony_ci } else { 189d9f0492fSopenharmony_ci g_printf = printf; 190d9f0492fSopenharmony_ci } 191d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 192d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return, "Invalid paramSpace"); 193d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return, "Invalid space"); 194d9f0492fSopenharmony_ci // check default dac 195d9f0492fSopenharmony_ci int ret = CheckParamPermission(GetParamSecurityLabel(), "#", DAC_READ); 196d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return, "Forbid to dump parameters "); 197d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX // load security label 198d9f0492fSopenharmony_ci ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); 199d9f0492fSopenharmony_ci if (ops != NULL && ops->securityGetLabel != NULL) { 200d9f0492fSopenharmony_ci ops->securityGetLabel("open"); 201d9f0492fSopenharmony_ci } 202d9f0492fSopenharmony_ci#endif 203d9f0492fSopenharmony_ci PARAM_DUMP("Dump all parameters begin ...\n"); 204d9f0492fSopenharmony_ci if (verbose) { 205d9f0492fSopenharmony_ci PARAM_DUMP("Local security information\n"); 206d9f0492fSopenharmony_ci PARAM_DUMP("pid: %d uid: %u gid: %u \n", 207d9f0492fSopenharmony_ci paramSpace->securityLabel.cred.pid, 208d9f0492fSopenharmony_ci paramSpace->securityLabel.cred.uid, 209d9f0492fSopenharmony_ci paramSpace->securityLabel.cred.gid); 210d9f0492fSopenharmony_ci } 211d9f0492fSopenharmony_ci if (index > 0) { 212d9f0492fSopenharmony_ci WorkSpace *workSpace = GetWorkSpace(index); 213d9f0492fSopenharmony_ci if (workSpace != NULL) { 214d9f0492fSopenharmony_ci HashNodeTraverseForDump(workSpace, verbose); 215d9f0492fSopenharmony_ci } 216d9f0492fSopenharmony_ci return; 217d9f0492fSopenharmony_ci } 218d9f0492fSopenharmony_ci // show workspace size 219d9f0492fSopenharmony_ci WorkSpaceSize *spaceSize = GetWorkSpaceSize(GetWorkSpace(WORKSPACE_INDEX_SIZE)); 220d9f0492fSopenharmony_ci if (spaceSize != NULL) { 221d9f0492fSopenharmony_ci PARAM_DUMP("Max label index : %u\n", spaceSize->maxLabelIndex); 222d9f0492fSopenharmony_ci for (uint32_t i = 0; i < spaceSize->maxLabelIndex; i++) { 223d9f0492fSopenharmony_ci if (spaceSize->spaceSize[i] == PARAM_WORKSPACE_MIN) { 224d9f0492fSopenharmony_ci continue; 225d9f0492fSopenharmony_ci } 226d9f0492fSopenharmony_ci PARAM_DUMP("\t workspace %u size : %u\n", i, spaceSize->spaceSize[i]); 227d9f0492fSopenharmony_ci } 228d9f0492fSopenharmony_ci } 229d9f0492fSopenharmony_ci 230d9f0492fSopenharmony_ci WorkSpace *workSpace = GetNextWorkSpace(NULL); 231d9f0492fSopenharmony_ci while (workSpace != NULL) { 232d9f0492fSopenharmony_ci WorkSpace *next = GetNextWorkSpace(workSpace); 233d9f0492fSopenharmony_ci HashNodeTraverseForDump(workSpace, verbose); 234d9f0492fSopenharmony_ci workSpace = next; 235d9f0492fSopenharmony_ci } 236d9f0492fSopenharmony_ci PARAM_DUMP("Dump all parameters finish\n"); 237d9f0492fSopenharmony_ci} 238d9f0492fSopenharmony_ci 239d9f0492fSopenharmony_ciINIT_LOCAL_API int SysCheckParamExist(const char *name) 240d9f0492fSopenharmony_ci{ 241d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 242d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace"); 243d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space"); 244d9f0492fSopenharmony_ci PARAM_CHECK(name != NULL, return -1, "The name or handle is null"); 245d9f0492fSopenharmony_ci 246d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX // load security label 247d9f0492fSopenharmony_ci ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); 248d9f0492fSopenharmony_ci if (ops != NULL && ops->securityGetLabel != NULL) { 249d9f0492fSopenharmony_ci ops->securityGetLabel("open"); 250d9f0492fSopenharmony_ci } 251d9f0492fSopenharmony_ci#endif 252d9f0492fSopenharmony_ci WorkSpace *workSpace = GetNextWorkSpace(NULL); 253d9f0492fSopenharmony_ci while (workSpace != NULL) { 254d9f0492fSopenharmony_ci PARAM_LOGV("SysCheckParamExist name %s in space %s", name, workSpace->fileName); 255d9f0492fSopenharmony_ci WorkSpace *next = GetNextWorkSpace(workSpace); 256d9f0492fSopenharmony_ci ParamTrieNode *node = FindTrieNode(workSpace, name, strlen(name), NULL); 257d9f0492fSopenharmony_ci if (node != NULL && node->dataIndex != 0) { 258d9f0492fSopenharmony_ci return 0; 259d9f0492fSopenharmony_ci } else if (node != NULL) { 260d9f0492fSopenharmony_ci return PARAM_CODE_NODE_EXIST; 261d9f0492fSopenharmony_ci } 262d9f0492fSopenharmony_ci workSpace = next; 263d9f0492fSopenharmony_ci } 264d9f0492fSopenharmony_ci return PARAM_CODE_NOT_FOUND; 265d9f0492fSopenharmony_ci} 266d9f0492fSopenharmony_ci 267d9f0492fSopenharmony_ciINIT_INNER_API int GetParamSecurityAuditData(const char *name, int type, ParamAuditData *auditData) 268d9f0492fSopenharmony_ci{ 269d9f0492fSopenharmony_ci UNUSED(type); 270d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 271d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace"); 272d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space"); 273d9f0492fSopenharmony_ci uint32_t labelIndex = 0; 274d9f0492fSopenharmony_ci // get from dac 275d9f0492fSopenharmony_ci WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); 276d9f0492fSopenharmony_ci PARAM_CHECK(space != NULL, return -1, "Invalid workSpace"); 277d9f0492fSopenharmony_ci FindTrieNode(space, name, strlen(name), &labelIndex); 278d9f0492fSopenharmony_ci ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, labelIndex); 279d9f0492fSopenharmony_ci PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %d", labelIndex); 280d9f0492fSopenharmony_ci 281d9f0492fSopenharmony_ci auditData->name = name; 282d9f0492fSopenharmony_ci auditData->dacData.uid = node->uid; 283d9f0492fSopenharmony_ci auditData->dacData.gid = node->gid; 284d9f0492fSopenharmony_ci auditData->dacData.mode = node->mode; 285d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 286d9f0492fSopenharmony_ci const char *tmpName = (paramSpace->selinuxSpace.getParamLabel != NULL) ? 287d9f0492fSopenharmony_ci paramSpace->selinuxSpace.getParamLabel(name) : NULL; 288d9f0492fSopenharmony_ci if (tmpName != NULL) { 289d9f0492fSopenharmony_ci int ret = strcpy_s(auditData->label, sizeof(auditData->label), tmpName); 290d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return 0, "Failed to copy label for %s", name); 291d9f0492fSopenharmony_ci } 292d9f0492fSopenharmony_ci#endif 293d9f0492fSopenharmony_ci return 0; 294d9f0492fSopenharmony_ci} 295d9f0492fSopenharmony_ci 296d9f0492fSopenharmony_cistatic int CreateCtrlInfo(ServiceCtrlInfo **ctrlInfo, const char *cmd, uint32_t offset, 297d9f0492fSopenharmony_ci uint8_t ctrlParam, const char *format, ...) 298d9f0492fSopenharmony_ci{ 299d9f0492fSopenharmony_ci *ctrlInfo = calloc(1, sizeof(ServiceCtrlInfo)); 300d9f0492fSopenharmony_ci PARAM_CHECK(*ctrlInfo != NULL, return -1, "Failed to alloc memory %s", cmd); 301d9f0492fSopenharmony_ci va_list vargs; 302d9f0492fSopenharmony_ci va_start(vargs, format); 303d9f0492fSopenharmony_ci int len = vsnprintf_s((*ctrlInfo)->realKey, 304d9f0492fSopenharmony_ci sizeof((*ctrlInfo)->realKey), sizeof((*ctrlInfo)->realKey) - 1, format, vargs); 305d9f0492fSopenharmony_ci va_end(vargs); 306d9f0492fSopenharmony_ci int ret = strcpy_s((*ctrlInfo)->cmdName, sizeof((*ctrlInfo)->cmdName), cmd); 307d9f0492fSopenharmony_ci (*ctrlInfo)->valueOffset = offset; 308d9f0492fSopenharmony_ci if (ret != 0 || len <= 0) { 309d9f0492fSopenharmony_ci free(*ctrlInfo); 310d9f0492fSopenharmony_ci *ctrlInfo = NULL; 311d9f0492fSopenharmony_ci return -1; 312d9f0492fSopenharmony_ci } 313d9f0492fSopenharmony_ci (*ctrlInfo)->ctrlParam = ctrlParam; 314d9f0492fSopenharmony_ci return 0; 315d9f0492fSopenharmony_ci} 316d9f0492fSopenharmony_ci 317d9f0492fSopenharmony_cistatic int GetServiceCtrlInfoForPowerCtrl(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo) 318d9f0492fSopenharmony_ci{ 319d9f0492fSopenharmony_ci size_t size = 0; 320d9f0492fSopenharmony_ci const ParamCmdInfo *powerCtrlArg = GetStartupPowerCtl(&size); 321d9f0492fSopenharmony_ci PARAM_CHECK(powerCtrlArg != NULL, return -1, "Invalid ctrlInfo for %s", name); 322d9f0492fSopenharmony_ci uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen("reboot") + 1; 323d9f0492fSopenharmony_ci if (strcmp(value, "reboot") == 0) { 324d9f0492fSopenharmony_ci return CreateCtrlInfo(ctrlInfo, "reboot", valueOffset, 1, 325d9f0492fSopenharmony_ci "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, "reboot", value); 326d9f0492fSopenharmony_ci } 327d9f0492fSopenharmony_ci for (size_t i = 0; i < size; i++) { 328d9f0492fSopenharmony_ci PARAM_LOGV("Get power ctrl %s name %s value %s", powerCtrlArg[i].name, name, value); 329d9f0492fSopenharmony_ci if (strncmp(value, powerCtrlArg[i].name, strlen(powerCtrlArg[i].name)) == 0) { 330d9f0492fSopenharmony_ci valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(powerCtrlArg[i].replace) + 1; 331d9f0492fSopenharmony_ci return CreateCtrlInfo(ctrlInfo, powerCtrlArg[i].cmd, valueOffset, 1, 332d9f0492fSopenharmony_ci "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, powerCtrlArg[i].replace, value); 333d9f0492fSopenharmony_ci } 334d9f0492fSopenharmony_ci } 335d9f0492fSopenharmony_ci // not found reboot, so reboot by normal 336d9f0492fSopenharmony_ci valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen("reboot") + 1; 337d9f0492fSopenharmony_ci return CreateCtrlInfo(ctrlInfo, "reboot.other", valueOffset, 1, "%s%s.%s", 338d9f0492fSopenharmony_ci OHOS_SERVICE_CTRL_PREFIX, "reboot", value); 339d9f0492fSopenharmony_ci} 340d9f0492fSopenharmony_ci 341d9f0492fSopenharmony_ciINIT_LOCAL_API int GetServiceCtrlInfo(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo) 342d9f0492fSopenharmony_ci{ 343d9f0492fSopenharmony_ci PARAM_CHECK(ctrlInfo != NULL, return -1, "Invalid ctrlInfo %s", name); 344d9f0492fSopenharmony_ci *ctrlInfo = NULL; 345d9f0492fSopenharmony_ci size_t size = 0; 346d9f0492fSopenharmony_ci if (strcmp("ohos.startup.powerctrl", name) == 0) { 347d9f0492fSopenharmony_ci return GetServiceCtrlInfoForPowerCtrl(name, value, ctrlInfo); 348d9f0492fSopenharmony_ci } 349d9f0492fSopenharmony_ci if (strncmp("ohos.ctl.", name, strlen("ohos.ctl.")) == 0) { 350d9f0492fSopenharmony_ci const ParamCmdInfo *ctrlParam = GetServiceStartCtrl(&size); 351d9f0492fSopenharmony_ci PARAM_CHECK(ctrlParam != NULL, return -1, "Invalid ctrlInfo for %s", name); 352d9f0492fSopenharmony_ci for (size_t i = 0; i < size; i++) { 353d9f0492fSopenharmony_ci if (strcmp(name, ctrlParam[i].name) == 0) { 354d9f0492fSopenharmony_ci uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(ctrlParam[i].replace) + 1; 355d9f0492fSopenharmony_ci return CreateCtrlInfo(ctrlInfo, ctrlParam[i].cmd, valueOffset, 1, 356d9f0492fSopenharmony_ci "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, ctrlParam[i].replace, value); 357d9f0492fSopenharmony_ci } 358d9f0492fSopenharmony_ci } 359d9f0492fSopenharmony_ci } 360d9f0492fSopenharmony_ci if (strncmp("ohos.servicectrl.", name, strlen("ohos.servicectrl.")) == 0) { 361d9f0492fSopenharmony_ci const ParamCmdInfo *installParam = GetServiceCtl(&size); 362d9f0492fSopenharmony_ci PARAM_CHECK(installParam != NULL, return -1, "Invalid ctrlInfo for %s", name); 363d9f0492fSopenharmony_ci for (size_t i = 0; i < size; i++) { 364d9f0492fSopenharmony_ci if (strncmp(name, installParam[i].name, strlen(installParam[i].name)) == 0) { 365d9f0492fSopenharmony_ci return CreateCtrlInfo(ctrlInfo, installParam[i].cmd, strlen(name) + 1, 1, "%s.%s", name, value); 366d9f0492fSopenharmony_ci } 367d9f0492fSopenharmony_ci } 368d9f0492fSopenharmony_ci } 369d9f0492fSopenharmony_ci const ParamCmdInfo *other = GetOtherSpecial(&size); 370d9f0492fSopenharmony_ci for (size_t i = 0; i < size; i++) { 371d9f0492fSopenharmony_ci if (strncmp(name, other[i].name, strlen(other[i].name)) == 0) { 372d9f0492fSopenharmony_ci return CreateCtrlInfo(ctrlInfo, other[i].cmd, strlen(other[i].replace), 0, "%s.%s", name, value); 373d9f0492fSopenharmony_ci } 374d9f0492fSopenharmony_ci } 375d9f0492fSopenharmony_ci return 0; 376d9f0492fSopenharmony_ci} 377d9f0492fSopenharmony_ci 378d9f0492fSopenharmony_ciINIT_LOCAL_API int CheckParameterSet(const char *name, 379d9f0492fSopenharmony_ci const char *value, const ParamSecurityLabel *srcLabel, int *ctrlService) 380d9f0492fSopenharmony_ci{ 381d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 382d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return PARAM_WORKSPACE_NOT_INIT, "Invalid paramSpace"); 383d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return PARAM_WORKSPACE_NOT_INIT, "Invalid space"); 384d9f0492fSopenharmony_ci PARAM_LOGV("CheckParameterSet name %s value: %s", name, value); 385d9f0492fSopenharmony_ci PARAM_CHECK(srcLabel != NULL && ctrlService != NULL, return -1, "Invalid param "); 386d9f0492fSopenharmony_ci int ret = CheckParamName(name, 0); 387d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name); 388d9f0492fSopenharmony_ci ret = CheckParamValue(NULL, name, value, GetParamValueType(name)); 389d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Illegal param value %s", value); 390d9f0492fSopenharmony_ci *ctrlService = 0; 391d9f0492fSopenharmony_ci 392d9f0492fSopenharmony_ci ServiceCtrlInfo *serviceInfo = NULL; 393d9f0492fSopenharmony_ci GetServiceCtrlInfo(name, value, &serviceInfo); 394d9f0492fSopenharmony_ci ret = CheckParamPermission(srcLabel, (serviceInfo == NULL) ? name : serviceInfo->realKey, DAC_WRITE); 395d9f0492fSopenharmony_ci if (ret == 0) { 396d9f0492fSopenharmony_ci if (serviceInfo == NULL) { 397d9f0492fSopenharmony_ci return 0; 398d9f0492fSopenharmony_ci } 399d9f0492fSopenharmony_ci if (serviceInfo->ctrlParam != 0) { // ctrl param 400d9f0492fSopenharmony_ci *ctrlService |= PARAM_CTRL_SERVICE; 401d9f0492fSopenharmony_ci } 402d9f0492fSopenharmony_ci#if !(defined __LITEOS_A__ || defined __LITEOS_M__) 403d9f0492fSopenharmony_ci // do hook cmd 404d9f0492fSopenharmony_ci PARAM_LOGV("Check parameter settings realKey %s cmd: '%s' value: %s", 405d9f0492fSopenharmony_ci serviceInfo->realKey, serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset); 406d9f0492fSopenharmony_ci int cmdIndex = 0; 407d9f0492fSopenharmony_ci (void)GetMatchCmd(serviceInfo->cmdName, &cmdIndex); 408d9f0492fSopenharmony_ci DoCmdByIndex(cmdIndex, (char *)serviceInfo->realKey + serviceInfo->valueOffset, NULL); 409d9f0492fSopenharmony_ci#endif 410d9f0492fSopenharmony_ci } 411d9f0492fSopenharmony_ci if (serviceInfo != NULL) { 412d9f0492fSopenharmony_ci free(serviceInfo); 413d9f0492fSopenharmony_ci } 414d9f0492fSopenharmony_ci return ret; 415d9f0492fSopenharmony_ci} 416d9f0492fSopenharmony_ci 417d9f0492fSopenharmony_ciint SystemGetParameterName(ParamHandle handle, char *name, unsigned int len) 418d9f0492fSopenharmony_ci{ 419d9f0492fSopenharmony_ci PARAM_CHECK(name != NULL && handle != 0, return -1, "The name is null"); 420d9f0492fSopenharmony_ci return ReadParamName(handle, name, len); 421d9f0492fSopenharmony_ci} 422d9f0492fSopenharmony_ci 423d9f0492fSopenharmony_cistatic int AddParam(WorkSpace *workSpace, ParamInfos paramInfos, uint32_t *dataIndex) 424d9f0492fSopenharmony_ci{ 425d9f0492fSopenharmony_ci ParamTrieNode *node = AddTrieNode(workSpace, paramInfos.name, strlen(paramInfos.name)); 426d9f0492fSopenharmony_ci PARAM_CHECK(node != NULL, return PARAM_CODE_REACHED_MAX, 427d9f0492fSopenharmony_ci "Failed to add node name %s space %s", paramInfos.name, workSpace->fileName); 428d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, node->dataIndex); 429d9f0492fSopenharmony_ci if (entry == NULL) { 430d9f0492fSopenharmony_ci uint32_t offset = AddParamNode(workSpace, paramInfos.type, paramInfos.name, 431d9f0492fSopenharmony_ci strlen(paramInfos.name), paramInfos.value, strlen(paramInfos.value), paramInfos.mode); 432d9f0492fSopenharmony_ci PARAM_CHECK(offset > 0, return PARAM_CODE_REACHED_MAX, 433d9f0492fSopenharmony_ci "Failed to allocate name %s space %s", paramInfos.name, workSpace->fileName); 434d9f0492fSopenharmony_ci SaveIndex(&node->dataIndex, offset); 435d9f0492fSopenharmony_ci ATOMIC_SYNC_ADD_AND_FETCH(&workSpace->area->commitId, 1, MEMORY_ORDER_RELEASE); 436d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 437d9f0492fSopenharmony_ci WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); 438d9f0492fSopenharmony_ci if (space != NULL && space != workSpace) { // dac commit is global commit 439d9f0492fSopenharmony_ci ATOMIC_SYNC_ADD_AND_FETCH(&space->area->commitId, 1, MEMORY_ORDER_RELEASE); 440d9f0492fSopenharmony_ci } 441d9f0492fSopenharmony_ci#endif 442d9f0492fSopenharmony_ci } 443d9f0492fSopenharmony_ci if (dataIndex != NULL) { 444d9f0492fSopenharmony_ci *dataIndex = node->dataIndex; 445d9f0492fSopenharmony_ci } 446d9f0492fSopenharmony_ci PARAM_LOGV("AddParam name %s value: %s", paramInfos.name, paramInfos.value); 447d9f0492fSopenharmony_ci return 0; 448d9f0492fSopenharmony_ci} 449d9f0492fSopenharmony_ci 450d9f0492fSopenharmony_cistatic int UpdateParam(const WorkSpace *workSpace, uint32_t *dataIndex, const char *name, const char *value, int mode) 451d9f0492fSopenharmony_ci{ 452d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, *dataIndex); 453d9f0492fSopenharmony_ci PARAM_CHECK(entry != NULL, return PARAM_CODE_REACHED_MAX, "Failed to update param value %s %u", name, *dataIndex); 454d9f0492fSopenharmony_ci PARAM_CHECK(entry->keyLength == strlen(name), return PARAM_CODE_INVALID_NAME, "Failed to check name len %s", name); 455d9f0492fSopenharmony_ci 456d9f0492fSopenharmony_ci uint32_t valueLen = strlen(value); 457d9f0492fSopenharmony_ci uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_RELAXED); 458d9f0492fSopenharmony_ci ATOMIC_STORE_EXPLICIT(&entry->commitId, commitId | PARAM_FLAGS_MODIFY, MEMORY_ORDER_RELAXED); 459d9f0492fSopenharmony_ci if (entry->valueLength < PARAM_VALUE_LEN_MAX && valueLen < PARAM_VALUE_LEN_MAX) { 460d9f0492fSopenharmony_ci int ret = PARAM_MEMCPY(entry->data + entry->keyLength + 1, PARAM_VALUE_LEN_MAX, value, valueLen + 1); 461d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_VALUE, "Failed to copy value"); 462d9f0492fSopenharmony_ci entry->valueLength = valueLen; 463d9f0492fSopenharmony_ci } 464d9f0492fSopenharmony_ci 465d9f0492fSopenharmony_ci uint32_t flags = commitId & ~PARAM_FLAGS_COMMITID; 466d9f0492fSopenharmony_ci uint32_t commitIdCount = (++commitId) & PARAM_FLAGS_COMMITID; 467d9f0492fSopenharmony_ci ATOMIC_STORE_EXPLICIT(&entry->commitId, flags | commitIdCount, MEMORY_ORDER_RELEASE); 468d9f0492fSopenharmony_ci ATOMIC_SYNC_ADD_AND_FETCH(&workSpace->area->commitId, 1, MEMORY_ORDER_RELEASE); 469d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 470d9f0492fSopenharmony_ci WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); 471d9f0492fSopenharmony_ci if (space != NULL && space != workSpace) { // dac commit is global commit 472d9f0492fSopenharmony_ci ATOMIC_SYNC_ADD_AND_FETCH(&space->area->commitId, 1, MEMORY_ORDER_RELEASE); 473d9f0492fSopenharmony_ci } 474d9f0492fSopenharmony_ci#endif 475d9f0492fSopenharmony_ci PARAM_LOGV("UpdateParam name %s value: %s", name, value); 476d9f0492fSopenharmony_ci 477d9f0492fSopenharmony_ci if (((unsigned int)mode & LOAD_PARAM_PERSIST) != 0) { 478d9f0492fSopenharmony_ci entry->commitId |= PARAM_FLAGS_PERSIST; 479d9f0492fSopenharmony_ci } 480d9f0492fSopenharmony_ci futex_wake(&entry->commitId, INT_MAX); 481d9f0492fSopenharmony_ci return 0; 482d9f0492fSopenharmony_ci} 483d9f0492fSopenharmony_ci 484d9f0492fSopenharmony_ciINIT_LOCAL_API int WriteParam(const char *name, const char *value, uint32_t *dataIndex, int mode) 485d9f0492fSopenharmony_ci{ 486d9f0492fSopenharmony_ci int flag = 0; 487d9f0492fSopenharmony_ci PARAM_LOGV("WriteParam %s", name); 488d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 489d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return PARAM_WORKSPACE_NOT_INIT, "Invalid paramSpace"); 490d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return PARAM_WORKSPACE_NOT_INIT, "Invalid space"); 491d9f0492fSopenharmony_ci PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid name or value"); 492d9f0492fSopenharmony_ci WorkSpace *workSpace = GetWorkSpaceByName(name); 493d9f0492fSopenharmony_ci PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace"); 494d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 495d9f0492fSopenharmony_ci if (strcmp(workSpace->fileName, WORKSPACE_NAME_DEF_SELINUX) == 0) { 496d9f0492fSopenharmony_ci flag = 1; 497d9f0492fSopenharmony_ci } 498d9f0492fSopenharmony_ci#endif 499d9f0492fSopenharmony_ci ParamTrieNode *node = FindTrieNode(workSpace, name, strlen(name), NULL); 500d9f0492fSopenharmony_ci int ret = 0; 501d9f0492fSopenharmony_ci if (node != NULL && node->dataIndex != 0) { 502d9f0492fSopenharmony_ci if (dataIndex != NULL) { 503d9f0492fSopenharmony_ci *dataIndex = node->dataIndex; 504d9f0492fSopenharmony_ci } 505d9f0492fSopenharmony_ci if ((mode & LOAD_PARAM_ONLY_ADD) == LOAD_PARAM_ONLY_ADD) { 506d9f0492fSopenharmony_ci return PARAM_CODE_READ_ONLY; 507d9f0492fSopenharmony_ci } 508d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, node->dataIndex); 509d9f0492fSopenharmony_ci PARAM_CHECK(entry != NULL, return PARAM_CODE_REACHED_MAX, 510d9f0492fSopenharmony_ci "Failed to update param value %s %u", name, node->dataIndex); 511d9f0492fSopenharmony_ci // use save type to check value 512d9f0492fSopenharmony_ci ret = CheckParamValue(node, name, value, entry->type); 513d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Invalid param value param: %s=%s", name, value); 514d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_LOCK(workSpace); 515d9f0492fSopenharmony_ci ret = UpdateParam(workSpace, &node->dataIndex, name, value, mode); 516d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_UNLOCK(workSpace); 517d9f0492fSopenharmony_ci } else { 518d9f0492fSopenharmony_ci uint8_t type = GetParamValueType(name); 519d9f0492fSopenharmony_ci ret = CheckParamValue(node, name, value, type); 520d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Invalid param value param: %s=%s", name, value); 521d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_LOCK(workSpace); 522d9f0492fSopenharmony_ci ParamInfos paramInfos = {type, mode, name, value}; 523d9f0492fSopenharmony_ci ret = AddParam((WorkSpace *)workSpace, paramInfos, dataIndex); 524d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_UNLOCK(workSpace); 525d9f0492fSopenharmony_ci } 526d9f0492fSopenharmony_ci if ((ret == PARAM_CODE_REACHED_MAX) && (flag == 1)) { 527d9f0492fSopenharmony_ci PARAM_LOGE("Add node %s to space %s failed! memory is not enough, system reboot!", name, workSpace->fileName); 528d9f0492fSopenharmony_ci return PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH; 529d9f0492fSopenharmony_ci } 530d9f0492fSopenharmony_ci return ret; 531d9f0492fSopenharmony_ci} 532d9f0492fSopenharmony_ci 533d9f0492fSopenharmony_ciINIT_LOCAL_API WorkSpace *GetNextWorkSpace(WorkSpace *curr) 534d9f0492fSopenharmony_ci{ 535d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 536d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace"); 537d9f0492fSopenharmony_ci uint32_t i = (curr == NULL) ? 0 : (curr->spaceIndex + 1); 538d9f0492fSopenharmony_ci WorkSpace *workSpace = NULL; 539d9f0492fSopenharmony_ci for (; i < paramSpace->maxLabelIndex; ++i) { 540d9f0492fSopenharmony_ci workSpace = GetWorkSpace(i); 541d9f0492fSopenharmony_ci if (workSpace != NULL) { 542d9f0492fSopenharmony_ci return workSpace; 543d9f0492fSopenharmony_ci } 544d9f0492fSopenharmony_ci } 545d9f0492fSopenharmony_ci return NULL; 546d9f0492fSopenharmony_ci} 547d9f0492fSopenharmony_ci 548d9f0492fSopenharmony_ciINIT_LOCAL_API uint8_t GetParamValueType(const char *name) 549d9f0492fSopenharmony_ci{ 550d9f0492fSopenharmony_ci uint32_t labelIndex = 0; 551d9f0492fSopenharmony_ci WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); 552d9f0492fSopenharmony_ci if (space == NULL) { 553d9f0492fSopenharmony_ci return PARAM_TYPE_STRING; 554d9f0492fSopenharmony_ci } 555d9f0492fSopenharmony_ci (void)FindTrieNode(space, name, strlen(name), &labelIndex); 556d9f0492fSopenharmony_ci ParamSecurityNode *securityNode = (ParamSecurityNode *)GetTrieNode(space, labelIndex); 557d9f0492fSopenharmony_ci if (securityNode == NULL) { 558d9f0492fSopenharmony_ci return PARAM_TYPE_STRING; 559d9f0492fSopenharmony_ci } 560d9f0492fSopenharmony_ci return securityNode->type; 561d9f0492fSopenharmony_ci} 562d9f0492fSopenharmony_ci 563d9f0492fSopenharmony_cistatic int CheckParamValueType(const char *name, const char *value, uint8_t paramType) 564d9f0492fSopenharmony_ci{ 565d9f0492fSopenharmony_ci (void)name; 566d9f0492fSopenharmony_ci if (paramType == PARAM_TYPE_INT) { 567d9f0492fSopenharmony_ci long long int temp1 = 0; 568d9f0492fSopenharmony_ci if (strlen(value) > 1 && value[0] == '-' && StringToLL(value, &temp1) != 0) { 569d9f0492fSopenharmony_ci PARAM_LOGE("Illegal param value %s for int", value); 570d9f0492fSopenharmony_ci return PARAM_CODE_INVALID_VALUE; 571d9f0492fSopenharmony_ci } 572d9f0492fSopenharmony_ci unsigned long long int temp2 = 0; 573d9f0492fSopenharmony_ci if (StringToULL(value, &temp2) != 0) { 574d9f0492fSopenharmony_ci PARAM_LOGE("Illegal param value %s for int", value); 575d9f0492fSopenharmony_ci return PARAM_CODE_INVALID_VALUE; 576d9f0492fSopenharmony_ci } 577d9f0492fSopenharmony_ci } else if (paramType == PARAM_TYPE_BOOL) { 578d9f0492fSopenharmony_ci static const char *validValue[] = { 579d9f0492fSopenharmony_ci "1", "0", "true", "false", "y", "yes", "on", "off", "n", "no" 580d9f0492fSopenharmony_ci }; 581d9f0492fSopenharmony_ci size_t i = 0; 582d9f0492fSopenharmony_ci for (; i < ARRAY_LENGTH(validValue); i++) { 583d9f0492fSopenharmony_ci if (strcasecmp(validValue[i], value) == 0) { 584d9f0492fSopenharmony_ci break; 585d9f0492fSopenharmony_ci } 586d9f0492fSopenharmony_ci } 587d9f0492fSopenharmony_ci if (i >= ARRAY_LENGTH(validValue)) { 588d9f0492fSopenharmony_ci PARAM_LOGE("Illegal param value %s for bool", value); 589d9f0492fSopenharmony_ci return PARAM_CODE_INVALID_VALUE; 590d9f0492fSopenharmony_ci } 591d9f0492fSopenharmony_ci } 592d9f0492fSopenharmony_ci return 0; 593d9f0492fSopenharmony_ci} 594d9f0492fSopenharmony_ci 595d9f0492fSopenharmony_ciINIT_LOCAL_API int CheckParamValue(const ParamTrieNode *node, const char *name, const char *value, uint8_t paramType) 596d9f0492fSopenharmony_ci{ 597d9f0492fSopenharmony_ci if (IS_READY_ONLY(name)) { 598d9f0492fSopenharmony_ci PARAM_CHECK(strlen(value) < PARAM_CONST_VALUE_LEN_MAX, 599d9f0492fSopenharmony_ci return PARAM_CODE_INVALID_VALUE, "Illegal param value %s", value); 600d9f0492fSopenharmony_ci if (node != NULL && node->dataIndex != 0) { 601d9f0492fSopenharmony_ci PARAM_LOGE("Read-only param was already set %s", name); 602d9f0492fSopenharmony_ci return PARAM_CODE_READ_ONLY; 603d9f0492fSopenharmony_ci } 604d9f0492fSopenharmony_ci } else { 605d9f0492fSopenharmony_ci PARAM_CHECK(strlen(value) < GetParamMaxLen(paramType), 606d9f0492fSopenharmony_ci return PARAM_CODE_INVALID_VALUE, "Illegal param value %s length", value); 607d9f0492fSopenharmony_ci } 608d9f0492fSopenharmony_ci return CheckParamValueType(name, value, paramType); 609d9f0492fSopenharmony_ci} 610d9f0492fSopenharmony_ci 611d9f0492fSopenharmony_cistatic int ReadParamName(ParamHandle handle, char *name, uint32_t length) 612d9f0492fSopenharmony_ci{ 613d9f0492fSopenharmony_ci PARAM_CHECK(name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); 614d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 615d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Param workspace has not init."); 616d9f0492fSopenharmony_ci PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return PARAM_CODE_NOT_FOUND); 617d9f0492fSopenharmony_ci uint32_t labelIndex = 0; 618d9f0492fSopenharmony_ci uint32_t index = 0; 619d9f0492fSopenharmony_ci PARAM_GET_HANDLE_INFO(handle, labelIndex, index); 620d9f0492fSopenharmony_ci WorkSpace *workSpace = GetWorkSpace(labelIndex); 621d9f0492fSopenharmony_ci PARAM_CHECK(workSpace != NULL, return PARAM_CODE_NOT_FOUND, "Invalid workSpace for handle %x", handle); 622d9f0492fSopenharmony_ci ParamNode *entry = NULL; 623d9f0492fSopenharmony_ci if (PARAM_IS_ALIGNED(index)) { 624d9f0492fSopenharmony_ci entry = (ParamNode *)GetTrieNode(workSpace, index); 625d9f0492fSopenharmony_ci } 626d9f0492fSopenharmony_ci if (entry == NULL) { 627d9f0492fSopenharmony_ci return PARAM_CODE_NOT_FOUND; 628d9f0492fSopenharmony_ci } 629d9f0492fSopenharmony_ci PARAM_CHECK(length > entry->keyLength, return -1, "Invalid param size %u %u", entry->keyLength, length); 630d9f0492fSopenharmony_ci int ret = PARAM_MEMCPY(name, length, entry->data, entry->keyLength); 631d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_PARAM, "Failed to copy name"); 632d9f0492fSopenharmony_ci name[entry->keyLength] = '\0'; 633d9f0492fSopenharmony_ci return 0; 634d9f0492fSopenharmony_ci} 635d9f0492fSopenharmony_ci 636d9f0492fSopenharmony_ciINIT_LOCAL_API int CheckParamName(const char *name, int info) 637d9f0492fSopenharmony_ci{ 638d9f0492fSopenharmony_ci PARAM_CHECK(name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); 639d9f0492fSopenharmony_ci size_t nameLen = strlen(name); 640d9f0492fSopenharmony_ci if (nameLen >= PARAM_NAME_LEN_MAX) { 641d9f0492fSopenharmony_ci return PARAM_CODE_INVALID_NAME; 642d9f0492fSopenharmony_ci } 643d9f0492fSopenharmony_ci if (strcmp(name, "#") == 0) { 644d9f0492fSopenharmony_ci return 0; 645d9f0492fSopenharmony_ci } 646d9f0492fSopenharmony_ci 647d9f0492fSopenharmony_ci if (nameLen < 1 || name[0] == '.' || (!info && name[nameLen - 1] == '.')) { 648d9f0492fSopenharmony_ci PARAM_LOGE("CheckParamName %s %d", name, info); 649d9f0492fSopenharmony_ci return PARAM_CODE_INVALID_NAME; 650d9f0492fSopenharmony_ci } 651d9f0492fSopenharmony_ci 652d9f0492fSopenharmony_ci /* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */ 653d9f0492fSopenharmony_ci /* Don't allow ".." to appear in a param name */ 654d9f0492fSopenharmony_ci for (size_t i = 0; i < nameLen; i++) { 655d9f0492fSopenharmony_ci if (name[i] == '.') { 656d9f0492fSopenharmony_ci if (name[i - 1] == '.') { 657d9f0492fSopenharmony_ci return PARAM_CODE_INVALID_NAME; 658d9f0492fSopenharmony_ci } 659d9f0492fSopenharmony_ci continue; 660d9f0492fSopenharmony_ci } 661d9f0492fSopenharmony_ci if (name[i] == '_' || name[i] == '-' || name[i] == '@' || name[i] == ':') { 662d9f0492fSopenharmony_ci continue; 663d9f0492fSopenharmony_ci } 664d9f0492fSopenharmony_ci if (isalnum(name[i])) { 665d9f0492fSopenharmony_ci continue; 666d9f0492fSopenharmony_ci } 667d9f0492fSopenharmony_ci return PARAM_CODE_INVALID_NAME; 668d9f0492fSopenharmony_ci } 669d9f0492fSopenharmony_ci return 0; 670d9f0492fSopenharmony_ci} 671d9f0492fSopenharmony_ci 672d9f0492fSopenharmony_cistatic int CheckParamPermission_(WorkSpace **workspace, ParamTrieNode **node, 673d9f0492fSopenharmony_ci const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) 674d9f0492fSopenharmony_ci{ 675d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 676d9f0492fSopenharmony_ci PARAM_CHECK(srcLabel != NULL, return DAC_RESULT_FORBIDED, "The srcLabel is null"); 677d9f0492fSopenharmony_ci WorkSpace *dacSpace = GetWorkSpace(WORKSPACE_INDEX_DAC); 678d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace->checkParamPermission != NULL, return DAC_RESULT_FORBIDED, "Invalid check permission"); 679d9f0492fSopenharmony_ci ParamLabelIndex labelIndex = {0}; 680d9f0492fSopenharmony_ci // search node from dac space, and get selinux label index 681d9f0492fSopenharmony_ci *node = FindTrieNode(dacSpace, name, strlen(name), &labelIndex.dacLabelIndex); 682d9f0492fSopenharmony_ci labelIndex.workspace = GetWorkSpaceByName(name); 683d9f0492fSopenharmony_ci PARAM_CHECK(labelIndex.workspace != NULL, return DAC_RESULT_FORBIDED, "Invalid workSpace for %s", name); 684d9f0492fSopenharmony_ci labelIndex.selinuxLabelIndex = labelIndex.workspace->spaceIndex; 685d9f0492fSopenharmony_ci 686d9f0492fSopenharmony_ci int ret = paramSpace->checkParamPermission(&labelIndex, srcLabel, name, mode); 687d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, 688d9f0492fSopenharmony_ci "Forbid to access %s label %u %u", name, labelIndex.dacLabelIndex, labelIndex.selinuxLabelIndex); 689d9f0492fSopenharmony_ci *workspace = labelIndex.workspace; 690d9f0492fSopenharmony_ci return ret; 691d9f0492fSopenharmony_ci} 692d9f0492fSopenharmony_ci 693d9f0492fSopenharmony_ciINIT_LOCAL_API int CheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) 694d9f0492fSopenharmony_ci{ 695d9f0492fSopenharmony_ci ParamTrieNode *entry = NULL; 696d9f0492fSopenharmony_ci WorkSpace *workspace = NULL; 697d9f0492fSopenharmony_ci return CheckParamPermission_(&workspace, &entry, srcLabel, name, mode); 698d9f0492fSopenharmony_ci} 699d9f0492fSopenharmony_ci 700d9f0492fSopenharmony_ciSTATIC_INLINE ParamTrieNode *GetTrieNodeByHandle(ParamHandle handle) 701d9f0492fSopenharmony_ci{ 702d9f0492fSopenharmony_ci PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return NULL); 703d9f0492fSopenharmony_ci uint32_t labelIndex = 0; 704d9f0492fSopenharmony_ci uint32_t index = 0; 705d9f0492fSopenharmony_ci PARAM_GET_HANDLE_INFO(handle, labelIndex, index); 706d9f0492fSopenharmony_ci WorkSpace *workSpace = GetWorkSpace(labelIndex); 707d9f0492fSopenharmony_ci PARAM_CHECK(workSpace != NULL, return NULL, "Invalid workSpace for handle %x", handle); 708d9f0492fSopenharmony_ci if (PARAM_IS_ALIGNED(index)) { 709d9f0492fSopenharmony_ci return (ParamTrieNode *)GetTrieNode(workSpace, index); 710d9f0492fSopenharmony_ci } 711d9f0492fSopenharmony_ci return NULL; 712d9f0492fSopenharmony_ci} 713d9f0492fSopenharmony_ci 714d9f0492fSopenharmony_ciSTATIC_INLINE int ReadParamValue(ParamNode *entry, char *value, uint32_t *length) 715d9f0492fSopenharmony_ci{ 716d9f0492fSopenharmony_ci if (entry == NULL) { 717d9f0492fSopenharmony_ci return PARAM_CODE_NOT_FOUND; 718d9f0492fSopenharmony_ci } 719d9f0492fSopenharmony_ci if (value == NULL) { 720d9f0492fSopenharmony_ci *length = entry->valueLength + 1; 721d9f0492fSopenharmony_ci return 0; 722d9f0492fSopenharmony_ci } 723d9f0492fSopenharmony_ci PARAM_CHECK(*length > entry->valueLength, return PARAM_CODE_INVALID_VALUE, 724d9f0492fSopenharmony_ci "Invalid value len %u %u", *length, entry->valueLength); 725d9f0492fSopenharmony_ci uint32_t commitId = ReadCommitId(entry); 726d9f0492fSopenharmony_ci return ReadParamValue_(entry, &commitId, value, length); 727d9f0492fSopenharmony_ci} 728d9f0492fSopenharmony_ci 729d9f0492fSopenharmony_ciint SystemReadParam(const char *name, char *value, uint32_t *len) 730d9f0492fSopenharmony_ci{ 731d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return PARAM_WORKSPACE_NOT_INIT, 732d9f0492fSopenharmony_ci "SystemReadParam failed! name is:%s, errNum is:%d!", name, PARAM_WORKSPACE_NOT_INIT); 733d9f0492fSopenharmony_ci PARAM_CHECK(name != NULL && len != NULL, return PARAM_CODE_ERROR, 734d9f0492fSopenharmony_ci "SystemReadParam failed! name is:%s, errNum is:%d!", name, PARAM_CODE_ERROR); 735d9f0492fSopenharmony_ci ParamTrieNode *node = NULL; 736d9f0492fSopenharmony_ci WorkSpace *workspace = NULL; 737d9f0492fSopenharmony_ci int ret = CheckParamPermission_(&workspace, &node, GetParamSecurityLabel(), name, DAC_READ); 738d9f0492fSopenharmony_ci if (ret != 0) { 739d9f0492fSopenharmony_ci PARAM_LOGE("SystemReadParam failed! name is:%s, errNum is:%d!", name, ret); 740d9f0492fSopenharmony_ci return ret; 741d9f0492fSopenharmony_ci } 742d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 743d9f0492fSopenharmony_ci // search from real workspace 744d9f0492fSopenharmony_ci node = FindTrieNode(workspace, name, strlen(name), NULL); 745d9f0492fSopenharmony_ci#endif 746d9f0492fSopenharmony_ci if (node == NULL) { 747d9f0492fSopenharmony_ci return PARAM_CODE_NOT_FOUND; 748d9f0492fSopenharmony_ci } 749d9f0492fSopenharmony_ci ret = ReadParamValue((ParamNode *)GetTrieNode(workspace, node->dataIndex), value, len); 750d9f0492fSopenharmony_ci if (ret != 0) { 751d9f0492fSopenharmony_ci PARAM_LOGE("SystemReadParam failed! name is:%s, errNum is:%d!", name, ret); 752d9f0492fSopenharmony_ci } 753d9f0492fSopenharmony_ci return ret; 754d9f0492fSopenharmony_ci} 755d9f0492fSopenharmony_ci 756d9f0492fSopenharmony_ciint SystemFindParameter(const char *name, ParamHandle *handle) 757d9f0492fSopenharmony_ci{ 758d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return PARAM_WORKSPACE_NOT_INIT, "Param workspace has not init."); 759d9f0492fSopenharmony_ci PARAM_CHECK(name != NULL && handle != NULL, return -1, "The name or handle is null"); 760d9f0492fSopenharmony_ci *handle = -1; 761d9f0492fSopenharmony_ci ParamTrieNode *entry = NULL; 762d9f0492fSopenharmony_ci WorkSpace *workspace = NULL; 763d9f0492fSopenharmony_ci int ret = CheckParamPermission_(&workspace, &entry, GetParamSecurityLabel(), name, DAC_READ); 764d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Forbid to access parameter %s", name); 765d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_SELINUX 766d9f0492fSopenharmony_ci // search from real workspace 767d9f0492fSopenharmony_ci entry = FindTrieNode(workspace, name, strlen(name), NULL); 768d9f0492fSopenharmony_ci#endif 769d9f0492fSopenharmony_ci if (entry != NULL && entry->dataIndex != 0) { 770d9f0492fSopenharmony_ci *handle = PARAM_HANDLE(workspace, entry->dataIndex); 771d9f0492fSopenharmony_ci return 0; 772d9f0492fSopenharmony_ci } else if (entry != NULL) { 773d9f0492fSopenharmony_ci return PARAM_CODE_NODE_EXIST; 774d9f0492fSopenharmony_ci } 775d9f0492fSopenharmony_ci return PARAM_CODE_NOT_FOUND; 776d9f0492fSopenharmony_ci} 777d9f0492fSopenharmony_ci 778d9f0492fSopenharmony_ciint SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId) 779d9f0492fSopenharmony_ci{ 780d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init."); 781d9f0492fSopenharmony_ci PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return PARAM_CODE_NOT_FOUND); 782d9f0492fSopenharmony_ci PARAM_CHECK(handle != 0 && commitId != NULL, return -1, "The handle is null"); 783d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNodeByHandle(handle); 784d9f0492fSopenharmony_ci if (entry == NULL) { 785d9f0492fSopenharmony_ci return PARAM_CODE_NOT_FOUND; 786d9f0492fSopenharmony_ci } 787d9f0492fSopenharmony_ci *commitId = ReadCommitId(entry); 788d9f0492fSopenharmony_ci return 0; 789d9f0492fSopenharmony_ci} 790d9f0492fSopenharmony_ci 791d9f0492fSopenharmony_cilong long GetSystemCommitId(void) 792d9f0492fSopenharmony_ci{ 793d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init."); 794d9f0492fSopenharmony_ci WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); 795d9f0492fSopenharmony_ci if (space == NULL || space->area == NULL) { 796d9f0492fSopenharmony_ci return 0; 797d9f0492fSopenharmony_ci } 798d9f0492fSopenharmony_ci return ATOMIC_UINT64_LOAD_EXPLICIT(&space->area->commitId, MEMORY_ORDER_ACQUIRE); 799d9f0492fSopenharmony_ci} 800d9f0492fSopenharmony_ci 801d9f0492fSopenharmony_ciint SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len) 802d9f0492fSopenharmony_ci{ 803d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init."); 804d9f0492fSopenharmony_ci PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return PARAM_CODE_NOT_FOUND); 805d9f0492fSopenharmony_ci PARAM_CHECK(len != NULL && handle != 0, return -1, "The value is null"); 806d9f0492fSopenharmony_ci return ReadParamValue((ParamNode *)GetTrieNodeByHandle(handle), value, len); 807d9f0492fSopenharmony_ci} 808d9f0492fSopenharmony_ci 809d9f0492fSopenharmony_ciINIT_LOCAL_API int CheckIfUidInGroup(const gid_t groupId, const char *groupCheckName) 810d9f0492fSopenharmony_ci{ 811d9f0492fSopenharmony_ci PARAM_CHECK(groupCheckName != NULL, return -1, "Invalid groupCheckName"); 812d9f0492fSopenharmony_ci struct group *groupName = getgrnam(groupCheckName); 813d9f0492fSopenharmony_ci PARAM_CHECK(groupName != NULL, return -1, "Not find %s group", groupCheckName); 814d9f0492fSopenharmony_ci char **gr_mem = groupName->gr_mem; 815d9f0492fSopenharmony_ci PARAM_CHECK(gr_mem != NULL, return -1, "No member in %s", groupCheckName); 816d9f0492fSopenharmony_ci for (int i = 0; gr_mem[i] != NULL; ++i) { 817d9f0492fSopenharmony_ci struct group *userGroup = getgrnam(gr_mem[i]); 818d9f0492fSopenharmony_ci if (userGroup != NULL) { 819d9f0492fSopenharmony_ci if (groupId == userGroup->gr_gid) { 820d9f0492fSopenharmony_ci return 0; 821d9f0492fSopenharmony_ci } 822d9f0492fSopenharmony_ci } 823d9f0492fSopenharmony_ci } 824d9f0492fSopenharmony_ci PARAM_LOGE("Forbid to access, groupId %u not in %s", groupId, groupCheckName); 825d9f0492fSopenharmony_ci return PARAM_CODE_PERMISSION_DENIED; 826d9f0492fSopenharmony_ci} 827