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(¶m->commitId,
50 ATOMIC_LOAD_EXPLICIT(¶m->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