mirror of
https://github.com/openharmony/kernel_linux_common_modules.git
synced 2026-08-27 01:31:36 -04:00
0afc82cd6f
--------------------------------------- DEC(Dynamic Enhance Control) is a dynamic file access enhancement mechanism. It resolves DAC interception and sharefs security risks, precisely controlling file access via a kernel permission database, ioctl interfaces and LSM framework. DEC will bind the token ID of the application and the paths it can access. The user-level sandboxmanager module and appspawn module will configure the relevant policies. When the application accesses the control paths under the sharefs file system, DEC checks the: create, read, write, remove, rename, move, access of files by the application. Signed-off-by: staralien <chengxin@servicecenter-harmonytsc.com>
119 lines
3.2 KiB
C
119 lines
3.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/rwsem.h>
|
|
#include <linux/slab.h>
|
|
|
|
#include "dec_constraint_tree.h"
|
|
#include "dec_common.h"
|
|
#include "dec_log.h"
|
|
#include "dec_utils.h"
|
|
|
|
static struct trie_node *constraint_tree = NULL;
|
|
static struct rw_semaphore *dec_constraint_rwsem = NULL;
|
|
|
|
static int __init dec_constraint_tree_init(void)
|
|
{
|
|
dec_constraint_rwsem = kmalloc(sizeof(struct rw_semaphore), GFP_KERNEL);
|
|
if (!dec_constraint_rwsem) {
|
|
dec_loge("Failed to allocate rwsem for constraint tree");
|
|
return -ENOMEM;
|
|
}
|
|
init_rwsem(dec_constraint_rwsem);
|
|
|
|
constraint_tree = trie_node_create("/");
|
|
if (!constraint_tree) {
|
|
kfree(dec_constraint_rwsem);
|
|
dec_constraint_rwsem = NULL;
|
|
dec_loge("Failed to create root node for constraint tree");
|
|
return -ENOMEM;
|
|
}
|
|
dec_logd("Constraint tree initialized successfully");
|
|
return 0;
|
|
}
|
|
|
|
bool dec_constraint_query(const char *path)
|
|
{
|
|
struct list_head comp_list;
|
|
struct trie_node *node = constraint_tree;
|
|
struct path_component *comp = NULL;
|
|
bool found = false;
|
|
|
|
INIT_LIST_HEAD(&comp_list);
|
|
|
|
if (split_path_to_component_list(path, &comp_list) < 0) {
|
|
free_component_list(&comp_list);
|
|
return found;
|
|
}
|
|
|
|
down_read(dec_constraint_rwsem);
|
|
/* Check root node first */
|
|
if (node->has_permissions) {
|
|
found = true;
|
|
goto cleanup;
|
|
}
|
|
/* Traverse path components to check child nodes */
|
|
list_for_each_entry(comp, &comp_list, list) {
|
|
node = find_child(node, comp->name);
|
|
if (node == NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (node->has_permissions) {
|
|
found = true;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
cleanup:
|
|
up_read(dec_constraint_rwsem);
|
|
free_component_list(&comp_list);
|
|
return found;
|
|
}
|
|
|
|
int dec_constraint_add(char *path)
|
|
{
|
|
if (is_path_valid(path) != 0) {
|
|
dec_loge("Invalid path for constraint add: %s", path);
|
|
return -EINVAL;
|
|
}
|
|
int ret = 0;
|
|
struct trie_node *node = constraint_tree;
|
|
struct list_head comp_list;
|
|
INIT_LIST_HEAD(&comp_list);
|
|
|
|
ret = split_path_to_component_list(path, &comp_list);
|
|
if (ret < 0) {
|
|
dec_loge("Failed to split path components for add: %s (err=%d)", path, ret);
|
|
free_component_list(&comp_list);
|
|
return ret;
|
|
}
|
|
|
|
down_write(dec_constraint_rwsem);
|
|
struct path_component *comp;
|
|
list_for_each_entry(comp, &comp_list, list) {
|
|
struct trie_node *child = find_child(node, comp->name);
|
|
if (child == NULL) {
|
|
child = insert_child(node, comp->name);
|
|
if (child == NULL) {
|
|
dec_loge("Failed to allocate child node for %s", comp->name);
|
|
ret = -ENOMEM;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
node = child;
|
|
}
|
|
|
|
node->has_permissions = true;
|
|
dec_logi("Constraint added for path: %s", path);
|
|
cleanup:
|
|
up_write(dec_constraint_rwsem);
|
|
free_component_list(&comp_list);
|
|
return ret;
|
|
}
|
|
|
|
/* Register initialization function for filesystem init phase */
|
|
fs_initcall(dec_constraint_tree_init); |