1281 lines
34 KiB
Diff
1281 lines
34 KiB
Diff
From 0e193ae62a67dd4141ec6089f515e651c7e6a515 Mon Sep 17 00:00:00 2001
|
|
From: Huaxin Lu <luhuaxin1@huawei.com>
|
|
Date: Sun, 11 Feb 2024 22:07:12 +0800
|
|
Subject: [PATCH 13/26] Refactor dim_core policy and support the action policy
|
|
|
|
1. Refactor the code for dim_core policy, separate policy text parsing
|
|
and policy management for expansion of other policy formats in future
|
|
2. Optimize the policy parsing, make it easier to extend the policy fields
|
|
3. Support to set "action=kill" in the policy line. If a process tamparing
|
|
is detected, kill the process (now only vaild for user process measurement)
|
|
---
|
|
src/Makefile | 7 +-
|
|
src/common/dim_utils.c | 44 ++-
|
|
src/common/dim_utils.h | 4 +-
|
|
src/core/dim_core_fs.c | 15 -
|
|
src/core/dim_core_main.c | 5 +
|
|
src/core/dim_core_measure.c | 17 -
|
|
src/core/dim_core_measure.h | 3 +-
|
|
src/core/dim_core_policy.c | 302 ------------------
|
|
src/core/dim_core_policy.h | 63 ----
|
|
src/core/dim_core_static_baseline.c | 4 +-
|
|
.../measure_task/dim_core_measure_module.c | 4 +-
|
|
src/core/measure_task/dim_core_measure_task.c | 8 +-
|
|
src/core/policy/dim_core_policy.c | 268 ++++++++++++++++
|
|
src/core/policy/dim_core_policy.h | 69 ++++
|
|
src/core/policy/dim_core_policy_complex.c | 190 +++++++++++
|
|
15 files changed, 583 insertions(+), 420 deletions(-)
|
|
delete mode 100644 src/core/dim_core_policy.c
|
|
delete mode 100644 src/core/dim_core_policy.h
|
|
create mode 100644 src/core/policy/dim_core_policy.c
|
|
create mode 100644 src/core/policy/dim_core_policy.h
|
|
create mode 100644 src/core/policy/dim_core_policy_complex.c
|
|
|
|
diff --git a/src/Makefile b/src/Makefile
|
|
index 1a3fac0..a17ce5b 100644
|
|
--- a/src/Makefile
|
|
+++ b/src/Makefile
|
|
@@ -6,7 +6,6 @@ obj-m += dim_monitor.o
|
|
dim_core-objs += core/dim_core_main.o
|
|
dim_core-objs += core/dim_core_fs.o
|
|
dim_core-objs += core/dim_core_mem_pool.o
|
|
-dim_core-objs += core/dim_core_policy.o
|
|
dim_core-objs += core/dim_core_static_baseline.o
|
|
dim_core-objs += core/dim_core_measure.o
|
|
dim_core-objs += core/dim_core_symbol.o
|
|
@@ -14,6 +13,8 @@ dim_core-objs += core/dim_core_sig.o
|
|
dim_core-objs += core/measure_task/dim_core_measure_kernel.o
|
|
dim_core-objs += core/measure_task/dim_core_measure_module.o
|
|
dim_core-objs += core/measure_task/dim_core_measure_task.o
|
|
+dim_core-objs += core/policy/dim_core_policy.o
|
|
+dim_core-objs += core/policy/dim_core_policy_complex.o
|
|
dim_core-objs += common/dim_entry.o
|
|
dim_core-objs += common/dim_utils.o
|
|
dim_core-objs += common/dim_baseline.o
|
|
@@ -46,9 +47,9 @@ dim_monitor-objs += measure/dim_measure_status.o
|
|
dim_monitor-objs += monitor/measure_task/dim_monitor_measure_data.o
|
|
dim_monitor-objs += monitor/measure_task/dim_monitor_measure_text.o
|
|
|
|
-# TODO
|
|
ccflags-y := -I$(src)/core
|
|
ccflags-y += -I$(src)/core/measure_task
|
|
+ccflags-y += -I$(src)/core/policy
|
|
ccflags-y += -I$(src)/monitor
|
|
ccflags-y += -I$(src)/monitor/measure_task
|
|
ccflags-y += -I$(src)/common
|
|
@@ -74,4 +75,4 @@ install:
|
|
insmod dim_monitor.ko
|
|
|
|
test:
|
|
- cd ../test && { sh test_dim_core.sh; sh test_dim_monitor.sh; }
|
|
\ No newline at end of file
|
|
+ cd ../test && { sh test_dim_core.sh; sh test_dim_monitor.sh; }
|
|
diff --git a/src/common/dim_utils.c b/src/common/dim_utils.c
|
|
index 75b58fc..4c99879 100644
|
|
--- a/src/common/dim_utils.c
|
|
+++ b/src/common/dim_utils.c
|
|
@@ -17,25 +17,47 @@ void *dim_kmalloc_gfp(size_t size)
|
|
|
|
void dim_kfree(void *data)
|
|
{
|
|
- kfree(data);
|
|
+ if (data != NULL)
|
|
+ kfree(data);
|
|
}
|
|
|
|
-const char *dim_absolute_path(const char *path, char *buf, int len)
|
|
+int dim_get_absolute_path(const char *path, const char **result)
|
|
{
|
|
- int ret;
|
|
+ int ret = 0;
|
|
struct path p;
|
|
+ char *buf = NULL;
|
|
char *apath = NULL;
|
|
|
|
- if (path == NULL || buf == NULL)
|
|
- return ERR_PTR(-EINVAL);
|
|
+ if (path == NULL)
|
|
+ return -EINVAL;
|
|
|
|
ret = kern_path(path, LOOKUP_FOLLOW, &p);
|
|
if (ret < 0)
|
|
- return ERR_PTR(ret);
|
|
+ return ret;
|
|
|
|
- apath = d_path(&p, buf, len);
|
|
+ buf = dim_kmalloc_gfp(PATH_MAX);
|
|
+ if (buf == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ apath = d_path(&p, buf, PATH_MAX);
|
|
+ if (IS_ERR(apath)) {
|
|
+ ret = PTR_ERR(apath);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ *result = kstrdup(apath, GFP_KERNEL);
|
|
+ if (*result == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+out:
|
|
path_put(&p);
|
|
- return apath;
|
|
+ if (buf != NULL)
|
|
+ dim_kfree(buf);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
bool dim_string_end_with(const char *str, const char *ext)
|
|
@@ -53,7 +75,7 @@ bool dim_string_end_with(const char *str, const char *ext)
|
|
return strcmp(str + name_len - ext_len, ext) == 0;
|
|
}
|
|
|
|
-int dim_parse_line_buf(char *buf, loff_t len, int (*line_parser)(char *, int))
|
|
+int dim_parse_line_buf(char *buf, loff_t len, int (*line_parser)(char *, int, void *), void *data)
|
|
{
|
|
int ret = 0;
|
|
int i = 0;
|
|
@@ -71,7 +93,7 @@ int dim_parse_line_buf(char *buf, loff_t len, int (*line_parser)(char *, int))
|
|
|
|
if (buf[i] == '\n') {
|
|
buf[i] = '\0';
|
|
- ret = line_parser(line, line_no);
|
|
+ ret = line_parser(line, line_no, data);
|
|
line = &buf[i + 1];
|
|
} else {
|
|
line_len = buf + i - line + 1;
|
|
@@ -80,7 +102,7 @@ int dim_parse_line_buf(char *buf, loff_t len, int (*line_parser)(char *, int))
|
|
return -ENOMEM;
|
|
|
|
memcpy(line_buf, line, line_len);
|
|
- ret = line_parser(line_buf, line_no);
|
|
+ ret = line_parser(line_buf, line_no, data);
|
|
}
|
|
|
|
if (ret < 0) {
|
|
diff --git a/src/common/dim_utils.h b/src/common/dim_utils.h
|
|
index 1db3ca1..5a9f132 100644
|
|
--- a/src/common/dim_utils.h
|
|
+++ b/src/common/dim_utils.h
|
|
@@ -19,8 +19,8 @@
|
|
|
|
void *dim_kmalloc_gfp(size_t size);
|
|
void dim_kfree(void *data);
|
|
-const char *dim_absolute_path(const char *path, char *buf, int len);
|
|
+int dim_get_absolute_path(const char *path, const char **result);
|
|
bool dim_string_end_with(const char *str, const char *ext);
|
|
-int dim_parse_line_buf(char *buf, loff_t len, int (*line_parser)(char *, int));
|
|
+int dim_parse_line_buf(char *buf, loff_t len, int (*line_parser)(char *, int, void *), void *data);
|
|
|
|
#endif
|
|
\ No newline at end of file
|
|
diff --git a/src/core/dim_core_fs.c b/src/core/dim_core_fs.c
|
|
index a76d622..4d6bdd4 100644
|
|
--- a/src/core/dim_core_fs.c
|
|
+++ b/src/core/dim_core_fs.c
|
|
@@ -53,18 +53,6 @@ dim_string_print_entry(dim_status, runtime_status, dim_core_status_print);
|
|
dim_uint_rw_entry(dim_interval, interval, dim_core_interval_get,
|
|
dim_core_interval_set);
|
|
|
|
-#ifdef DIM_CORE_TAMPERED_ACTION
|
|
-/*
|
|
- * tampered action set and read interface
|
|
- * dim_entry struct: dim_tampered_action_entry
|
|
- * file entry name: tampered_action
|
|
- * read function: dim_core_tampered_action_get
|
|
- * write function: dim_core_tampered_action_set
|
|
- */
|
|
-dim_uint_rw_entry(dim_tampered_action, tampered_action,
|
|
- dim_core_tampered_action_get, dim_core_tampered_action_set);
|
|
-#endif
|
|
-
|
|
/*
|
|
* dim directory
|
|
*/
|
|
@@ -81,9 +69,6 @@ static struct dim_entry *dim_core_files[] = {
|
|
&dim_measure_log_entry,
|
|
&dim_status_entry,
|
|
&dim_interval_entry,
|
|
-#ifdef DIM_CORE_TAMPERED_ACTION
|
|
- &dim_tampered_action_entry,
|
|
-#endif
|
|
};
|
|
|
|
void dim_core_destroy_fs(void)
|
|
diff --git a/src/core/dim_core_main.c b/src/core/dim_core_main.c
|
|
index 6a0ca41..ae34e81 100644
|
|
--- a/src/core/dim_core_main.c
|
|
+++ b/src/core/dim_core_main.c
|
|
@@ -4,6 +4,7 @@
|
|
|
|
#include <linux/module.h>
|
|
|
|
+#include "dim_core_policy.h"
|
|
#include "dim_core_symbol.h"
|
|
#include "dim_core_fs.h"
|
|
#include "dim_core_measure.h"
|
|
@@ -30,11 +31,15 @@ MODULE_PARM_DESC(measure_pcr, "TPM PCR index to extend measure log");
|
|
|
|
/* special measurement configuration for dim_core */
|
|
static unsigned int measure_interval = 0;
|
|
+bool dim_core_measure_action_enabled = 0;
|
|
static bool signature = false;
|
|
|
|
module_param(measure_interval, uint, 0);
|
|
MODULE_PARM_DESC(measure_interval, "Interval time (min) for automatic measurement");
|
|
|
|
+module_param_named(measure_action, dim_core_measure_action_enabled, bool, 0);
|
|
+MODULE_PARM_DESC(signature, "Enable actions when tampering detected");
|
|
+
|
|
module_param(signature, bool, 0);
|
|
MODULE_PARM_DESC(signature, "Require signature for policy and static baseline");
|
|
|
|
diff --git a/src/core/dim_core_measure.c b/src/core/dim_core_measure.c
|
|
index 0147735..3f1d6e4 100644
|
|
--- a/src/core/dim_core_measure.c
|
|
+++ b/src/core/dim_core_measure.c
|
|
@@ -30,7 +30,6 @@ static struct work_struct dim_baseline_work;
|
|
|
|
/* special measurement parameters for dim_core */
|
|
static atomic_t measure_interval = ATOMIC_INIT(0);
|
|
-static atomic_t tampered_action = ATOMIC_INIT(0);
|
|
|
|
/* interface to print measure status string */
|
|
const char *dim_core_status_print(void)
|
|
@@ -68,22 +67,6 @@ int dim_core_interval_set(unsigned int min)
|
|
return 0;
|
|
}
|
|
|
|
-/* interface to get tamper action flag */
|
|
-long dim_core_tampered_action_get(void)
|
|
-{
|
|
- return atomic_read(&tampered_action);
|
|
-}
|
|
-
|
|
-/* interface to set tamper action flag */
|
|
-int dim_core_tampered_action_set(unsigned int p)
|
|
-{
|
|
- if (p != 0 && p != 1)
|
|
- return -EINVAL;
|
|
-
|
|
- atomic_set(&tampered_action, p);
|
|
- return 0;
|
|
-}
|
|
-
|
|
static int baseline_prepare(struct dim_measure *m)
|
|
{
|
|
int ret = 0;
|
|
diff --git a/src/core/dim_core_measure.h b/src/core/dim_core_measure.h
|
|
index 699724a..3522ba0 100644
|
|
--- a/src/core/dim_core_measure.h
|
|
+++ b/src/core/dim_core_measure.h
|
|
@@ -16,6 +16,7 @@
|
|
#define DIM_MINUTE_TO_SEC (60UL)
|
|
#define DIM_MINUTE_TO_NSEC (60UL * 1000 * 1000 * 1000)
|
|
|
|
+extern bool dim_core_measure_action_enabled;
|
|
extern struct dim_measure dim_core_handle;
|
|
|
|
/* global init and destroy */
|
|
@@ -33,4 +34,4 @@ int dim_core_tampered_action_set(unsigned int p);
|
|
int dim_core_measure_blocking(void);
|
|
int dim_core_baseline_blocking(void);
|
|
|
|
-#endif
|
|
\ No newline at end of file
|
|
+#endif
|
|
diff --git a/src/core/dim_core_policy.c b/src/core/dim_core_policy.c
|
|
deleted file mode 100644
|
|
index 50ebcf7..0000000
|
|
--- a/src/core/dim_core_policy.c
|
|
+++ /dev/null
|
|
@@ -1,302 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#include <linux/fs.h>
|
|
-#include <linux/err.h>
|
|
-#include <linux/errno.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/uaccess.h>
|
|
-#include <linux/vmalloc.h>
|
|
-#include <linux/namei.h>
|
|
-#include <linux/utsname.h>
|
|
-
|
|
-#include "dim_utils.h"
|
|
-#include "dim_rb.h"
|
|
-
|
|
-#include "dim_core_sig.h"
|
|
-#include "dim_core_policy.h"
|
|
-
|
|
-static const char *dim_policy_obj_str[DIM_POLICY_OBJ_LAST] = {
|
|
- [DIM_POLICY_OBJ_BPRM_TEXT] = "obj=BPRM_TEXT",
|
|
- [DIM_POLICY_OBJ_MODULE_TEXT] = "obj=MODULE_TEXT",
|
|
- [DIM_POLICY_OBJ_KERNEL_TEXT] = "obj=KERNEL_TEXT",
|
|
-};
|
|
-
|
|
-static const char *dim_policy_key_str[DIM_POLICY_KEY_LAST] = {
|
|
- [DIM_POLICY_KEY_NAME] = "name=",
|
|
- [DIM_POLICY_KEY_PATH] = "path=",
|
|
-};
|
|
-
|
|
-static struct rb_root policy_root = RB_ROOT;
|
|
-
|
|
-static int dim_policy_compare(struct dim_policy *x,
|
|
- struct dim_policy *y)
|
|
-{
|
|
- if (x->obj != y->obj)
|
|
- return x->obj - y->obj;
|
|
-
|
|
- if (x->key != y->key)
|
|
- return x->key - y->key;
|
|
-
|
|
- return strcmp(x->val, y->val);
|
|
-}
|
|
-
|
|
-/*
|
|
-static int dim_policy_rb_find(struct rb_root *root,
|
|
- struct dim_policy *data,
|
|
- struct dim_policy **find_data)
|
|
-*/
|
|
-dim_rb_find(dim_policy);
|
|
-/*
|
|
-static int dim_policy_rb_add(struct rb_root *root,
|
|
- struct dim_policy *data,
|
|
- struct dim_policy **find_data)
|
|
-*/
|
|
-dim_rb_add(dim_policy);
|
|
-
|
|
-static void policy_destroy(struct dim_policy *policy)
|
|
-{
|
|
- kfree(policy->val);
|
|
- kfree(policy);
|
|
-}
|
|
-
|
|
-static int policy_add(int obj, int key, const char *val, int action)
|
|
-{
|
|
- int ret = 0;
|
|
- struct dim_policy *policy = NULL;
|
|
-
|
|
- policy = dim_kmalloc_gfp(sizeof(struct dim_policy));
|
|
- if (policy == NULL)
|
|
- return -ENOMEM;
|
|
-
|
|
- policy->obj = obj;
|
|
- policy->key = key;
|
|
- policy->action = action;
|
|
- policy->val = kstrdup(val, GFP_KERNEL);
|
|
- if (policy->val == NULL) {
|
|
- kfree(policy);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- ret = dim_policy_rb_add(&policy_root, policy, NULL);
|
|
- if (ret < 0)
|
|
- policy_destroy(policy);
|
|
-
|
|
- return ret == -EEXIST ? 0 : ret;
|
|
-}
|
|
-
|
|
-static int policy_add_kernel(int action)
|
|
-{
|
|
- return policy_add(DIM_POLICY_OBJ_KERNEL_TEXT, DIM_POLICY_KEY_NAME,
|
|
- init_uts_ns.name.release, action);
|
|
-}
|
|
-
|
|
-static int policy_add_module(const char *name, int action)
|
|
-{
|
|
- return policy_add(DIM_POLICY_OBJ_MODULE_TEXT, DIM_POLICY_KEY_NAME,
|
|
- name, action);
|
|
-}
|
|
-
|
|
-static int policy_add_path(const char *path, int action)
|
|
-{
|
|
- int ret = 0;
|
|
- char *path_buf = NULL;
|
|
- const char *apath = NULL;
|
|
-
|
|
- /* This element is a filepath */
|
|
- ret = policy_add(DIM_POLICY_OBJ_BPRM_TEXT, DIM_POLICY_KEY_PATH,
|
|
- path, action);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- /* Try to get the absolute path */
|
|
- path_buf = dim_kmalloc_gfp(PATH_MAX);
|
|
- if (path_buf == NULL)
|
|
- return -ENOMEM;
|
|
-
|
|
- apath = dim_absolute_path(path, path_buf, PATH_MAX);
|
|
- if (IS_ERR(apath)) {
|
|
- dim_warn("failed to get absolute path of %s in policy: %ld\n",
|
|
- path, PTR_ERR(apath));
|
|
- kfree(path_buf);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (strcmp(path, apath) != 0)
|
|
- ret = policy_add(DIM_POLICY_OBJ_BPRM_TEXT, DIM_POLICY_KEY_PATH,
|
|
- apath, action);
|
|
-
|
|
- kfree(path_buf);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static int policy_parse_key_value(const char *s, int *key, const char **val)
|
|
-{
|
|
- int i = 0;
|
|
- int len = 0;
|
|
-
|
|
- for (; i < DIM_POLICY_KEY_LAST; i++) {
|
|
- len = strlen(dim_policy_key_str[i]);
|
|
- if (strncmp(s, dim_policy_key_str[i], len) == 0) {
|
|
- *key = i;
|
|
- *val = s + len;
|
|
- return 0;
|
|
- }
|
|
- }
|
|
-
|
|
- return -EINVAL;
|
|
-}
|
|
-
|
|
-static int policy_parse_obj(const char *s, int *key)
|
|
-{
|
|
- int ret = match_string(dim_policy_obj_str, DIM_POLICY_OBJ_LAST, s);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- *key = ret;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int policy_parse_line(char* line, int line_no)
|
|
-{
|
|
- int ret = 0;
|
|
- char *p = NULL;
|
|
- char *line_str = line;
|
|
- /* currently only support log action */
|
|
- int action = DIM_POLICY_LOG;
|
|
- int obj = 0;
|
|
- int key = 0;
|
|
- const char *val = NULL;
|
|
-
|
|
- if (line_no > DIM_POLICY_LINE_MAX) {
|
|
- dim_warn("more than %d policy items will be ignored\n",
|
|
- DIM_POLICY_LINE_MAX);
|
|
- return -E2BIG;
|
|
- }
|
|
-
|
|
- if (strlen(line) == 0 || line[0] == '#')
|
|
- return 0; /* ignore blank line and comment */
|
|
-
|
|
- if (strlen(line) > DIM_POLICY_MAX_LEN) {
|
|
- dim_err("overlength item at line %d\n", line_no);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if ((p = strsep(&line_str, " ")) == NULL ||
|
|
- strcmp(p, DIM_POLICY_MEASURE) != 0) {
|
|
- dim_err("invalid policy prefix at line %d\n", line_no);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if ((p = strsep(&line_str, " ")) == NULL ||
|
|
- (policy_parse_obj(p, &obj)) < 0) {
|
|
- dim_err("invalid policy object at line %d\n", line_no);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- /* for kernel policy, ignore other parameters */
|
|
- if (obj == DIM_POLICY_OBJ_KERNEL_TEXT) {
|
|
- ret = policy_add_kernel(action);
|
|
- if (ret < 0)
|
|
- dim_err("failed to add measure policy line %d: %d\n",
|
|
- line_no, ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- if ((p = strsep(&line_str, " ")) == NULL ||
|
|
- (policy_parse_key_value(p, &key, &val)) < 0) {
|
|
- dim_err("invalid policy key at line %d\n", line_no);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if ((obj == DIM_POLICY_OBJ_BPRM_TEXT && key != DIM_POLICY_KEY_PATH) ||
|
|
- (obj == DIM_POLICY_OBJ_MODULE_TEXT && key != DIM_POLICY_KEY_NAME)) {
|
|
- dim_err("mismatch policy object and key at line %d\n", line_no);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- ret = obj == DIM_POLICY_OBJ_BPRM_TEXT ?
|
|
- policy_add_path(val, action) :
|
|
- policy_add_module(val, action);
|
|
- if (ret < 0)
|
|
- dim_err("failed to add measure policy line %d: %d\n",
|
|
- line_no, ret);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-int dim_core_policy_load(void)
|
|
-{
|
|
- int ret = 0;
|
|
- void *buf = NULL;
|
|
- loff_t buf_len = 0;
|
|
-
|
|
- if (!RB_EMPTY_ROOT(&policy_root))
|
|
- dim_core_policy_destroy();
|
|
-
|
|
- ret = dim_read_verify_file(NULL, DIM_POLICY_PATH, &buf);
|
|
- if (ret < 0 || buf == NULL) {
|
|
- dim_err("failed to read policy file: %d\n", ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- buf_len = ret;
|
|
- ret = dim_parse_line_buf(buf, buf_len, policy_parse_line);
|
|
- if (ret < 0) {
|
|
- dim_err("failed to parse policy: %d\n", ret);
|
|
- dim_core_policy_destroy();
|
|
- }
|
|
-
|
|
- vfree(buf);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-void dim_core_policy_destroy(void)
|
|
-{
|
|
- struct dim_policy *pos = NULL;
|
|
- struct dim_policy *n = NULL;
|
|
-
|
|
- rbtree_postorder_for_each_entry_safe(pos, n, &policy_root, rb_node)
|
|
- policy_destroy(pos);
|
|
-
|
|
- policy_root = RB_ROOT;
|
|
-}
|
|
-
|
|
-bool dim_core_policy_match(int obj, int key, const char *val)
|
|
-{
|
|
- struct dim_policy policy = {
|
|
- .obj = obj,
|
|
- .key = key,
|
|
- .val = val,
|
|
- };
|
|
-
|
|
- if (obj < 0 || obj >= DIM_POLICY_OBJ_LAST ||
|
|
- key < 0 || key >= DIM_POLICY_KEY_LAST ||
|
|
- val == NULL)
|
|
- return false;
|
|
-
|
|
- return dim_policy_rb_find(&policy_root, &policy, NULL) == 0;
|
|
-}
|
|
-
|
|
-int dim_core_policy_get_action(int obj __always_unused,
|
|
- int key __always_unused,
|
|
- const char *val __always_unused)
|
|
-{
|
|
- return DIM_POLICY_LOG;
|
|
-}
|
|
-
|
|
-int dim_core_policy_walk(int (*f)(struct dim_policy *, void *), void *data)
|
|
-{
|
|
- int ret = 0;
|
|
- struct dim_policy *pos = NULL;
|
|
- struct dim_policy *n = NULL;
|
|
-
|
|
- rbtree_postorder_for_each_entry_safe(pos, n, &policy_root, rb_node) {
|
|
- ret = f(pos, data);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
diff --git a/src/core/dim_core_policy.h b/src/core/dim_core_policy.h
|
|
deleted file mode 100644
|
|
index 2baab12..0000000
|
|
--- a/src/core/dim_core_policy.h
|
|
+++ /dev/null
|
|
@@ -1,63 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#ifndef __DIM_CORE_POLICY_H
|
|
-#define __DIM_CORE_POLICY_H
|
|
-
|
|
-#include <linux/rbtree.h>
|
|
-
|
|
-#define DIM_POLICY_PATH "/etc/dim/policy"
|
|
-#define DIM_POLICY_LINE_MAX 10000
|
|
-
|
|
-/* policy key */
|
|
-#define DIM_POLICY_MEASURE "measure"
|
|
-
|
|
-/* DIM_POLICY_OBJECT */
|
|
-enum dim_policy_obj {
|
|
- DIM_POLICY_OBJ_BPRM_TEXT,
|
|
- DIM_POLICY_OBJ_MODULE_TEXT,
|
|
- DIM_POLICY_OBJ_KERNEL_TEXT,
|
|
- DIM_POLICY_OBJ_LAST,
|
|
-};
|
|
-
|
|
-/* DIM_POLICY_KEY */
|
|
-enum dim_policy_key {
|
|
- DIM_POLICY_KEY_NAME,
|
|
- DIM_POLICY_KEY_PATH,
|
|
- DIM_POLICY_KEY_LAST,
|
|
-};
|
|
-
|
|
- /* measure obj=MODULE_TEXT path={PATH_MAX}\n*/
|
|
- #define DIM_POLICY_OBJ_MAX_LEN 15
|
|
- #define DIM_POLICY_KEY_MAX_LEN 5
|
|
- #define DIM_POLICY_MAX_LEN (strlen(DIM_POLICY_MEASURE) + 1 + \
|
|
- DIM_POLICY_OBJ_MAX_LEN + 1 + \
|
|
- DIM_POLICY_KEY_MAX_LEN + 1 + PATH_MAX + 1 + 1)
|
|
-
|
|
-struct dim_policy {
|
|
- struct rb_node rb_node;
|
|
- int obj; /* enum dim_policy_obj */
|
|
- int key; /* enum dim_policy_key */
|
|
- const char *val;
|
|
- int action; /* enum dim_policy_action */
|
|
-};
|
|
-
|
|
-/* funtion to walk dim policy nodes */
|
|
-typedef int (*dim_policy_visitor)(struct dim_policy *, void *);
|
|
-
|
|
-enum dim_policy_action {
|
|
- DIM_POLICY_LOG,
|
|
- DIM_POLICY_KILL,
|
|
- DIM_POLICY_LAST,
|
|
-};
|
|
-
|
|
-int dim_core_policy_load(void);
|
|
-void dim_core_policy_destroy(void);
|
|
-bool dim_core_policy_match(int obj, int key, const char *val);
|
|
-int dim_core_policy_walk(dim_policy_visitor f, void *data);
|
|
-int dim_core_policy_get_action(int obj __always_unused,
|
|
- int key __always_unused,
|
|
- const char *val __always_unused);
|
|
-
|
|
-#endif
|
|
diff --git a/src/core/dim_core_static_baseline.c b/src/core/dim_core_static_baseline.c
|
|
index f23dbce..1a87cfd 100644
|
|
--- a/src/core/dim_core_static_baseline.c
|
|
+++ b/src/core/dim_core_static_baseline.c
|
|
@@ -47,7 +47,7 @@ static bool match_policy(const char *name, int type)
|
|
DIM_POLICY_KEY_NAME, mod_name);
|
|
}
|
|
|
|
-static int parse_simple_baseline_line(char* line, int line_no)
|
|
+static int parse_simple_baseline_line(char* line, int line_no, void *data)
|
|
{
|
|
int ret = 0;
|
|
int type = 0;
|
|
@@ -149,7 +149,7 @@ static_baseline_load(struct dir_context *__ctx,
|
|
}
|
|
|
|
buf_len = ret;
|
|
- ret = dim_parse_line_buf(buf, buf_len, parse_simple_baseline_line);
|
|
+ ret = dim_parse_line_buf(buf, buf_len, parse_simple_baseline_line, NULL);
|
|
if (ret < 0)
|
|
dim_err("failed to parse baseline file %s: %d\n", name, ret);
|
|
out:
|
|
diff --git a/src/core/measure_task/dim_core_measure_module.c b/src/core/measure_task/dim_core_measure_module.c
|
|
index 497d3a4..aa3e2f3 100644
|
|
--- a/src/core/measure_task/dim_core_measure_module.c
|
|
+++ b/src/core/measure_task/dim_core_measure_module.c
|
|
@@ -64,11 +64,11 @@ static int measure_module(struct dim_policy *policy, void *data)
|
|
{
|
|
int ret = 0;
|
|
struct module_text_measure_ctx *ctx = data;
|
|
- const char *mod_name = policy->val;
|
|
+ const char *mod_name = policy->name;
|
|
struct dim_digest digest = { 0 };
|
|
|
|
if (policy == NULL || policy->obj != DIM_POLICY_OBJ_MODULE_TEXT ||
|
|
- policy->key != DIM_POLICY_KEY_NAME || mod_name == NULL)
|
|
+ mod_name == NULL)
|
|
return 0;
|
|
|
|
/* if module is not inserted in baseline_init stage, ignore it */
|
|
diff --git a/src/core/measure_task/dim_core_measure_task.c b/src/core/measure_task/dim_core_measure_task.c
|
|
index f240ddc..c9d21b1 100644
|
|
--- a/src/core/measure_task/dim_core_measure_task.c
|
|
+++ b/src/core/measure_task/dim_core_measure_task.c
|
|
@@ -293,13 +293,17 @@ static int check_user_digest(struct dim_digest *digest,
|
|
return ret;
|
|
}
|
|
|
|
- if (log_flag != LOG_TAMPERED || !dim_core_tampered_action_get())
|
|
+ if (log_flag != LOG_TAMPERED || !dim_core_measure_action_enabled)
|
|
return 0;
|
|
|
|
+ /* now the process is tampered, check if action need to be taken */
|
|
action = dim_core_policy_get_action(DIM_POLICY_OBJ_BPRM_TEXT,
|
|
DIM_POLICY_KEY_PATH, ctx->path);
|
|
- if (action == DIM_POLICY_KILL)
|
|
+ if (action == DIM_POLICY_ACTION_KILL) {
|
|
+ dim_warn("kill action is set, process %s will be killed\n",
|
|
+ ctx->path);
|
|
ctx->task_kill = true; /* this task need to be killed */
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/src/core/policy/dim_core_policy.c b/src/core/policy/dim_core_policy.c
|
|
new file mode 100644
|
|
index 0000000..4d7bcc1
|
|
--- /dev/null
|
|
+++ b/src/core/policy/dim_core_policy.c
|
|
@@ -0,0 +1,268 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include <linux/fs.h>
|
|
+#include <linux/err.h>
|
|
+#include <linux/errno.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/uaccess.h>
|
|
+#include <linux/vmalloc.h>
|
|
+#include <linux/namei.h>
|
|
+#include <linux/utsname.h>
|
|
+
|
|
+#include "dim_utils.h"
|
|
+#include "dim_rb.h"
|
|
+
|
|
+#include "dim_core_sig.h"
|
|
+#include "dim_core_policy.h"
|
|
+
|
|
+static struct rb_root policy_root = RB_ROOT;
|
|
+
|
|
+static int dim_policy_compare(struct dim_policy *x, struct dim_policy *y)
|
|
+{
|
|
+ if (x->obj != y->obj)
|
|
+ return x->obj - y->obj;
|
|
+
|
|
+ switch (x->obj) {
|
|
+ case DIM_POLICY_OBJ_BPRM_TEXT:
|
|
+ if (x->path == NULL || y->path == NULL)
|
|
+ return -1;
|
|
+ return strcmp(x->path, y->path);
|
|
+ case DIM_POLICY_OBJ_MODULE_TEXT:
|
|
+ if (x->name == NULL || y->name == NULL)
|
|
+ return -1;
|
|
+ return strcmp(x->name, y->name);
|
|
+ case DIM_POLICY_OBJ_KERNEL_TEXT:
|
|
+ return 0;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+/*
|
|
+static int dim_policy_rb_find(struct rb_root *root,
|
|
+ struct dim_policy *data,
|
|
+ struct dim_policy **find_data)
|
|
+*/
|
|
+dim_rb_find(dim_policy);
|
|
+/*
|
|
+static int dim_policy_rb_add(struct rb_root *root,
|
|
+ struct dim_policy *data,
|
|
+ struct dim_policy **find_data)
|
|
+*/
|
|
+dim_rb_add(dim_policy);
|
|
+
|
|
+void policy_destroy(struct dim_policy *policy)
|
|
+{
|
|
+ if (policy == NULL)
|
|
+ return;
|
|
+
|
|
+ dim_kfree((char *)policy->name);
|
|
+ dim_kfree((char *)policy->path);
|
|
+ dim_kfree(policy);
|
|
+}
|
|
+
|
|
+static int policy_check_add_bprm_text(struct dim_policy *policy)
|
|
+{
|
|
+ int ret = 0;
|
|
+ const char *apath = NULL;
|
|
+ struct dim_policy *p = NULL;
|
|
+
|
|
+ /* check the policy is valid */
|
|
+ if (policy->path == NULL) {
|
|
+ pr_err("path must be set for BPRM_TEXT policy\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (strlen(policy->path) + 1 > PATH_MAX) {
|
|
+ pr_err("path must be shorter than %d\n", PATH_MAX);
|
|
+ return -ENAMETOOLONG;
|
|
+ }
|
|
+
|
|
+ if (policy->name != NULL)
|
|
+ pr_warn("name is ignored for BPRM_TEXT policy\n");
|
|
+
|
|
+ /* firstly, add the current node */
|
|
+ ret = dim_policy_rb_add(&policy_root, policy, NULL);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ /* secondly, try to add another node with absolute path. beacuse
|
|
+ sometimes users may not sure whether to write /usr/bin/bash
|
|
+ or /bin/bash in policy */
|
|
+ ret = dim_get_absolute_path(policy->path, &apath);
|
|
+ if (ret < 0) {
|
|
+ dim_warn("failed to get absolute path of %s in policy: %d\n",
|
|
+ policy->path, ret);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (strcmp(apath, policy->path) == 0) {
|
|
+ /* the two paths are same, no need to add another policy */
|
|
+ dim_kfree((char *)apath);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ p = kmemdup(policy, sizeof(struct dim_policy), GFP_KERNEL);
|
|
+ if (p == NULL) {
|
|
+ dim_kfree((char *)apath);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ /* set the absolute path and add the policy node */
|
|
+ p->path = apath;
|
|
+ ret = dim_policy_rb_add(&policy_root, p, NULL);
|
|
+ if (ret < 0)
|
|
+ policy_destroy(p);
|
|
+
|
|
+ /* the EEXIST error must be processed here */
|
|
+ return ret == -EEXIST ? 0 : ret;
|
|
+}
|
|
+
|
|
+static int policy_check_add_module_text(struct dim_policy *policy)
|
|
+{
|
|
+ if (policy->name == NULL) {
|
|
+ pr_err("name must be set for MODULE_TEXT policy\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (strlen(policy->name) + 1 > NAME_MAX) {
|
|
+ pr_err("name must be shorter than %d\n", NAME_MAX);
|
|
+ return -ENAMETOOLONG;
|
|
+ }
|
|
+
|
|
+ if (policy->path != NULL)
|
|
+ pr_warn("path is ignored for BPRM_TEXT policy\n");
|
|
+
|
|
+ if (policy->action != DIM_POLICY_ACTION_LOG)
|
|
+ pr_warn("action is ignored for MODULE_TEXT policy\n");
|
|
+
|
|
+ return dim_policy_rb_add(&policy_root, policy, NULL);
|
|
+}
|
|
+
|
|
+static int policy_check_add_kernel_text(struct dim_policy *policy)
|
|
+{
|
|
+ if (policy->name != NULL || policy->path != NULL ||
|
|
+ policy->action != DIM_POLICY_ACTION_LOG)
|
|
+ pr_warn("all parameters are ignored for KERNEL_TEXT policy\n");
|
|
+
|
|
+ return dim_policy_rb_add(&policy_root, policy, NULL);
|
|
+}
|
|
+
|
|
+static int policy_check_add(struct dim_policy *policy)
|
|
+{
|
|
+ switch (policy->obj)
|
|
+ {
|
|
+ case DIM_POLICY_OBJ_BPRM_TEXT:
|
|
+ return policy_check_add_bprm_text(policy);
|
|
+ case DIM_POLICY_OBJ_MODULE_TEXT:
|
|
+ return policy_check_add_module_text(policy);
|
|
+ case DIM_POLICY_OBJ_KERNEL_TEXT:
|
|
+ return policy_check_add_kernel_text(policy);
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+int dim_core_policy_load(void)
|
|
+{
|
|
+ int ret = 0;
|
|
+ void *buf = NULL;
|
|
+ loff_t buf_len = 0;
|
|
+
|
|
+ if (!RB_EMPTY_ROOT(&policy_root))
|
|
+ dim_core_policy_destroy();
|
|
+
|
|
+ ret = dim_read_verify_file(NULL, DIM_POLICY_PATH, &buf);
|
|
+ if (ret < 0 || buf == NULL) {
|
|
+ dim_err("failed to read policy file: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ buf_len = ret;
|
|
+ ret = dim_policy_parse(buf, buf_len, policy_check_add);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to parse policy: %d\n", ret);
|
|
+ dim_core_policy_destroy();
|
|
+ }
|
|
+
|
|
+ vfree(buf);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+void dim_core_policy_destroy(void)
|
|
+{
|
|
+ struct dim_policy *pos = NULL;
|
|
+ struct dim_policy *n = NULL;
|
|
+
|
|
+ rbtree_postorder_for_each_entry_safe(pos, n, &policy_root, rb_node)
|
|
+ policy_destroy(pos);
|
|
+
|
|
+ policy_root = RB_ROOT;
|
|
+}
|
|
+
|
|
+static int policy_find(int obj, int key __always_unused, const char *val,
|
|
+ struct dim_policy **find)
|
|
+{
|
|
+ struct dim_policy policy = { 0 };
|
|
+
|
|
+ /* now the key parameter is unused */
|
|
+ switch (obj) {
|
|
+ case DIM_POLICY_OBJ_BPRM_TEXT:
|
|
+ policy.path = val;
|
|
+ break;
|
|
+ case DIM_POLICY_OBJ_MODULE_TEXT:
|
|
+ policy.name = val;
|
|
+ break;
|
|
+ case DIM_POLICY_OBJ_KERNEL_TEXT:
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ policy.obj = obj;
|
|
+ return dim_policy_rb_find(&policy_root, &policy, find);
|
|
+}
|
|
+
|
|
+bool dim_core_policy_match(int obj, int key, const char *val)
|
|
+{
|
|
+ if (val == NULL)
|
|
+ return false;
|
|
+
|
|
+ return policy_find(obj, key, val, NULL) == 0;
|
|
+}
|
|
+
|
|
+int dim_core_policy_get_action(int obj, int key, const char *val)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct dim_policy *find = NULL;
|
|
+
|
|
+ if (val == NULL)
|
|
+ return DIM_POLICY_ACTION_LAST;
|
|
+
|
|
+ ret = policy_find(obj, key, val, &find);
|
|
+ if (ret < 0)
|
|
+ return DIM_POLICY_ACTION_LAST;
|
|
+
|
|
+ return find->action;
|
|
+}
|
|
+
|
|
+int dim_core_policy_walk(int (*f)(struct dim_policy *, void *), void *data)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct dim_policy *pos = NULL;
|
|
+ struct dim_policy *n = NULL;
|
|
+
|
|
+ rbtree_postorder_for_each_entry_safe(pos, n, &policy_root, rb_node) {
|
|
+ ret = f(pos, data);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/src/core/policy/dim_core_policy.h b/src/core/policy/dim_core_policy.h
|
|
new file mode 100644
|
|
index 0000000..7f2c756
|
|
--- /dev/null
|
|
+++ b/src/core/policy/dim_core_policy.h
|
|
@@ -0,0 +1,69 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __DIM_CORE_POLICY_H
|
|
+#define __DIM_CORE_POLICY_H
|
|
+
|
|
+#include <linux/rbtree.h>
|
|
+
|
|
+/* the policy filepath */
|
|
+#define DIM_POLICY_PATH "/etc/dim/policy"
|
|
+/* max number of lines for parsing */
|
|
+#define DIM_POLICY_LINE_MAX 10000
|
|
+
|
|
+/* measurement object of policy */
|
|
+enum dim_policy_obj {
|
|
+ DIM_POLICY_OBJ_BPRM_TEXT,
|
|
+ DIM_POLICY_OBJ_MODULE_TEXT,
|
|
+ DIM_POLICY_OBJ_KERNEL_TEXT,
|
|
+ DIM_POLICY_OBJ_LAST,
|
|
+};
|
|
+
|
|
+/* key of measurement condition */
|
|
+enum dim_policy_key {
|
|
+ DIM_POLICY_KEY_OBJ,
|
|
+ DIM_POLICY_KEY_NAME,
|
|
+ DIM_POLICY_KEY_PATH,
|
|
+ DIM_POLICY_KEY_ACTION,
|
|
+ DIM_POLICY_KEY_LAST,
|
|
+};
|
|
+
|
|
+/* action to perform when dim detected a tampering */
|
|
+enum dim_policy_action {
|
|
+ /* add to measure log (default) */
|
|
+ DIM_POLICY_ACTION_LOG,
|
|
+ /* kill the tampered user process */
|
|
+ DIM_POLICY_ACTION_KILL,
|
|
+ DIM_POLICY_ACTION_LAST,
|
|
+};
|
|
+
|
|
+struct dim_policy {
|
|
+ struct rb_node rb_node;
|
|
+ int obj; /* enum dim_policy_obj */
|
|
+ const char *path; /* user process path */
|
|
+ const char *name; /* module name */
|
|
+ int action; /* enum dim_policy_action */
|
|
+};
|
|
+
|
|
+/* callback funtion to walk dim policy nodes */
|
|
+typedef int (*dim_policy_visitor)(struct dim_policy *, void *);
|
|
+
|
|
+/* callback funtion to add a policy item when parsing policy file */
|
|
+typedef int (*policy_add_func)(struct dim_policy *);
|
|
+
|
|
+/* parse dim policy in complex format */
|
|
+int policy_parse_complex_format(char *buf, size_t buf_len,
|
|
+ policy_add_func policy_add);
|
|
+#define dim_policy_parse policy_parse_complex_format
|
|
+
|
|
+/* export for implementing the policy parser */
|
|
+void policy_destroy(struct dim_policy *policy);
|
|
+
|
|
+int dim_core_policy_load(void);
|
|
+void dim_core_policy_destroy(void);
|
|
+bool dim_core_policy_match(int obj, int key, const char *val);
|
|
+int dim_core_policy_walk(dim_policy_visitor f, void *data);
|
|
+int dim_core_policy_get_action(int obj, int key, const char *val);
|
|
+
|
|
+#endif
|
|
diff --git a/src/core/policy/dim_core_policy_complex.c b/src/core/policy/dim_core_policy_complex.c
|
|
new file mode 100644
|
|
index 0000000..b29483d
|
|
--- /dev/null
|
|
+++ b/src/core/policy/dim_core_policy_complex.c
|
|
@@ -0,0 +1,190 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include <linux/slab.h>
|
|
+
|
|
+#include "dim_utils.h"
|
|
+
|
|
+#include "dim_core_policy.h"
|
|
+
|
|
+/* policy key */
|
|
+#define DIM_POLICY_MEASURE "measure"
|
|
+
|
|
+/* measure obj=MODULE_TEXT path={PATH_MAX} action=kill\n */
|
|
+#define DIM_POLICY_MAX_KEY_FIELDS 3
|
|
+#define DIM_POLICY_OBJ_MAX_LEN 15
|
|
+#define DIM_POLICY_KEY_MAX_LEN 5
|
|
+#define DIM_POLICY_ACTION_MAX_LEN 11
|
|
+#define DIM_POLICY_MAX_LEN (strlen(DIM_POLICY_MEASURE) + 1 + \
|
|
+ DIM_POLICY_OBJ_MAX_LEN + 1 + \
|
|
+ DIM_POLICY_KEY_MAX_LEN + 1 + PATH_MAX + 1 + \
|
|
+ DIM_POLICY_ACTION_MAX_LEN + 1)
|
|
+
|
|
+static const char *dim_policy_key_str[DIM_POLICY_KEY_LAST] = {
|
|
+ [DIM_POLICY_KEY_OBJ] = "obj=",
|
|
+ [DIM_POLICY_KEY_NAME] = "name=",
|
|
+ [DIM_POLICY_KEY_PATH] = "path=",
|
|
+ [DIM_POLICY_KEY_ACTION] = "action=",
|
|
+};
|
|
+
|
|
+static const char *dim_policy_obj_str[DIM_POLICY_OBJ_LAST] = {
|
|
+ [DIM_POLICY_OBJ_BPRM_TEXT] = "BPRM_TEXT",
|
|
+ [DIM_POLICY_OBJ_MODULE_TEXT] = "MODULE_TEXT",
|
|
+ [DIM_POLICY_OBJ_KERNEL_TEXT] = "KERNEL_TEXT",
|
|
+};
|
|
+
|
|
+static const char *dim_policy_action_str[DIM_POLICY_KEY_LAST] = {
|
|
+ [DIM_POLICY_ACTION_LOG] = "log",
|
|
+ [DIM_POLICY_ACTION_KILL] = "kill",
|
|
+};
|
|
+
|
|
+static const char *policy_get_string_value(const char *s)
|
|
+{
|
|
+ return kstrdup(s, GFP_KERNEL);
|
|
+}
|
|
+
|
|
+static int policy_get_action(const char *s)
|
|
+{
|
|
+ return match_string(dim_policy_action_str, DIM_POLICY_ACTION_LAST, s);
|
|
+}
|
|
+
|
|
+static int policy_get_obj(const char *s)
|
|
+{
|
|
+ return match_string(dim_policy_obj_str, DIM_POLICY_OBJ_LAST, s);
|
|
+}
|
|
+
|
|
+static int policy_get_key(const char *s, const char **val)
|
|
+{
|
|
+ unsigned int i = 0;
|
|
+ unsigned int len = 0;
|
|
+
|
|
+ for (; i < DIM_POLICY_KEY_LAST; i++) {
|
|
+ len = strlen(dim_policy_key_str[i]);
|
|
+ if (strncmp(s, dim_policy_key_str[i], len) == 0) {
|
|
+ *val = s + len;
|
|
+ return i;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+static int policy_parse_key_value(char *s, struct dim_policy *policy)
|
|
+{
|
|
+ char *p = NULL;
|
|
+ int key = 0;
|
|
+ int filed_num = 0;
|
|
+ const char *val = NULL;
|
|
+
|
|
+ while ((p = strsep(&s, " ")) != NULL) {
|
|
+ key = policy_get_key(p, &val);
|
|
+ if (key < 0 || val == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (++filed_num > DIM_POLICY_MAX_KEY_FIELDS)
|
|
+ return -EINVAL;
|
|
+
|
|
+ switch (key)
|
|
+ {
|
|
+ case DIM_POLICY_KEY_OBJ:
|
|
+ policy->obj = policy_get_obj(val);
|
|
+ if (policy->obj < 0)
|
|
+ return -EINVAL;
|
|
+ break;
|
|
+ case DIM_POLICY_KEY_NAME:
|
|
+ policy->name = policy_get_string_value(val);
|
|
+ if (policy->name == NULL)
|
|
+ return -ENOMEM;
|
|
+ break;
|
|
+ case DIM_POLICY_KEY_PATH:
|
|
+ policy->path = policy_get_string_value(val);
|
|
+ if (policy->path == NULL)
|
|
+ return -ENOMEM;
|
|
+ break;
|
|
+ case DIM_POLICY_KEY_ACTION:
|
|
+ policy->action = policy_get_action(val);
|
|
+ if (policy->action < 0)
|
|
+ return -EINVAL;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int parse_line(char *line_str, struct dim_policy *policy)
|
|
+{
|
|
+ int ret = 0;
|
|
+ char *p = NULL;
|
|
+
|
|
+ if ((p = strsep(&line_str, " ")) == NULL ||
|
|
+ strcmp(p, DIM_POLICY_MEASURE) != 0) {
|
|
+ dim_err("invalid policy prefix, must start with %s\n",
|
|
+ DIM_POLICY_MEASURE);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ ret = policy_parse_key_value(line_str, policy);
|
|
+ if (ret < 0) {
|
|
+ dim_err("fail to parse policy key and value: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int policy_parse_line(char* line, int line_no, void *data)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct dim_policy *policy = NULL;
|
|
+ policy_add_func policy_add = data;
|
|
+
|
|
+ if (line_no > DIM_POLICY_LINE_MAX) {
|
|
+ dim_warn("more than %d policy items will be ignored\n",
|
|
+ DIM_POLICY_LINE_MAX);
|
|
+ return -E2BIG;
|
|
+ }
|
|
+
|
|
+ if (strlen(line) == 0 || line[0] == '#')
|
|
+ return 0; /* ignore blank line and comment */
|
|
+
|
|
+ if (strlen(line) > DIM_POLICY_MAX_LEN) {
|
|
+ dim_err("overlength line %d\n", line_no);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ policy = dim_kmalloc_gfp(sizeof(struct dim_policy));
|
|
+ if (policy == NULL)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ memset(policy, 0, sizeof(struct dim_policy));
|
|
+
|
|
+ ret = parse_line(line, policy);
|
|
+ if (ret < 0) {
|
|
+ dim_err("fail to parse policy at line %d: %d\n", line_no, ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = policy_add(policy);
|
|
+ if (ret < 0) {
|
|
+ policy_destroy(policy);
|
|
+ /* ignore the repeat add */
|
|
+ if (ret != -EEXIST)
|
|
+ dim_err("fail to add policy at line %d: %d\n", line_no, ret);
|
|
+ return ret == -EEXIST ? 0 : ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int policy_parse_complex_format(char *buf, size_t buf_len,
|
|
+ policy_add_func policy_add)
|
|
+{
|
|
+ if (buf == NULL || buf_len == 0 || policy_add == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return dim_parse_line_buf(buf, buf_len, policy_parse_line, policy_add);
|
|
+}
|
|
\ No newline at end of file
|
|
--
|
|
2.33.0
|
|
|