• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "param_manager.h"
17 
18 #include <ctype.h>
19 #include <limits.h>
20 
21 #include "init_cmds.h"
22 #include "init_hook.h"
23 #include "param_trie.h"
24 #include "param_utils.h"
25 #include "securec.h"
26 static DUMP_PRINTF g_printf = printf;
27 
SystemCheckMatchParamWait(const char * name,const char * value)28 ParamNode *SystemCheckMatchParamWait(const char *name, const char *value)
29 {
30     ParamWorkSpace *paramSpace = GetParamWorkSpace();
31     PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace");
32     PARAM_WORKSPACE_CHECK(paramSpace, return NULL, "Invalid space");
33 
34     WorkSpace *workspace = GetWorkSpace(name);
35     PARAM_CHECK(workspace != NULL, return NULL, "Failed to get workspace %s", name);
36     PARAM_LOGV("SystemCheckMatchParamWait name %s", name);
37     uint32_t nameLength = strlen(name);
38     ParamTrieNode *node = FindTrieNode(workspace, name, nameLength, NULL);
39     if (node == NULL || node->dataIndex == 0) {
40         return NULL;
41     }
42     ParamNode *param = (ParamNode *)GetTrieNode(workspace, node->dataIndex);
43     if (param == NULL) {
44         return NULL;
45     }
46     if ((param->keyLength != nameLength) || (strncmp(param->data, name, nameLength) != 0)) {  // compare name
47         return NULL;
48     }
49     ATOMIC_STORE_EXPLICIT(&param->commitId,
50         ATOMIC_LOAD_EXPLICIT(&param->commitId, memory_order_relaxed) | PARAM_FLAGS_WAITED, memory_order_release);
51     if ((strncmp(value, "*", 1) == 0) || (strcmp(param->data + nameLength + 1, value) == 0)) { // compare value
52         return param;
53     }
54     char *tmp = strstr(value, "*");
55     if (tmp != NULL && (strncmp(param->data + nameLength + 1, value, tmp - value) == 0)) {
56         return param;
57     }
58     return NULL;
59 }
60 
ProcessParamTraversal(const WorkSpace * workSpace,const ParamTrieNode * node,const void * cookie)61 static int ProcessParamTraversal(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie)
62 {
63     ParamTraversalContext *context = (ParamTraversalContext *)cookie;
64     ParamTrieNode *current = (ParamTrieNode *)node;
65     if (current == NULL) {
66         return 0;
67     }
68     if (current->dataIndex == 0) {
69         return 0;
70     }
71     ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex);
72     if (entry == NULL) {
73         return 0;
74     }
75     if ((strcmp("#", context->prefix) != 0) && (strncmp(entry->data, context->prefix, strlen(context->prefix)) != 0)) {
76         return 0;
77     }
78     uint32_t index = GetParamHandle(workSpace, current->dataIndex, entry->data);
79     context->traversalParamPtr(index, context->context);
80     return 0;
81 }
82 
SystemTraversalParameter(const char * prefix,TraversalParamPtr traversalParameter,void * cookie)83 int SystemTraversalParameter(const char *prefix, TraversalParamPtr traversalParameter, void *cookie)
84 {
85     ParamWorkSpace *paramSpace = GetParamWorkSpace();
86     PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
87     PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
88     PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null");
89 
90 #ifdef PARAM_SUPPORT_SELINUX // load security label
91     ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX);
92     if (ops != NULL && ops->securityGetLabel != NULL) {
93         ops->securityGetLabel(NULL);
94     }
95 #endif
96     ParamTraversalContext context = {traversalParameter, cookie, "#"};
97     if (!(prefix == NULL || strlen(prefix) == 0)) {
98         ParamHandle handle = 0;
99         // only check for valid parameter
100         int ret = ReadParamWithCheck(prefix, DAC_READ, &handle);
101         if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
102             PARAM_CHECK(ret == 0, return ret, "Forbid to traversal parameters");
103         }
104         context.prefix = (char *)prefix;
105     }
106 
107     WorkSpace *workSpace = GetFirstWorkSpace();
108     if (workSpace != NULL && strcmp(workSpace->fileName, WORKSPACE_NAME_DAC) == 0) {
109         workSpace = GetNextWorkSpace(workSpace);
110     }
111     while (workSpace != NULL) {
112         PARAM_LOGV("SystemTraversalParameter prefix %s in space %s", context.prefix, workSpace->fileName);
113         WorkSpace *next = GetNextWorkSpace(workSpace);
114         ParamTrieNode *root = NULL;
115         if (prefix != NULL && strlen(prefix) != 0) {
116             root = FindTrieNode(workSpace, prefix, strlen(prefix), NULL);
117         }
118         PARAMSPACE_AREA_RD_LOCK(workSpace);
119         TraversalTrieNode(workSpace, root, ProcessParamTraversal, (const void *)&context);
120         PARAMSPACE_AREA_RW_UNLOCK(workSpace);
121         workSpace = next;
122     }
123     return 0;
124 }
125 
DumpTrieDataNodeTraversal(const WorkSpace * workSpace,const ParamTrieNode * node,const void * cookie)126 static int DumpTrieDataNodeTraversal(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie)
127 {
128     int verbose = *(int *)cookie;
129     ParamTrieNode *current = (ParamTrieNode *)node;
130     if (current == NULL) {
131         return 0;
132     }
133     if (verbose) {
134         PARAM_DUMP("\tTrie node info [%u,%u,%u] data: %u label: %u key length:%u \n\t  key: %s \n",
135             current->left, current->right, current->child,
136             current->dataIndex, current->labelIndex, current->length, current->key);
137     }
138     if (current->dataIndex != 0) {
139         ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex);
140         if (entry != NULL) {
141             PARAM_DUMP("\tparameter length info [%u, %u] \n\t  param: %s \n",
142                 entry->keyLength, entry->valueLength, entry->data);
143         }
144     }
145     if (current->labelIndex != 0 && verbose) {
146         ParamSecurityNode *label = (ParamSecurityNode *)GetTrieNode(workSpace, current->labelIndex);
147         if (label != NULL) {
148             PARAM_DUMP("\tparameter label dac %u %u %o \n\t  label: %s \n",
149                 label->uid, label->gid, label->mode, (label->length > 0) ? label->data : "null");
150         }
151     }
152     return 0;
153 }
154 
HashNodeTraverseForDump(WorkSpace * workSpace,int verbose)155 static void HashNodeTraverseForDump(WorkSpace *workSpace, int verbose)
156 {
157     PARAM_DUMP("    map file: %s \n", workSpace->fileName);
158     if (workSpace->area != NULL) {
159         PARAM_DUMP("    total size: %u \n", workSpace->area->dataSize);
160         PARAM_DUMP("    first offset: %u \n", workSpace->area->firstNode);
161         PARAM_DUMP("    current offset: %u \n", workSpace->area->currOffset);
162         PARAM_DUMP("    total node: %u \n", workSpace->area->trieNodeCount);
163         PARAM_DUMP("    total param node: %u \n", workSpace->area->paramNodeCount);
164         PARAM_DUMP("    total security node: %u\n", workSpace->area->securityNodeCount);
165     }
166     PARAM_DUMP("    node info: \n");
167     PARAMSPACE_AREA_RD_LOCK(workSpace);
168     TraversalTrieNode(workSpace, NULL, DumpTrieDataNodeTraversal, (const void *)&verbose);
169     PARAMSPACE_AREA_RW_UNLOCK(workSpace);
170 }
171 
SystemDumpParameters(int verbose,int (* dump)(const char * fmt,...))172 void SystemDumpParameters(int verbose, int (*dump)(const char *fmt, ...))
173 {
174     if (dump != NULL) {
175         g_printf = dump;
176     } else {
177         g_printf = printf;
178     }
179     ParamWorkSpace *paramSpace = GetParamWorkSpace();
180     PARAM_CHECK(paramSpace != NULL, return, "Invalid paramSpace");
181     PARAM_WORKSPACE_CHECK(paramSpace, return, "Invalid space");
182     // check default dac
183     ParamHandle handle = 0;
184     int ret = ReadParamWithCheck("#", DAC_READ, &handle);
185     if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
186         PARAM_CHECK(ret == 0, return, "Forbid to dump parameters");
187     }
188 #ifdef PARAM_SUPPORT_SELINUX // load security label
189     ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX);
190     if (ops != NULL && ops->securityGetLabel != NULL) {
191         ops->securityGetLabel(NULL);
192     }
193 #endif
194     PARAM_DUMP("Dump all parameters begin ...\n");
195     if (verbose) {
196         PARAM_DUMP("Local sercurity information\n");
197         PARAM_DUMP("pid: %d uid: %u gid: %u \n",
198             paramSpace->securityLabel.cred.pid,
199             paramSpace->securityLabel.cred.uid,
200             paramSpace->securityLabel.cred.gid);
201     }
202     WorkSpace *workSpace = GetFirstWorkSpace();
203     while (workSpace != NULL) {
204         WorkSpace *next = GetNextWorkSpace(workSpace);
205         HashNodeTraverseForDump(workSpace, verbose);
206         workSpace = next;
207     }
208     PARAM_DUMP("Dump all parameters finish\n");
209 }
210 
SysCheckParamExist(const char * name)211 INIT_LOCAL_API int SysCheckParamExist(const char *name)
212 {
213     ParamWorkSpace *paramSpace = GetParamWorkSpace();
214     PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
215     PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
216     PARAM_CHECK(name != NULL, return -1, "The name or handle is null");
217 
218     WorkSpace *workSpace = GetFirstWorkSpace();
219     while (workSpace != NULL) {
220         PARAM_LOGV("SysCheckParamExist name %s in space %s", name, workSpace->fileName);
221         WorkSpace *next = GetNextWorkSpace(workSpace);
222         ParamTrieNode *node = FindTrieNode(workSpace, name, strlen(name), NULL);
223         if (node != NULL && node->dataIndex != 0) {
224             return 0;
225         } else if (node != NULL) {
226             return PARAM_CODE_NODE_EXIST;
227         }
228         workSpace = next;
229     }
230     return PARAM_CODE_NOT_FOUND;
231 }
232 
GetParamSecurityAuditData(const char * name,int type,ParamAuditData * auditData)233 INIT_INNER_API int GetParamSecurityAuditData(const char *name, int type, ParamAuditData *auditData)
234 {
235     UNUSED(type);
236     ParamWorkSpace *paramSpace = GetParamWorkSpace();
237     PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
238     PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
239     uint32_t labelIndex = 0;
240     // get from dac
241     WorkSpace *space = GetWorkSpace(WORKSPACE_NAME_DAC);
242     PARAM_CHECK(space != NULL, return -1, "Invalid workSpace");
243     FindTrieNode(space, name, strlen(name), &labelIndex);
244     ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, labelIndex);
245     PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %d", labelIndex);
246 
247     auditData->name = name;
248     auditData->dacData.uid = node->uid;
249     auditData->dacData.gid = node->gid;
250     auditData->dacData.mode = node->mode;
251 #ifdef PARAM_SUPPORT_SELINUX
252     const char *tmpName = (paramSpace->selinuxSpace.getParamLabel != NULL) ?
253         paramSpace->selinuxSpace.getParamLabel(name) : NULL;
254     if (tmpName != NULL) {
255         int ret = strcpy_s(auditData->label, sizeof(auditData->label), tmpName);
256         PARAM_CHECK(ret == 0, return 0, "Failed to copy label for %s", name);
257     }
258 #endif
259     return 0;
260 }
261 
CreateCtrlInfo(ServiceCtrlInfo ** ctrlInfo,const char * cmd,uint32_t offset,uint8_t ctrlParam,const char * format,...)262 static int CreateCtrlInfo(ServiceCtrlInfo **ctrlInfo, const char *cmd, uint32_t offset,
263     uint8_t ctrlParam, const char *format, ...)
264 {
265     *ctrlInfo = calloc(1, sizeof(ServiceCtrlInfo));
266     PARAM_CHECK(ctrlInfo != NULL, return -1, "Failed to alloc memory %s", cmd);
267     va_list vargs;
268     va_start(vargs, format);
269     int len = vsnprintf_s((*ctrlInfo)->realKey,
270         sizeof((*ctrlInfo)->realKey), sizeof((*ctrlInfo)->realKey) - 1, format, vargs);
271     va_end(vargs);
272     int ret = strcpy_s((*ctrlInfo)->cmdName, sizeof((*ctrlInfo)->cmdName), cmd);
273     (*ctrlInfo)->valueOffset = offset;
274     if (ret != 0 || len <= 0) {
275         free(*ctrlInfo);
276         return -1;
277     }
278     (*ctrlInfo)->ctrlParam = ctrlParam;
279     return 0;
280 }
281 
GetServiceCtrlInfoForPowerCtrl(const char * name,const char * value,ServiceCtrlInfo ** ctrlInfo)282 static int GetServiceCtrlInfoForPowerCtrl(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo)
283 {
284     size_t size = 0;
285     const ParamCmdInfo *powerCtrlArg = GetStartupPowerCtl(&size);
286     PARAM_CHECK(powerCtrlArg != NULL, return -1, "Invalid ctrlInfo for %s", name);
287     uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen("reboot") + 1;
288     if (strcmp(value, "reboot") == 0) {
289         return CreateCtrlInfo(ctrlInfo, "reboot", valueOffset, 1,
290             "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, "reboot", value);
291     }
292     for (size_t i = 0; i < size; i++) {
293         PARAM_LOGV("Get power ctrl %s name %s value %s", powerCtrlArg[i].name, name, value);
294         if (strncmp(value, powerCtrlArg[i].name, strlen(powerCtrlArg[i].name)) == 0) {
295             valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(powerCtrlArg[i].replace) + 1;
296             return CreateCtrlInfo(ctrlInfo, powerCtrlArg[i].cmd, valueOffset, 1,
297                 "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, powerCtrlArg[i].replace, value);
298         }
299     }
300     // not found reboot, so reboot by normal
301     valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen("reboot") + 1;
302     return CreateCtrlInfo(ctrlInfo, "reboot.other", valueOffset, 1, "%s%s.%s",
303         OHOS_SERVICE_CTRL_PREFIX, "reboot", value);
304 }
305 
GetServiceCtrlInfo(const char * name,const char * value,ServiceCtrlInfo ** ctrlInfo)306 INIT_LOCAL_API int GetServiceCtrlInfo(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo)
307 {
308     PARAM_CHECK(ctrlInfo != NULL, return -1, "Invalid ctrlInfo %s", name);
309     *ctrlInfo = NULL;
310     size_t size = 0;
311     if (strcmp("ohos.startup.powerctrl", name) == 0) {
312         return GetServiceCtrlInfoForPowerCtrl(name, value, ctrlInfo);
313     }
314     if (strncmp("ohos.ctl.", name, strlen("ohos.ctl.")) == 0) {
315         const ParamCmdInfo *ctrlParam = GetServiceStartCtrl(&size);
316         PARAM_CHECK(ctrlParam != NULL, return -1, "Invalid ctrlInfo for %s", name);
317         for (size_t i = 0; i < size; i++) {
318             if (strcmp(name, ctrlParam[i].name) == 0) {
319                 uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(ctrlParam[i].replace) + 1;
320                 return CreateCtrlInfo(ctrlInfo, ctrlParam[i].cmd, valueOffset, 1,
321                     "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, ctrlParam[i].replace, value);
322             }
323         }
324     }
325     if (strncmp("ohos.servicectrl.", name, strlen("ohos.servicectrl.")) == 0) {
326         const ParamCmdInfo *installParam = GetServiceCtl(&size);
327         PARAM_CHECK(installParam != NULL, return -1, "Invalid ctrlInfo for %s", name);
328         for (size_t i = 0; i < size; i++) {
329             if (strncmp(name, installParam[i].name, strlen(installParam[i].name)) == 0) {
330                 return CreateCtrlInfo(ctrlInfo, installParam[i].cmd, strlen(name) + 1, 1, "%s.%s", name, value);
331             }
332         }
333     }
334     const ParamCmdInfo *other = GetOtherSpecial(&size);
335     for (size_t i = 0; i < size; i++) {
336         if (strncmp(name, other[i].name, strlen(other[i].name)) == 0) {
337             return CreateCtrlInfo(ctrlInfo, other[i].cmd, strlen(other[i].name), 0, "%s.%s", name, value);
338         }
339     }
340     return 0;
341 }
342 
CheckParameterSet(const char * name,const char * value,const ParamSecurityLabel * srcLabel,int * ctrlService)343 INIT_LOCAL_API int CheckParameterSet(const char *name,
344     const char *value, const ParamSecurityLabel *srcLabel, int *ctrlService)
345 {
346     ParamWorkSpace *paramSpace = GetParamWorkSpace();
347     PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
348     PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
349     PARAM_LOGV("CheckParameterSet name %s value: %s", name, value);
350     PARAM_CHECK(srcLabel != NULL && ctrlService != NULL, return -1, "Invalid param ");
351     int ret = CheckParamName(name, 0);
352     PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name);
353     ret = CheckParamValue(NULL, name, value, GetParamValueType(name));
354     PARAM_CHECK(ret == 0, return ret, "Illegal param value %s", value);
355     *ctrlService = 0;
356 
357     ServiceCtrlInfo *serviceInfo = NULL;
358     GetServiceCtrlInfo(name, value, &serviceInfo);
359     ret = CheckParamPermission(srcLabel, (serviceInfo == NULL) ? name : serviceInfo->realKey, DAC_WRITE);
360     if (ret == 0) {
361         if (serviceInfo == NULL) {
362             return 0;
363         }
364         if (serviceInfo->ctrlParam != 0) {  // ctrl param
365             *ctrlService |= PARAM_CTRL_SERVICE;
366         }
367 #if !(defined __LITEOS_A__ || defined __LITEOS_M__)
368         // do hook cmd
369         PARAM_LOGV("Check parameter settings realKey %s cmd: '%s' value: %s",
370             serviceInfo->realKey, serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset);
371         DoCmdByName(serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset);
372 #endif
373     }
374     if (serviceInfo != NULL) {
375         free(serviceInfo);
376     }
377     return ret;
378 }
379 
SystemGetParameterName(ParamHandle handle,char * name,unsigned int len)380 int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len)
381 {
382     PARAM_CHECK(name != NULL && handle != 0, return -1, "The name is null");
383     return ReadParamName(handle, name, len);
384 }
385