mirror of
https://gitee.com/openharmony/startup_init
synced 2024-12-19 08:57:34 +00:00
ea20e0d438
Merge pull request !1302 from cheng_jinsong/initsf0923
393 lines
16 KiB
C
393 lines
16 KiB
C
/*
|
|
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "param_manager.h"
|
|
|
|
#include <ctype.h>
|
|
#include <limits.h>
|
|
|
|
#include "init_cmds.h"
|
|
#include "init_hook.h"
|
|
#include "param_trie.h"
|
|
#include "param_utils.h"
|
|
#include "securec.h"
|
|
static DUMP_PRINTF g_printf = printf;
|
|
|
|
ParamNode *SystemCheckMatchParamWait(const char *name, const char *value)
|
|
{
|
|
ParamWorkSpace *paramSpace = GetParamWorkSpace();
|
|
PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace");
|
|
PARAM_WORKSPACE_CHECK(paramSpace, return NULL, "Invalid space");
|
|
|
|
WorkSpace *workspace = GetWorkSpace(name);
|
|
PARAM_CHECK(workspace != NULL, return NULL, "Failed to get workspace %s", name);
|
|
PARAM_LOGV("SystemCheckMatchParamWait name %s", name);
|
|
uint32_t nameLength = strlen(name);
|
|
ParamTrieNode *node = FindTrieNode(workspace, name, nameLength, NULL);
|
|
if (node == NULL || node->dataIndex == 0) {
|
|
return NULL;
|
|
}
|
|
ParamNode *param = (ParamNode *)GetTrieNode(workspace, node->dataIndex);
|
|
if (param == NULL) {
|
|
return NULL;
|
|
}
|
|
if ((param->keyLength != nameLength) || (strncmp(param->data, name, nameLength) != 0)) { // compare name
|
|
return NULL;
|
|
}
|
|
ATOMIC_STORE_EXPLICIT(¶m->commitId,
|
|
ATOMIC_LOAD_EXPLICIT(¶m->commitId, memory_order_relaxed) | PARAM_FLAGS_WAITED, memory_order_release);
|
|
if ((strncmp(value, "*", 1) == 0) || (strcmp(param->data + nameLength + 1, value) == 0)) { // compare value
|
|
return param;
|
|
}
|
|
char *tmp = strstr(value, "*");
|
|
if (tmp != NULL && (strncmp(param->data + nameLength + 1, value, tmp - value) == 0)) {
|
|
return param;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static int ProcessParamTraversal(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie)
|
|
{
|
|
ParamTraversalContext *context = (ParamTraversalContext *)cookie;
|
|
ParamTrieNode *current = (ParamTrieNode *)node;
|
|
if (current == NULL) {
|
|
return 0;
|
|
}
|
|
if (current->dataIndex == 0) {
|
|
return 0;
|
|
}
|
|
ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex);
|
|
if (entry == NULL) {
|
|
return 0;
|
|
}
|
|
if ((strcmp("#", context->prefix) != 0) && (strncmp(entry->data, context->prefix, strlen(context->prefix)) != 0)) {
|
|
return 0;
|
|
}
|
|
uint32_t index = GetParamHandle(workSpace, current->dataIndex, entry->data);
|
|
context->traversalParamPtr(index, context->context);
|
|
return 0;
|
|
}
|
|
|
|
int SystemTraversalParameter(const char *prefix, TraversalParamPtr traversalParameter, void *cookie)
|
|
{
|
|
ParamWorkSpace *paramSpace = GetParamWorkSpace();
|
|
PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
|
|
PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
|
|
PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null");
|
|
|
|
#ifdef PARAM_SUPPORT_SELINUX // load security label
|
|
ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX);
|
|
if (ops != NULL && ops->securityGetLabel != NULL) {
|
|
ops->securityGetLabel(NULL);
|
|
}
|
|
#endif
|
|
ParamTraversalContext context = {traversalParameter, cookie, "#"};
|
|
if (!(prefix == NULL || strlen(prefix) == 0)) {
|
|
ParamHandle handle = 0;
|
|
// only check for valid parameter
|
|
int ret = ReadParamWithCheck(prefix, DAC_READ, &handle);
|
|
if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
|
|
PARAM_CHECK(ret == 0, return ret, "Forbid to traversal parameters");
|
|
}
|
|
context.prefix = (char *)prefix;
|
|
}
|
|
|
|
WorkSpace *workSpace = GetFirstWorkSpace();
|
|
if (workSpace != NULL && strcmp(workSpace->fileName, WORKSPACE_NAME_DAC) == 0) {
|
|
workSpace = GetNextWorkSpace(workSpace);
|
|
}
|
|
while (workSpace != NULL) {
|
|
PARAM_LOGV("SystemTraversalParameter prefix %s in space %s", context.prefix, workSpace->fileName);
|
|
WorkSpace *next = GetNextWorkSpace(workSpace);
|
|
ParamTrieNode *root = NULL;
|
|
if (prefix != NULL && strlen(prefix) != 0) {
|
|
root = FindTrieNode(workSpace, prefix, strlen(prefix), NULL);
|
|
}
|
|
PARAMSPACE_AREA_RD_LOCK(workSpace);
|
|
TraversalTrieNode(workSpace, root, ProcessParamTraversal, (const void *)&context);
|
|
PARAMSPACE_AREA_RW_UNLOCK(workSpace);
|
|
workSpace = next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int DumpTrieDataNodeTraversal(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie)
|
|
{
|
|
int verbose = *(int *)cookie;
|
|
ParamTrieNode *current = (ParamTrieNode *)node;
|
|
if (current == NULL) {
|
|
return 0;
|
|
}
|
|
if (verbose) {
|
|
PARAM_DUMP("\tTrie node info [%u,%u,%u] data: %u label: %u key length:%u \n\t key: %s \n",
|
|
current->left, current->right, current->child,
|
|
current->dataIndex, current->labelIndex, current->length, current->key);
|
|
}
|
|
if (current->dataIndex != 0) {
|
|
ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex);
|
|
if (entry != NULL) {
|
|
PARAM_DUMP("\tparameter length info [%u, %u] \n\t param: %s \n",
|
|
entry->keyLength, entry->valueLength, entry->data);
|
|
}
|
|
}
|
|
if (current->labelIndex != 0 && verbose) {
|
|
ParamSecurityNode *label = (ParamSecurityNode *)GetTrieNode(workSpace, current->labelIndex);
|
|
if (label != NULL) {
|
|
PARAM_DUMP("\tparameter label dac %u %u %o \n\t label: %s \n",
|
|
label->uid, label->gid, label->mode, (label->length > 0) ? label->data : "null");
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void HashNodeTraverseForDump(WorkSpace *workSpace, int verbose)
|
|
{
|
|
PARAM_DUMP(" map file: %s \n", workSpace->fileName);
|
|
if (workSpace->area != NULL) {
|
|
PARAM_DUMP(" total size: %u \n", workSpace->area->dataSize);
|
|
PARAM_DUMP(" first offset: %u \n", workSpace->area->firstNode);
|
|
PARAM_DUMP(" current offset: %u \n", workSpace->area->currOffset);
|
|
PARAM_DUMP(" total node: %u \n", workSpace->area->trieNodeCount);
|
|
PARAM_DUMP(" total param node: %u \n", workSpace->area->paramNodeCount);
|
|
PARAM_DUMP(" total security node: %u\n", workSpace->area->securityNodeCount);
|
|
}
|
|
PARAM_DUMP(" node info: \n");
|
|
PARAMSPACE_AREA_RD_LOCK(workSpace);
|
|
TraversalTrieNode(workSpace, NULL, DumpTrieDataNodeTraversal, (const void *)&verbose);
|
|
PARAMSPACE_AREA_RW_UNLOCK(workSpace);
|
|
}
|
|
|
|
void SystemDumpParameters(int verbose, int (*dump)(const char *fmt, ...))
|
|
{
|
|
if (dump != NULL) {
|
|
g_printf = dump;
|
|
} else {
|
|
g_printf = printf;
|
|
}
|
|
ParamWorkSpace *paramSpace = GetParamWorkSpace();
|
|
PARAM_CHECK(paramSpace != NULL, return, "Invalid paramSpace");
|
|
PARAM_WORKSPACE_CHECK(paramSpace, return, "Invalid space");
|
|
// check default dac
|
|
ParamHandle handle = 0;
|
|
int ret = ReadParamWithCheck("#", DAC_READ, &handle);
|
|
if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
|
|
PARAM_CHECK(ret == 0, return, "Forbid to dump parameters");
|
|
}
|
|
#ifdef PARAM_SUPPORT_SELINUX // load security label
|
|
ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX);
|
|
if (ops != NULL && ops->securityGetLabel != NULL) {
|
|
ops->securityGetLabel(NULL);
|
|
}
|
|
#endif
|
|
PARAM_DUMP("Dump all parameters begin ...\n");
|
|
if (verbose) {
|
|
PARAM_DUMP("Local sercurity information\n");
|
|
PARAM_DUMP("pid: %d uid: %u gid: %u \n",
|
|
paramSpace->securityLabel.cred.pid,
|
|
paramSpace->securityLabel.cred.uid,
|
|
paramSpace->securityLabel.cred.gid);
|
|
}
|
|
WorkSpace *workSpace = GetFirstWorkSpace();
|
|
while (workSpace != NULL) {
|
|
WorkSpace *next = GetNextWorkSpace(workSpace);
|
|
HashNodeTraverseForDump(workSpace, verbose);
|
|
workSpace = next;
|
|
}
|
|
PARAM_DUMP("Dump all parameters finish\n");
|
|
}
|
|
|
|
INIT_LOCAL_API int SysCheckParamExist(const char *name)
|
|
{
|
|
ParamWorkSpace *paramSpace = GetParamWorkSpace();
|
|
PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
|
|
PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
|
|
PARAM_CHECK(name != NULL, return -1, "The name or handle is null");
|
|
|
|
WorkSpace *workSpace = GetFirstWorkSpace();
|
|
while (workSpace != NULL) {
|
|
PARAM_LOGV("SysCheckParamExist name %s in space %s", name, workSpace->fileName);
|
|
WorkSpace *next = GetNextWorkSpace(workSpace);
|
|
ParamTrieNode *node = FindTrieNode(workSpace, name, strlen(name), NULL);
|
|
if (node != NULL && node->dataIndex != 0) {
|
|
return 0;
|
|
} else if (node != NULL) {
|
|
return PARAM_CODE_NODE_EXIST;
|
|
}
|
|
workSpace = next;
|
|
}
|
|
return PARAM_CODE_NOT_FOUND;
|
|
}
|
|
|
|
INIT_INNER_API int GetParamSecurityAuditData(const char *name, int type, ParamAuditData *auditData)
|
|
{
|
|
UNUSED(type);
|
|
ParamWorkSpace *paramSpace = GetParamWorkSpace();
|
|
PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
|
|
PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
|
|
uint32_t labelIndex = 0;
|
|
// get from dac
|
|
WorkSpace *space = GetWorkSpace(WORKSPACE_NAME_DAC);
|
|
PARAM_CHECK(space != NULL, return -1, "Invalid workSpace");
|
|
FindTrieNode(space, name, strlen(name), &labelIndex);
|
|
ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, labelIndex);
|
|
PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %d", labelIndex);
|
|
|
|
auditData->name = name;
|
|
auditData->dacData.uid = node->uid;
|
|
auditData->dacData.gid = node->gid;
|
|
auditData->dacData.mode = node->mode;
|
|
#ifdef PARAM_SUPPORT_SELINUX
|
|
const char *tmpName = (paramSpace->selinuxSpace.getParamLabel != NULL) ?
|
|
paramSpace->selinuxSpace.getParamLabel(name) : NULL;
|
|
if (tmpName != NULL) {
|
|
int ret = strcpy_s(auditData->label, sizeof(auditData->label), tmpName);
|
|
PARAM_CHECK(ret == 0, return 0, "Failed to copy label for %s", name);
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int CreateCtrlInfo(ServiceCtrlInfo **ctrlInfo, const char *cmd, uint32_t offset,
|
|
uint8_t ctrlParam, const char *format, ...)
|
|
{
|
|
*ctrlInfo = calloc(1, sizeof(ServiceCtrlInfo));
|
|
PARAM_CHECK(ctrlInfo != NULL, return -1, "Failed to alloc memory %s", cmd);
|
|
va_list vargs;
|
|
va_start(vargs, format);
|
|
int len = vsnprintf_s((*ctrlInfo)->realKey,
|
|
sizeof((*ctrlInfo)->realKey), sizeof((*ctrlInfo)->realKey) - 1, format, vargs);
|
|
va_end(vargs);
|
|
int ret = strcpy_s((*ctrlInfo)->cmdName, sizeof((*ctrlInfo)->cmdName), cmd);
|
|
(*ctrlInfo)->valueOffset = offset;
|
|
if (ret != 0 || len <= 0) {
|
|
free(*ctrlInfo);
|
|
return -1;
|
|
}
|
|
(*ctrlInfo)->ctrlParam = ctrlParam;
|
|
return 0;
|
|
}
|
|
|
|
INIT_LOCAL_API int GetServiceCtrlInfo(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo)
|
|
{
|
|
PARAM_CHECK(ctrlInfo != NULL, return -1, "Invalid ctrlInfo %s", name);
|
|
*ctrlInfo = NULL;
|
|
size_t size = 0;
|
|
if (strcmp("ohos.startup.powerctrl", name) == 0) {
|
|
const ParamCmdInfo *powerCtrlArg = GetStartupPowerCtl(&size);
|
|
for (size_t i = 0; i < size; i++) {
|
|
if (strncmp(value, powerCtrlArg[i].name, strlen(powerCtrlArg[i].name)) == 0) {
|
|
uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(powerCtrlArg[i].replace) + 1;
|
|
return CreateCtrlInfo(ctrlInfo, powerCtrlArg[i].cmd, valueOffset, 1,
|
|
"%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, powerCtrlArg[i].replace, value);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
if (strncmp("ohos.ctl.", name, strlen("ohos.ctl.")) == 0) {
|
|
const ParamCmdInfo *ctrlParam = GetServiceStartCtrl(&size);
|
|
for (size_t i = 0; i < size; i++) {
|
|
if (strcmp(name, ctrlParam[i].name) == 0) {
|
|
uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(ctrlParam[i].replace) + 1;
|
|
return CreateCtrlInfo(ctrlInfo, ctrlParam[i].cmd, valueOffset, 1,
|
|
"%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, ctrlParam[i].replace, value);
|
|
}
|
|
}
|
|
}
|
|
if (strncmp("ohos.servicectrl.", name, strlen("ohos.servicectrl.")) == 0) {
|
|
const ParamCmdInfo *installParam = GetServiceCtl(&size);
|
|
for (size_t i = 0; i < size; i++) {
|
|
if (strncmp(name, installParam[i].name, strlen(installParam[i].name)) == 0) {
|
|
return CreateCtrlInfo(ctrlInfo, installParam[i].cmd, strlen(name) + 1, 1, "%s.%s", name, value);
|
|
}
|
|
}
|
|
}
|
|
const ParamCmdInfo *other = GetOtherSpecial(&size);
|
|
for (size_t i = 0; i < size; i++) {
|
|
if (strncmp(name, other[i].name, strlen(other[i].name)) == 0) {
|
|
return CreateCtrlInfo(ctrlInfo, other[i].cmd, strlen(other[i].name), 0, "%s.%s", name, value);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
INIT_LOCAL_API int CheckParameterSet(const char *name,
|
|
const char *value, const ParamSecurityLabel *srcLabel, int *ctrlService)
|
|
{
|
|
ParamWorkSpace *paramSpace = GetParamWorkSpace();
|
|
PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace");
|
|
PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space");
|
|
PARAM_LOGV("CheckParameterSet name %s value: %s", name, value);
|
|
PARAM_CHECK(srcLabel != NULL && ctrlService != NULL, return -1, "Invalid param ");
|
|
int ret = CheckParamName(name, 0);
|
|
PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name);
|
|
ret = CheckParamValue(NULL, name, value, GetParamValueType(name));
|
|
PARAM_CHECK(ret == 0, return ret, "Illegal param value %s", value);
|
|
*ctrlService = 0;
|
|
|
|
ServiceCtrlInfo *serviceInfo = NULL;
|
|
GetServiceCtrlInfo(name, value, &serviceInfo);
|
|
ret = CheckParamPermission(srcLabel, (serviceInfo == NULL) ? name : serviceInfo->realKey, DAC_WRITE);
|
|
if (ret == 0) {
|
|
if (serviceInfo == NULL) {
|
|
return 0;
|
|
}
|
|
if (serviceInfo->ctrlParam != 0) { // ctrl param
|
|
*ctrlService |= PARAM_CTRL_SERVICE;
|
|
}
|
|
#if !(defined __LITEOS_A__ || defined __LITEOS_M__)
|
|
// do hook cmd
|
|
PARAM_LOGV("Check parameter settings realKey %s cmd: '%s' value: %s",
|
|
serviceInfo->realKey, serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset);
|
|
DoCmdByName(serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset);
|
|
#endif
|
|
}
|
|
if (serviceInfo != NULL) {
|
|
free(serviceInfo);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId)
|
|
{
|
|
PARAM_CHECK(handle != 0 && commitId != NULL, return -1, "The handle is null");
|
|
|
|
ParamNode *entry = (ParamNode *)GetTrieNodeByHandle(handle);
|
|
if (entry == NULL) {
|
|
return -1;
|
|
}
|
|
*commitId = ReadCommitId(entry);
|
|
return 0;
|
|
}
|
|
|
|
long long GetSystemCommitId(void)
|
|
{
|
|
WorkSpace *space = GetWorkSpace(WORKSPACE_NAME_DAC);
|
|
if (space == NULL || space->area == NULL) {
|
|
return 0;
|
|
}
|
|
return ATOMIC_LOAD_EXPLICIT(&space->area->commitId, memory_order_acquire);
|
|
}
|
|
|
|
int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len)
|
|
{
|
|
PARAM_CHECK(name != NULL && handle != 0, return -1, "The name is null");
|
|
return ReadParamName(handle, name, len);
|
|
}
|
|
|
|
int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len)
|
|
{
|
|
PARAM_CHECK(len != NULL && handle != 0, return -1, "The value is null");
|
|
return ReadParamValue(handle, value, len);
|
|
} |