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(&param->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