3199 lines
93 KiB
Diff
3199 lines
93 KiB
Diff
From f1751e2438811f861e24e7be285a333942132b47 Mon Sep 17 00:00:00 2001
|
|
From: Huaxin Lu <luhuaxin1@huawei.com>
|
|
Date: Sun, 11 Feb 2024 14:36:27 +0800
|
|
Subject: [PATCH 12/26] Refactor the measurement code
|
|
|
|
Refactor the measurement function code, extract a measurement
|
|
framework layer to implement the common measurement logic.
|
|
---
|
|
src/Makefile | 30 +-
|
|
src/common/dim_baseline.c | 10 +-
|
|
src/common/dim_entry.h | 11 +-
|
|
src/common/dim_hash.c | 2 +-
|
|
src/common/dim_status.c | 39 ---
|
|
src/common/dim_status.h | 23 --
|
|
src/common/dim_utils.h | 8 +-
|
|
src/core/dim_core.h | 13 -
|
|
src/core/dim_core_baseline.c | 115 -------
|
|
src/core/dim_core_baseline.h | 25 --
|
|
src/core/dim_core_fs.c | 33 +-
|
|
src/core/dim_core_main.c | 37 +-
|
|
src/core/dim_core_measure.c | 315 ++++++++----------
|
|
src/core/dim_core_measure.h | 73 +---
|
|
src/core/dim_core_measure_common.c | 87 -----
|
|
src/core/dim_core_mem_pool.c | 3 +-
|
|
src/core/dim_core_policy.c | 5 +-
|
|
src/core/dim_core_policy.h | 2 +
|
|
src/core/dim_core_sig.c | 3 +-
|
|
src/core/dim_core_static_baseline.c | 16 +-
|
|
src/core/dim_core_static_baseline.h | 2 +
|
|
src/core/dim_core_status.c | 42 ---
|
|
src/core/dim_core_status.h | 24 --
|
|
src/core/dim_core_symbol.c | 2 +-
|
|
.../dim_core_measure_kernel.c | 40 ++-
|
|
.../dim_core_measure_module.c | 48 ++-
|
|
.../dim_core_measure_task.c | 83 +++--
|
|
src/core/measure_task/dim_core_measure_task.h | 8 +
|
|
src/measure/dim_measure.c | 100 ++++++
|
|
src/measure/dim_measure.h | 117 +++++++
|
|
src/measure/dim_measure_baseline.c | 235 +++++++++++++
|
|
src/measure/dim_measure_status.c | 34 ++
|
|
src/measure/dim_measure_task.c | 91 +++++
|
|
src/measure/dim_measure_utils.c | 13 +
|
|
src/monitor/dim_monitor.h | 33 +-
|
|
src/monitor/dim_monitor_fs.c | 22 +-
|
|
src/monitor/dim_monitor_main.c | 23 +-
|
|
src/monitor/dim_monitor_measure.c | 245 +++-----------
|
|
src/monitor/dim_monitor_symbol.c | 2 +-
|
|
.../measure_task/dim_monitor_measure_data.c | 56 ++++
|
|
.../measure_task/dim_monitor_measure_task.h | 11 +
|
|
.../measure_task/dim_monitor_measure_text.c | 64 ++++
|
|
42 files changed, 1171 insertions(+), 974 deletions(-)
|
|
delete mode 100644 src/common/dim_status.c
|
|
delete mode 100644 src/common/dim_status.h
|
|
delete mode 100644 src/core/dim_core.h
|
|
delete mode 100644 src/core/dim_core_baseline.c
|
|
delete mode 100644 src/core/dim_core_baseline.h
|
|
delete mode 100644 src/core/dim_core_measure_common.c
|
|
delete mode 100644 src/core/dim_core_status.c
|
|
delete mode 100644 src/core/dim_core_status.h
|
|
rename src/core/{ => measure_task}/dim_core_measure_kernel.c (79%)
|
|
rename src/core/{ => measure_task}/dim_core_measure_module.c (64%)
|
|
rename src/core/{ => measure_task}/dim_core_measure_task.c (88%)
|
|
create mode 100644 src/core/measure_task/dim_core_measure_task.h
|
|
create mode 100644 src/measure/dim_measure.c
|
|
create mode 100644 src/measure/dim_measure.h
|
|
create mode 100644 src/measure/dim_measure_baseline.c
|
|
create mode 100644 src/measure/dim_measure_status.c
|
|
create mode 100644 src/measure/dim_measure_task.c
|
|
create mode 100644 src/measure/dim_measure_utils.c
|
|
create mode 100644 src/monitor/measure_task/dim_monitor_measure_data.c
|
|
create mode 100644 src/monitor/measure_task/dim_monitor_measure_task.h
|
|
create mode 100644 src/monitor/measure_task/dim_monitor_measure_text.c
|
|
|
|
diff --git a/src/Makefile b/src/Makefile
|
|
index fe22112..1a3fac0 100644
|
|
--- a/src/Makefile
|
|
+++ b/src/Makefile
|
|
@@ -8,23 +8,24 @@ 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_baseline.o
|
|
dim_core-objs += core/dim_core_measure.o
|
|
-dim_core-objs += core/dim_core_measure_task.o
|
|
-dim_core-objs += core/dim_core_measure_module.o
|
|
-dim_core-objs += core/dim_core_measure_kernel.o
|
|
-dim_core-objs += core/dim_core_measure_common.o
|
|
-dim_core-objs += core/dim_core_status.o
|
|
dim_core-objs += core/dim_core_symbol.o
|
|
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 += common/dim_entry.o
|
|
dim_core-objs += common/dim_utils.o
|
|
dim_core-objs += common/dim_baseline.o
|
|
dim_core-objs += common/dim_hash.o
|
|
dim_core-objs += common/dim_measure_log.o
|
|
-dim_core-objs += common/dim_status.o
|
|
dim_core-objs += common/dim_tpm.o
|
|
dim_core-objs += common/dim_symbol.o
|
|
+dim_core-objs += measure/dim_measure.o
|
|
+dim_core-objs += measure/dim_measure_baseline.o
|
|
+dim_core-objs += measure/dim_measure_task.o
|
|
+dim_core-objs += measure/dim_measure_utils.o
|
|
+dim_core-objs += measure/dim_measure_status.o
|
|
|
|
dim_monitor-objs += monitor/dim_monitor_main.o
|
|
dim_monitor-objs += monitor/dim_monitor_fs.o
|
|
@@ -32,16 +33,26 @@ dim_monitor-objs += monitor/dim_monitor_measure.o
|
|
dim_monitor-objs += monitor/dim_monitor_symbol.o
|
|
dim_monitor-objs += common/dim_entry.o
|
|
dim_monitor-objs += common/dim_hash.o
|
|
-dim_monitor-objs += common/dim_status.o
|
|
dim_monitor-objs += common/dim_utils.o
|
|
dim_monitor-objs += common/dim_measure_log.o
|
|
dim_monitor-objs += common/dim_baseline.o
|
|
dim_monitor-objs += common/dim_tpm.o
|
|
dim_monitor-objs += common/dim_symbol.o
|
|
+dim_monitor-objs += measure/dim_measure.o
|
|
+dim_monitor-objs += measure/dim_measure_baseline.o
|
|
+dim_monitor-objs += measure/dim_measure_task.o
|
|
+dim_monitor-objs += measure/dim_measure_utils.o
|
|
+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)/monitor
|
|
+ccflags-y += -I$(src)/monitor/measure_task
|
|
ccflags-y += -I$(src)/common
|
|
+ccflags-y += -I$(src)/measure
|
|
|
|
EXTRA_CFLAGS += -Wall -Werror -D_FORTIFY_SOURCE=2 -O2 -fstack-protector-strong
|
|
|
|
@@ -61,3 +72,6 @@ install:
|
|
rmmod -f dim_core || :
|
|
insmod dim_core.ko
|
|
insmod dim_monitor.ko
|
|
+
|
|
+test:
|
|
+ cd ../test && { sh test_dim_core.sh; sh test_dim_monitor.sh; }
|
|
\ No newline at end of file
|
|
diff --git a/src/common/dim_baseline.c b/src/common/dim_baseline.c
|
|
index 09a2780..ec53b1c 100644
|
|
--- a/src/common/dim_baseline.c
|
|
+++ b/src/common/dim_baseline.c
|
|
@@ -4,6 +4,7 @@
|
|
|
|
#include "dim_rb.h"
|
|
#include "dim_baseline.h"
|
|
+#include "dim_utils.h"
|
|
|
|
static int dim_baseline_compare(struct dim_baseline *x,
|
|
struct dim_baseline *y)
|
|
@@ -104,7 +105,7 @@ int dim_baseline_add(struct dim_baseline_tree *root, const char *name,
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
- strncpy((char *)baseline->name, name, buf_len - 1);
|
|
+ strncpy((char *)baseline->name, name, buf_len - 1);
|
|
((char *)baseline->name)[buf_len - 1] = '\0';
|
|
|
|
write_lock(&root->lock);
|
|
@@ -143,12 +144,13 @@ void dim_baseline_destroy_tree(struct dim_baseline_tree *root)
|
|
int dim_baseline_init_tree(malloc_func malloc, free_func free,
|
|
struct dim_baseline_tree *root)
|
|
{
|
|
- if (malloc == NULL || free == NULL || root == NULL)
|
|
+ if (root == NULL)
|
|
return -EINVAL;
|
|
|
|
rwlock_init(&root->lock);
|
|
root->rb_root = RB_ROOT;
|
|
- root->malloc = malloc;
|
|
- root->free = free;
|
|
+ /* use kmalloc by default */
|
|
+ root->malloc = malloc == NULL ? dim_kmalloc_gfp : malloc;
|
|
+ root->free = free == NULL ? dim_kfree : free;
|
|
return 0;
|
|
}
|
|
diff --git a/src/common/dim_entry.h b/src/common/dim_entry.h
|
|
index acfc3a0..1c557b8 100644
|
|
--- a/src/common/dim_entry.h
|
|
+++ b/src/common/dim_entry.h
|
|
@@ -10,7 +10,6 @@
|
|
#include <linux/seq_file.h>
|
|
|
|
#include "dim_measure_log.h"
|
|
-#include "dim_status.h"
|
|
|
|
#define DIM_ENTRY_DIR_MASK (S_IFDIR | S_IRWXU | S_IRUSR)
|
|
#define DIM_ENTRY_RW_MASK (S_IWUSR | S_IRUSR)
|
|
@@ -26,7 +25,7 @@ struct dim_entry {
|
|
};
|
|
|
|
/* the file interface for trigger by 'echo 1 > file_path' */
|
|
-#define dim_trigger_entry(sname, fname, function, param) \
|
|
+#define dim_trigger_entry(sname, fname, function) \
|
|
static ssize_t sname##_trigger(struct file *file, \
|
|
const char __user *buf, \
|
|
size_t count, loff_t *ppos) \
|
|
@@ -41,7 +40,7 @@ static ssize_t sname##_trigger(struct file *file, \
|
|
if (ret < 0 || val != 1) \
|
|
return ret < 0 ? ret : -EINVAL; \
|
|
\
|
|
- ret = function(param); \
|
|
+ ret = function(); \
|
|
if (ret < 0) \
|
|
return ret; \
|
|
\
|
|
@@ -113,8 +112,8 @@ static struct dim_entry sname##_entry = { \
|
|
.fops = &sname##_ops, \
|
|
};
|
|
|
|
-/* the file interface for reading dim status */
|
|
-#define dim_status_entry(sname, fname, status_ptr) \
|
|
+/* the file interface for print string */
|
|
+#define dim_string_print_entry(sname, fname, function) \
|
|
static ssize_t sname##_read(struct file *file, \
|
|
char __user *buf, \
|
|
size_t count, loff_t *ppos) \
|
|
@@ -125,7 +124,7 @@ static ssize_t sname##_read(struct file *file, \
|
|
len = scnprintf(tmpbuf, \
|
|
DIM_FS_TMP_BUF_SIZE, \
|
|
"%s\n", \
|
|
- dim_status_get_name(status_ptr)); \
|
|
+ function()); \
|
|
\
|
|
return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); \
|
|
} \
|
|
diff --git a/src/common/dim_hash.c b/src/common/dim_hash.c
|
|
index 38464df..9f73320 100644
|
|
--- a/src/common/dim_hash.c
|
|
+++ b/src/common/dim_hash.c
|
|
@@ -49,7 +49,7 @@ int dim_hash_calculate(const void *data, unsigned int len,
|
|
int ret = 0;
|
|
SHASH_DESC_ON_STACK(shash, alg->tfm);
|
|
|
|
- if (data == NULL || alg == NULL || digest == NULL)
|
|
+ if (data == NULL || alg == NULL || digest == NULL || alg->tfm == NULL)
|
|
return -EINVAL;
|
|
|
|
digest->algo = alg->algo;
|
|
diff --git a/src/common/dim_status.c b/src/common/dim_status.c
|
|
deleted file mode 100644
|
|
index 411430a..0000000
|
|
--- a/src/common/dim_status.c
|
|
+++ /dev/null
|
|
@@ -1,39 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#include <linux/err.h>
|
|
-
|
|
-#include "dim_status.h"
|
|
-
|
|
-int dim_status_init(struct dim_status *status,
|
|
- const char **table,
|
|
- unsigned int len)
|
|
-{
|
|
- if (status == NULL || table == NULL || len == 0)
|
|
- return -EINVAL;
|
|
-
|
|
- status->table = table;
|
|
- status->table_len = len;
|
|
- atomic_set(&status->status_cur, 0);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int dim_status_get(struct dim_status *status)
|
|
-{
|
|
- return status == NULL ? 0 : atomic_read(&status->status_cur);
|
|
-}
|
|
-
|
|
-const char *dim_status_get_name(struct dim_status *status)
|
|
-{
|
|
- return status == NULL ? NULL :
|
|
- status->table[atomic_read(&status->status_cur)];
|
|
-}
|
|
-
|
|
-void dim_status_set(struct dim_status *status, unsigned int s)
|
|
-{
|
|
- if (status == NULL || s >= status->table_len)
|
|
- return;
|
|
-
|
|
- atomic_set(&status->status_cur, s);
|
|
-}
|
|
\ No newline at end of file
|
|
diff --git a/src/common/dim_status.h b/src/common/dim_status.h
|
|
deleted file mode 100644
|
|
index 741bcda..0000000
|
|
--- a/src/common/dim_status.h
|
|
+++ /dev/null
|
|
@@ -1,23 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#ifndef __DIM_STATUS_H
|
|
-#define __DIM_STATUS_H
|
|
-
|
|
-#include <linux/atomic.h>
|
|
-
|
|
-struct dim_status {
|
|
- const char **table;
|
|
- int table_len;
|
|
- atomic_t status_cur;
|
|
-};
|
|
-
|
|
-int dim_status_init(struct dim_status *status,
|
|
- const char **table,
|
|
- unsigned int len);
|
|
-int dim_status_get(struct dim_status *status);
|
|
-const char *dim_status_get_name(struct dim_status *status);
|
|
-void dim_status_set(struct dim_status *status, unsigned int s);
|
|
-
|
|
-#endif
|
|
\ No newline at end of file
|
|
diff --git a/src/common/dim_utils.h b/src/common/dim_utils.h
|
|
index 382721b..1db3ca1 100644
|
|
--- a/src/common/dim_utils.h
|
|
+++ b/src/common/dim_utils.h
|
|
@@ -10,11 +10,11 @@
|
|
|
|
#define DIM_ARRAY_LEN(ARR) (sizeof(ARR) / sizeof(ARR[0]))
|
|
|
|
-#define dim_fmt(fmt) DIM_MODULE ": " fmt
|
|
+#define dim_fmt(fmt) "%s: " fmt
|
|
|
|
-#define dim_err(fmt, ...) pr_err(dim_fmt(fmt), ##__VA_ARGS__)
|
|
-#define dim_warn(fmt, ...) pr_warn(dim_fmt(fmt), ##__VA_ARGS__)
|
|
-#define dim_info(fmt, ...) pr_info(dim_fmt(fmt), ##__VA_ARGS__)
|
|
+#define dim_err(fmt, ...) pr_err(dim_fmt(fmt), THIS_MODULE->name, ##__VA_ARGS__)
|
|
+#define dim_warn(fmt, ...) pr_warn(dim_fmt(fmt), THIS_MODULE->name, ##__VA_ARGS__)
|
|
+#define dim_info(fmt, ...) pr_info(dim_fmt(fmt), THIS_MODULE->name, ##__VA_ARGS__)
|
|
#define dim_devel(fmt, ...)
|
|
|
|
void *dim_kmalloc_gfp(size_t size);
|
|
diff --git a/src/core/dim_core.h b/src/core/dim_core.h
|
|
deleted file mode 100644
|
|
index c210c66..0000000
|
|
--- a/src/core/dim_core.h
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#ifndef __DIM_CORE_H
|
|
-#define __DIM_CORE_H
|
|
-
|
|
-#include "dim_utils.h"
|
|
-
|
|
-#define DIM_MODULE "dim_core"
|
|
-#define DIM_CORE_HASH_DEFAULT "sha256"
|
|
-
|
|
-#endif
|
|
diff --git a/src/core/dim_core_baseline.c b/src/core/dim_core_baseline.c
|
|
deleted file mode 100644
|
|
index 27a8114..0000000
|
|
--- a/src/core/dim_core_baseline.c
|
|
+++ /dev/null
|
|
@@ -1,115 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#include <linux/atomic.h>
|
|
-#include <linux/utsname.h>
|
|
-
|
|
-#include "dim_baseline.h"
|
|
-#include "dim_hash.h"
|
|
-#include "dim_utils.h"
|
|
-
|
|
-#include "dim_core.h"
|
|
-#include "dim_core_mem_pool.h"
|
|
-
|
|
-static struct dim_baseline_tree static_baseline = { 0 };
|
|
-static struct dim_baseline_tree dynamic_baseline = { 0 };
|
|
-
|
|
-static const char *process_static_name(const char *name, int type,
|
|
- char *buf, int buf_len)
|
|
-{
|
|
- const char *kr = init_uts_ns.name.release;
|
|
-
|
|
- if (type != DIM_BASELINE_KERNEL || strcmp(name, kr) == 0)
|
|
- return name;
|
|
-
|
|
- /* name of kernel module has a kernel prefix in static baseline */
|
|
- if (sprintf(buf, "%s/%s", kr, name) < 0)
|
|
- return NULL;
|
|
-
|
|
- return buf;
|
|
-}
|
|
-
|
|
-int dim_core_add_static_baseline(const char *name, int type,
|
|
- struct dim_digest *digest)
|
|
-{
|
|
- int ret = dim_baseline_add(&static_baseline, name, type, digest);
|
|
- if (ret < 0 && ret != -EEXIST) {
|
|
- dim_err("failed to add static baseline of %s\n", name);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int dim_core_add_dynamic_baseline(const char *name, int type,
|
|
- struct dim_digest *digest)
|
|
-{
|
|
- int ret = dim_baseline_add(&dynamic_baseline, name, type, digest);
|
|
- if (ret < 0 && ret != -EEXIST) {
|
|
- dim_err("failed to add dynamic baseline of %s\n", name);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-bool dim_core_match_static_baseline(const char *name, int type,
|
|
- struct dim_digest *digest)
|
|
-{
|
|
- char buf[NAME_MAX + NAME_MAX + 1 + 1] = { 0 };
|
|
- return dim_baseline_match(&static_baseline,
|
|
- process_static_name(name, type, buf, sizeof(buf)),
|
|
- type, digest);
|
|
-}
|
|
-
|
|
-bool dim_core_match_dynamic_baseline(const char *name, int type,
|
|
- struct dim_digest *digest)
|
|
-{
|
|
- return dim_baseline_match(&dynamic_baseline, name, type, digest);
|
|
-}
|
|
-
|
|
-int dim_core_search_static_baseline(const char *name, int type,
|
|
- struct dim_digest *digest)
|
|
-{
|
|
- char buf[NAME_MAX + NAME_MAX + 1 + 1] = { 0 };
|
|
- return dim_baseline_search_digest(&static_baseline,
|
|
- process_static_name(name, type, buf, sizeof(buf)),
|
|
- type, digest);
|
|
-}
|
|
-
|
|
-int dim_core_search_dynamic_baseline(const char *name, int type,
|
|
- struct dim_digest *digest)
|
|
-{
|
|
- return dim_baseline_search_digest(&dynamic_baseline, name,
|
|
- type, digest);
|
|
-}
|
|
-
|
|
-int dim_core_baseline_init(void)
|
|
-{
|
|
- int ret;
|
|
-
|
|
- ret = dim_baseline_init_tree(dim_kmalloc_gfp,
|
|
- dim_kfree,
|
|
- &static_baseline);
|
|
- if (ret < 0) {
|
|
- dim_err("failed to initialize static baseline root: %d\n", ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- ret = dim_baseline_init_tree(dim_mem_pool_alloc,
|
|
- dim_mem_pool_free,
|
|
- &dynamic_baseline);
|
|
- if (ret < 0) {
|
|
- dim_err("failed to initialize dynamic baseline root: %d\n", ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-void dim_core_baseline_destroy(void)
|
|
-{
|
|
- dim_baseline_destroy_tree(&static_baseline);
|
|
- dim_baseline_destroy_tree(&dynamic_baseline);
|
|
-}
|
|
diff --git a/src/core/dim_core_baseline.h b/src/core/dim_core_baseline.h
|
|
deleted file mode 100644
|
|
index e4c7282..0000000
|
|
--- a/src/core/dim_core_baseline.h
|
|
+++ /dev/null
|
|
@@ -1,25 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#ifndef __DIM_CORE_BASELINE_H
|
|
-#define __DIM_CORE_BASELINE_H
|
|
-
|
|
-#include "dim_hash.h"
|
|
-
|
|
-int dim_core_baseline_init(void);
|
|
-void dim_core_baseline_destroy(void);
|
|
-int dim_core_add_static_baseline(const char *name, int type,
|
|
- struct dim_digest *digest);
|
|
-int dim_core_add_dynamic_baseline(const char *name, int type,
|
|
- struct dim_digest *digest);
|
|
-bool dim_core_match_static_baseline(const char *name, int type,
|
|
- struct dim_digest *digest);
|
|
-bool dim_core_match_dynamic_baseline(const char *name, int type,
|
|
- struct dim_digest *digest);
|
|
-int dim_core_search_static_baseline(const char *name, int type,
|
|
- struct dim_digest *digest);
|
|
-int dim_core_search_dynamic_baseline(const char *name, int type,
|
|
- struct dim_digest *digest);
|
|
-
|
|
-#endif
|
|
diff --git a/src/core/dim_core_fs.c b/src/core/dim_core_fs.c
|
|
index e050a19..a76d622 100644
|
|
--- a/src/core/dim_core_fs.c
|
|
+++ b/src/core/dim_core_fs.c
|
|
@@ -6,26 +6,25 @@
|
|
|
|
#include "dim_utils.h"
|
|
|
|
-#include "dim_core.h"
|
|
#include "dim_core_measure.h"
|
|
-#include "dim_core_status.h"
|
|
#include "dim_core_fs.h"
|
|
|
|
/*
|
|
* measure trigger interface
|
|
* dim_entry struct: dim_measure_entry
|
|
* file entry name: measure
|
|
- * function: dim_core_measure(0)
|
|
+ * function: dim_core_measure_blocking()
|
|
*/
|
|
-dim_trigger_entry(dim_measure, measure, dim_core_measure, 0);
|
|
+dim_trigger_entry(dim_measure, measure, dim_core_measure_blocking);
|
|
|
|
/*
|
|
* baseline_init trigger interface
|
|
* dim_entry struct: dim_baseline_init_entry
|
|
* file entry name: baseline_init
|
|
- * function: dim_core_measure(1)
|
|
+ * function: dim_core_baseline_blocking(0)
|
|
*/
|
|
-dim_trigger_entry(dim_baseline_init, baseline_init, dim_core_measure, 1);
|
|
+dim_trigger_entry(dim_baseline_init, baseline_init,
|
|
+ dim_core_baseline_blocking);
|
|
|
|
/*
|
|
* measure log read interface
|
|
@@ -33,17 +32,16 @@ dim_trigger_entry(dim_baseline_init, baseline_init, dim_core_measure, 1);
|
|
* file entry name: runtime_status
|
|
* status to read: dim_measure_log_tree
|
|
*/
|
|
-dim_measure_log_entry(dim_measure_log,
|
|
- ascii_runtime_measurements,
|
|
- &dim_core_log);
|
|
+dim_measure_log_entry(dim_measure_log, ascii_runtime_measurements,
|
|
+ &dim_core_handle.log);
|
|
|
|
/*
|
|
- * status read interface
|
|
+ * status print interface
|
|
* dim_entry struct: dim_status_entry
|
|
- * file entry name: ascii_runtime_measurements
|
|
- * data to read: dim_core_status
|
|
+ * file entry name: runtime_status
|
|
+ * print function: dim_core_status_print
|
|
*/
|
|
-dim_status_entry(dim_status, runtime_status, &dim_core_status);
|
|
+dim_string_print_entry(dim_status, runtime_status, dim_core_status_print);
|
|
|
|
/*
|
|
* measure interval set and read interface
|
|
@@ -52,8 +50,7 @@ dim_status_entry(dim_status, runtime_status, &dim_core_status);
|
|
* read function: dim_core_interval_get
|
|
* write function: dim_core_interval_set
|
|
*/
|
|
-dim_uint_rw_entry(dim_interval, interval,
|
|
- dim_core_interval_get,
|
|
+dim_uint_rw_entry(dim_interval, interval, dim_core_interval_get,
|
|
dim_core_interval_set);
|
|
|
|
#ifdef DIM_CORE_TAMPERED_ACTION
|
|
@@ -64,10 +61,8 @@ dim_uint_rw_entry(dim_interval, interval,
|
|
* 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);
|
|
+dim_uint_rw_entry(dim_tampered_action, tampered_action,
|
|
+ dim_core_tampered_action_get, dim_core_tampered_action_set);
|
|
#endif
|
|
|
|
/*
|
|
diff --git a/src/core/dim_core_main.c b/src/core/dim_core_main.c
|
|
index 6de0c2a..6a0ca41 100644
|
|
--- a/src/core/dim_core_main.c
|
|
+++ b/src/core/dim_core_main.c
|
|
@@ -4,31 +4,37 @@
|
|
|
|
#include <linux/module.h>
|
|
|
|
-#include "dim_core.h"
|
|
#include "dim_core_symbol.h"
|
|
#include "dim_core_fs.h"
|
|
#include "dim_core_measure.h"
|
|
#include "dim_core_mem_pool.h"
|
|
#include "dim_core_sig.h"
|
|
|
|
-static char *measure_hash = NULL;
|
|
-bool signature = false;
|
|
+/* common measurement configuration */
|
|
+static struct dim_measure_cfg cfg = {
|
|
+ .alg_name = DIM_CORE_HASH_DEFAULT,
|
|
+ .log_cap = DIM_CORE_LOG_CAP_DEFAULT,
|
|
+};
|
|
|
|
-module_param(measure_log_capacity, uint, 0);
|
|
+module_param_named(measure_log_capacity, cfg.log_cap, uint, 0);
|
|
MODULE_PARM_DESC(measure_log_capacity, "Max number of measure log");
|
|
|
|
-module_param(measure_schedule, uint, 0);
|
|
+module_param_named(measure_schedule, cfg.schedule_ms, uint, 0);
|
|
MODULE_PARM_DESC(measure_schedule, "Schedule time (ms) for each measure object");
|
|
|
|
-module_param(measure_interval, uint, 0);
|
|
-MODULE_PARM_DESC(measure_interval, "Interval time (min) for automatic measurement");
|
|
-
|
|
-module_param(measure_hash, charp, 0);
|
|
+module_param_named(measure_hash, cfg.alg_name, charp, 0);
|
|
MODULE_PARM_DESC(measure_hash, "Hash algorithm for measurement");
|
|
|
|
-module_param(measure_pcr, uint, 0);
|
|
+module_param_named(measure_pcr, cfg.pcr, uint, 0);
|
|
MODULE_PARM_DESC(measure_pcr, "TPM PCR index to extend measure log");
|
|
|
|
+/* special measurement configuration for dim_core */
|
|
+static unsigned int measure_interval = 0;
|
|
+static bool signature = false;
|
|
+
|
|
+module_param(measure_interval, uint, 0);
|
|
+MODULE_PARM_DESC(measure_interval, "Interval time (min) for automatic measurement");
|
|
+
|
|
module_param(signature, bool, 0);
|
|
MODULE_PARM_DESC(signature, "Require signature for policy and static baseline");
|
|
|
|
@@ -56,8 +62,7 @@ static int __init dim_core_init(void)
|
|
}
|
|
}
|
|
|
|
- ret = dim_core_measure_init(measure_hash == NULL ?
|
|
- DIM_CORE_HASH_DEFAULT : measure_hash);
|
|
+ ret = dim_core_measure_init(&cfg, measure_interval);
|
|
if (ret < 0) {
|
|
dim_err("failed to initialize dim measurement: %d\n", ret);
|
|
goto err;
|
|
@@ -72,14 +77,18 @@ static int __init dim_core_init(void)
|
|
return 0;
|
|
err:
|
|
dim_core_destroy_fs();
|
|
- dim_core_destroy_measure();
|
|
+ dim_core_measure_destroy();
|
|
dim_mem_pool_destroy();
|
|
+
|
|
+ if (signature)
|
|
+ dim_core_sig_destroy();
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
static void __exit dim_core_exit(void)
|
|
{
|
|
- dim_core_destroy_measure();
|
|
+ dim_core_measure_destroy();
|
|
dim_core_destroy_fs();
|
|
dim_mem_pool_destroy();
|
|
|
|
diff --git a/src/core/dim_core_measure.c b/src/core/dim_core_measure.c
|
|
index ed4a464..0147735 100644
|
|
--- a/src/core/dim_core_measure.c
|
|
+++ b/src/core/dim_core_measure.c
|
|
@@ -2,153 +2,107 @@
|
|
* Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
*/
|
|
|
|
-#include <linux/highmem.h>
|
|
-#include <linux/seq_file.h>
|
|
-#include <linux/vmalloc.h>
|
|
+#include <linux/workqueue.h>
|
|
|
|
-#include "dim_measure_log.h"
|
|
-#include "dim_tpm.h"
|
|
-
|
|
-#include "dim_core.h"
|
|
-#include "dim_core_status.h"
|
|
#include "dim_core_policy.h"
|
|
+#include "dim_core_mem_pool.h"
|
|
#include "dim_core_static_baseline.h"
|
|
-#include "dim_core_baseline.h"
|
|
+#include "dim_core_measure_task.h"
|
|
#include "dim_core_measure.h"
|
|
|
|
-/* lock to prevent concurrent measurement */
|
|
+/* measurement tasks */
|
|
+static struct dim_measure_task *dim_core_tasks[] = {
|
|
+ &dim_core_measure_task_user_text,
|
|
+ &dim_core_measure_task_kernel_text,
|
|
+ &dim_core_measure_task_module_text,
|
|
+};
|
|
+
|
|
+/* the global measurement handle */
|
|
+struct dim_measure dim_core_handle = { 0 };
|
|
+
|
|
+/* lock to prevent trigger multiple measurement */
|
|
DEFINE_MUTEX(dim_core_measure_lock);
|
|
-/* lock to prevent concurrent baseline_init */
|
|
-DEFINE_MUTEX(dim_core_baseline_lock);
|
|
-/* lock to prevent concurrent setting interval */
|
|
-DEFINE_MUTEX(dim_core_interval_lock);
|
|
-/* lock to prevent concurrent setting tampered_action */
|
|
-DEFINE_MUTEX(dim_core_tampered_action_lock);
|
|
-/* dim work quee */
|
|
+
|
|
+/* dim measurement work */
|
|
static struct workqueue_struct *dim_work_queue = NULL;
|
|
static struct delayed_work dim_measure_work;
|
|
-/* parameters set by module commandline */
|
|
-unsigned int measure_log_capacity = 100000;
|
|
-unsigned int measure_schedule = 0;
|
|
-unsigned int measure_interval = 0;
|
|
-unsigned int measure_pcr = 0;
|
|
-bool tampered_action = false;
|
|
-
|
|
-/* time (jiffies) to set */
|
|
-unsigned long measure_schedule_jiffies = 0;
|
|
-static unsigned long measure_interval_jiffies = 0;
|
|
+static struct work_struct dim_baseline_work;
|
|
|
|
-struct dim_tpm dim_core_tpm = { 0 };
|
|
-struct dim_hash dim_core_hash = { 0 };
|
|
-struct dim_measure_log_tree dim_core_log = { 0 };
|
|
+/* special measurement parameters for dim_core */
|
|
+static atomic_t measure_interval = ATOMIC_INIT(0);
|
|
+static atomic_t tampered_action = ATOMIC_INIT(0);
|
|
|
|
-long dim_core_interval_get(void)
|
|
+/* interface to print measure status string */
|
|
+const char *dim_core_status_print(void)
|
|
{
|
|
- long p = 0;
|
|
-
|
|
- mutex_lock(&dim_core_interval_lock);
|
|
- p = measure_interval;
|
|
- mutex_unlock(&dim_core_interval_lock);
|
|
- return p;
|
|
+ return dim_measure_status_print(&dim_core_handle);
|
|
}
|
|
|
|
-unsigned long dim_core_interval_jiffies_get(void)
|
|
+/* interface to get measure interval */
|
|
+long dim_core_interval_get(void)
|
|
{
|
|
- unsigned long p = 0;
|
|
-
|
|
- mutex_lock(&dim_core_interval_lock);
|
|
- p = measure_interval_jiffies;
|
|
- mutex_unlock(&dim_core_interval_lock);
|
|
- return p;
|
|
+ return atomic_read(&measure_interval);
|
|
}
|
|
|
|
+/* interface to set measure interval */
|
|
int dim_core_interval_set(unsigned int min)
|
|
{
|
|
- unsigned long min_jiffies = 0;
|
|
+ unsigned long jiffies = 0;
|
|
|
|
if (min > DIM_INTERVAL_MAX ||
|
|
(unsigned long)min * DIM_MINUTE_TO_SEC > MAX_SEC_IN_JIFFIES)
|
|
return -ERANGE;
|
|
|
|
- min_jiffies = (min == 0) ? 0 :
|
|
- nsecs_to_jiffies64((unsigned long)min * DIM_MINUTE_TO_NSEC);
|
|
-
|
|
- mutex_lock(&dim_core_interval_lock);
|
|
- measure_interval = min;
|
|
- measure_interval_jiffies = min_jiffies;
|
|
- if (measure_interval == 0) {
|
|
+ atomic_set(&measure_interval, min);
|
|
+ if (min == 0) {
|
|
dim_info("cancel dim timed measure work");
|
|
cancel_delayed_work_sync(&dim_measure_work);
|
|
} else {
|
|
+ jiffies = nsecs_to_jiffies64((unsigned long)min *
|
|
+ DIM_MINUTE_TO_NSEC);
|
|
dim_info("modify dim measure interval to %u min "
|
|
- "(jittfies = 0x%lx)", min, min_jiffies);
|
|
- mod_delayed_work(dim_work_queue, &dim_measure_work,
|
|
- min_jiffies);
|
|
+ "(jittfies = 0x%lx)", min, jiffies);
|
|
+ mod_delayed_work(dim_work_queue, &dim_measure_work, jiffies);
|
|
}
|
|
|
|
- mutex_unlock(&dim_core_interval_lock);
|
|
return 0;
|
|
}
|
|
|
|
+/* interface to get tamper action flag */
|
|
long dim_core_tampered_action_get(void)
|
|
{
|
|
- long p = 0;
|
|
-
|
|
- mutex_lock(&dim_core_tampered_action_lock);
|
|
- p = tampered_action ? 1 : 0;
|
|
- mutex_unlock(&dim_core_tampered_action_lock);
|
|
- return p;
|
|
+ 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;
|
|
|
|
- mutex_lock(&dim_core_tampered_action_lock);
|
|
- tampered_action = !!p;
|
|
- mutex_unlock(&dim_core_tampered_action_lock);
|
|
+ atomic_set(&tampered_action, p);
|
|
return 0;
|
|
}
|
|
|
|
-static void do_measure(void)
|
|
+static int baseline_prepare(struct dim_measure *m)
|
|
{
|
|
int ret = 0;
|
|
- int bi = 0;
|
|
-
|
|
- /* dont do measure when doing baseline_init */
|
|
- if (!mutex_trylock(&dim_core_baseline_lock))
|
|
- return;
|
|
-
|
|
- bi = (dim_core_status_get() == DIM_BASELINE_RUNNING ? 1 : 0);
|
|
- dim_info("start dim measure work, baseline_init = %d\n", bi);
|
|
-
|
|
- ret = dim_core_measure_task(bi);
|
|
- if (ret < 0)
|
|
- dim_err("failed to measure user process: %d\n", ret);
|
|
-
|
|
- ret = dim_core_measure_module(bi);
|
|
- if (ret < 0)
|
|
- dim_err("failed to measure kernel modules: %d\n", ret);
|
|
-
|
|
- ret = dim_core_measure_kernel(bi);
|
|
- if (ret < 0)
|
|
- dim_err("failed to measure kernel: %d\n", ret);
|
|
-
|
|
- mutex_unlock(&dim_core_baseline_lock);
|
|
-}
|
|
|
|
-static int do_baseline(void)
|
|
-{
|
|
- int ret = 0;
|
|
+ if (m == NULL)
|
|
+ return -EINVAL;
|
|
|
|
+ /* 1. reload dim policy */
|
|
ret = dim_core_policy_load();
|
|
if (ret < 0) {
|
|
dim_err("failed to load dim core policy: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
- dim_core_baseline_destroy();
|
|
+ /* 2. clear dim baseline */
|
|
+ dim_baseline_destroy_tree(&m->static_baseline);
|
|
+ dim_baseline_destroy_tree(&m->dynamic_baseline);
|
|
+
|
|
+ /* 3. reload dim baseline */
|
|
ret = dim_core_static_baseline_load();
|
|
if (ret < 0) {
|
|
dim_err("failed to load dim static baseline: %d\n", ret);
|
|
@@ -156,21 +110,38 @@ static int do_baseline(void)
|
|
return ret;
|
|
}
|
|
|
|
- dim_measure_log_refresh(&dim_core_log);
|
|
+ /* 4. refresh measure log */
|
|
+ dim_measure_log_refresh(&m->log);
|
|
return 0;
|
|
}
|
|
|
|
-static void dim_worker_work_cb(struct work_struct *work)
|
|
+static void queue_delayed_measure_work(void)
|
|
{
|
|
- unsigned long p;
|
|
+ unsigned long jiffies = 0;
|
|
+ unsigned int interval = atomic_read(&measure_interval);
|
|
+
|
|
+ if (interval == 0)
|
|
+ return;
|
|
|
|
- do_measure();
|
|
- p = dim_core_interval_jiffies_get();
|
|
- if (p != 0)
|
|
- queue_delayed_work(dim_work_queue, &dim_measure_work, p);
|
|
+ jiffies = nsecs_to_jiffies64((unsigned long)interval *
|
|
+ DIM_MINUTE_TO_NSEC);
|
|
+ queue_delayed_work(dim_work_queue, &dim_measure_work, jiffies);
|
|
}
|
|
|
|
-int dim_core_measure(int baseline_init)
|
|
+static void measure_work_cb(struct work_struct *work)
|
|
+{
|
|
+ dim_measure_task_measure(DIM_MEASURE, &dim_core_handle);
|
|
+ queue_delayed_measure_work();
|
|
+}
|
|
+
|
|
+static void baseline_work_cb(struct work_struct *work)
|
|
+{
|
|
+ dim_measure_task_measure(DIM_BASELINE, &dim_core_handle);
|
|
+ queue_delayed_measure_work();
|
|
+}
|
|
+
|
|
+/* trigger a measurement and wait for it to complete */
|
|
+int dim_core_measure_blocking(void)
|
|
{
|
|
int ret = 0;
|
|
|
|
@@ -180,125 +151,103 @@ int dim_core_measure(int baseline_init)
|
|
/* clean the running work */
|
|
flush_delayed_work(&dim_measure_work);
|
|
cancel_delayed_work_sync(&dim_measure_work);
|
|
-
|
|
- if (dim_core_status_get() == DIM_NO_BASELINE)
|
|
- baseline_init = 1;
|
|
-
|
|
- if (baseline_init) {
|
|
- mutex_lock(&dim_core_baseline_lock);
|
|
- dim_core_status_set(DIM_BASELINE_RUNNING);
|
|
- ret = do_baseline();
|
|
- mutex_unlock(&dim_core_baseline_lock);
|
|
- if (ret < 0)
|
|
- goto out;
|
|
- } else {
|
|
- dim_core_status_set(DIM_MEASURE_RUNNING);
|
|
- }
|
|
-
|
|
+ /* queue and flush measure work */
|
|
queue_delayed_work(dim_work_queue, &dim_measure_work, 0);
|
|
flush_delayed_work(&dim_measure_work);
|
|
-out:
|
|
- dim_core_status_set(ret < 0 ? DIM_ERROR : DIM_PROTECTED);
|
|
+
|
|
+ /* check error status */
|
|
+ if (dim_measure_status_error(&dim_core_handle))
|
|
+ ret = -EFAULT;
|
|
+
|
|
mutex_unlock(&dim_core_measure_lock);
|
|
return ret;
|
|
}
|
|
|
|
-int dim_core_measure_init(const char *alg_name)
|
|
+/* trigger a dynamic baseline and wait for it to complete */
|
|
+int dim_core_baseline_blocking(void)
|
|
{
|
|
int ret = 0;
|
|
|
|
- /* 1. check the measure parameter */
|
|
- if (measure_log_capacity < MEASURE_LOG_CAP_MIN ||
|
|
- measure_log_capacity > MEASURE_LOG_CAP_MAX) {
|
|
- dim_err("invalid measure_log_capacity parameter\n");
|
|
- return -ERANGE;
|
|
- }
|
|
+ if (!mutex_trylock(&dim_core_measure_lock))
|
|
+ return -EBUSY;
|
|
|
|
- if (measure_schedule > MEASURE_SCHEDULE_MAX) {
|
|
- dim_err("invalid measure_schedule parameter\n");
|
|
- return -ERANGE;
|
|
- }
|
|
+ /* clean the running work */
|
|
+ flush_delayed_work(&dim_measure_work);
|
|
+ cancel_delayed_work_sync(&dim_measure_work);
|
|
|
|
- if (measure_interval > DIM_INTERVAL_MAX) {
|
|
- dim_err("invalid measure_interval parameter\n");
|
|
- return -ERANGE;
|
|
- }
|
|
+ /* queue and flush baseline work */
|
|
+ queue_work(dim_work_queue, &dim_baseline_work);
|
|
+ flush_work(&dim_baseline_work);
|
|
|
|
- if (measure_pcr > DIM_PCR_MAX) {
|
|
- dim_err("invalid measure_pcr parameter\n");
|
|
- return -ERANGE;
|
|
- }
|
|
+ /* check error status */
|
|
+ if (dim_measure_status_error(&dim_core_handle))
|
|
+ ret = -EFAULT;
|
|
|
|
- /* 2. init measure hash algorithm */
|
|
- ret = dim_hash_init(alg_name, &dim_core_hash);
|
|
- if (ret < 0) {
|
|
- dim_err("failed to initialize hash algorithm: %d\n", ret);
|
|
- goto err;
|
|
- }
|
|
+ mutex_unlock(&dim_core_measure_lock);
|
|
+ return ret;
|
|
+}
|
|
|
|
- /* 3. init TPM, dont break if init fail */
|
|
- if (measure_pcr > 0) {
|
|
- ret = dim_tpm_init(&dim_core_tpm, HASH_ALGO_SHA256);
|
|
- if (ret < 0)
|
|
- dim_warn("failed to initialize tpm chip: %d\n", ret);
|
|
- }
|
|
+int dim_core_measure_init(struct dim_measure_cfg *cfg, unsigned int interval)
|
|
+{
|
|
+ int ret = 0;
|
|
|
|
- /* 4. init measurement status */
|
|
- ret = dim_core_status_init();
|
|
- if (ret < 0) {
|
|
- dim_err("failed to initialize dim status: %d\n", ret);
|
|
- goto err;
|
|
- }
|
|
+ /* set the special baseline memory functions */
|
|
+ cfg->dyn_malloc = dim_mem_pool_alloc;
|
|
+ cfg->dyn_free = dim_mem_pool_free;
|
|
|
|
- /* 5. init baseline data (static and dynamic) */
|
|
- ret = dim_core_baseline_init();
|
|
+ /* init the measurement handle */
|
|
+ ret = dim_measure_init(&dim_core_handle, cfg);
|
|
if (ret < 0) {
|
|
- dim_err("failed to initialize dim baseline: %d\n", ret);
|
|
- goto err;
|
|
+ dim_err("failed to init measurement handle\n");
|
|
+ return ret;
|
|
}
|
|
|
|
- /* 6. init measure log */
|
|
- ret = dim_measure_log_init_tree(&dim_core_log,
|
|
- &dim_core_hash, &dim_core_tpm,
|
|
- measure_log_capacity, measure_pcr);
|
|
+ /* set the baseline prepare function */
|
|
+ dim_core_handle.baseline_prepare = baseline_prepare;
|
|
+
|
|
+ /* register all measurement tasks */
|
|
+ ret = dim_measure_tasks_register(&dim_core_handle, dim_core_tasks,
|
|
+ DIM_ARRAY_LEN(dim_core_tasks));
|
|
if (ret < 0) {
|
|
- dim_err("failed to initialize measure log root: %d\n", ret);
|
|
+ dim_err("failed to register measure tasks: %d\n", ret);
|
|
goto err;
|
|
}
|
|
|
|
- /* 7. init measure work thread */
|
|
- INIT_DELAYED_WORK(&dim_measure_work, dim_worker_work_cb);
|
|
+ /* init the measurement working thread */
|
|
dim_work_queue = create_singlethread_workqueue("dim_core");
|
|
if (dim_work_queue == NULL) {
|
|
ret = -ENOMEM;
|
|
dim_err("failed to create dim work queue: %d\n", ret);
|
|
goto err;
|
|
}
|
|
-
|
|
- /* 8. if the interval is set, start to do baseline and measure */
|
|
- if (measure_interval) {
|
|
- ret = dim_core_measure(1);
|
|
+
|
|
+ /* init the measurement work */
|
|
+ INIT_WORK(&dim_baseline_work, baseline_work_cb);
|
|
+ INIT_DELAYED_WORK(&dim_measure_work, measure_work_cb);
|
|
+
|
|
+ /* if the interval is set, start to do baseline and measure */
|
|
+ if (interval) {
|
|
+ ret = dim_core_baseline_blocking();
|
|
if (ret < 0) {
|
|
dim_err("failed to do baseline init: %d\n", ret);
|
|
goto err;
|
|
}
|
|
|
|
- dim_core_interval_set(measure_interval);
|
|
+ ret = dim_core_interval_set(interval);
|
|
+ if (ret < 0)
|
|
+ dim_warn("failed to set measure interval: %d\n", ret);
|
|
}
|
|
|
|
- if (measure_schedule)
|
|
- measure_schedule_jiffies = msecs_to_jiffies(measure_schedule);
|
|
-
|
|
return 0;
|
|
err:
|
|
- dim_hash_destroy(&dim_core_hash);
|
|
- dim_tpm_destroy(&dim_core_tpm);
|
|
- dim_core_baseline_destroy();
|
|
- dim_measure_log_destroy_tree(&dim_core_log);
|
|
+ dim_measure_destroy(&dim_core_handle);
|
|
+ if (dim_work_queue != NULL)
|
|
+ destroy_workqueue(dim_work_queue);
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
-void dim_core_destroy_measure(void)
|
|
+void dim_core_measure_destroy(void)
|
|
{
|
|
mutex_lock(&dim_core_measure_lock);
|
|
if (dim_work_queue != NULL) {
|
|
@@ -309,9 +258,7 @@ void dim_core_destroy_measure(void)
|
|
destroy_workqueue(dim_work_queue);
|
|
}
|
|
|
|
- dim_measure_log_destroy_tree(&dim_core_log);
|
|
- dim_core_baseline_destroy();
|
|
+ dim_measure_destroy(&dim_core_handle);
|
|
dim_core_policy_destroy();
|
|
- dim_tpm_destroy(&dim_core_tpm);
|
|
- dim_hash_destroy(&dim_core_hash);
|
|
-}
|
|
+ mutex_unlock(&dim_core_measure_lock);
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/src/core/dim_core_measure.h b/src/core/dim_core_measure.h
|
|
index a379cf6..699724a 100644
|
|
--- a/src/core/dim_core_measure.h
|
|
+++ b/src/core/dim_core_measure.h
|
|
@@ -5,75 +5,32 @@
|
|
#ifndef __DIM_CORE_MEASURE_H
|
|
#define __DIM_CORE_MEASURE_H
|
|
|
|
-#include "dim_hash.h"
|
|
+#include "dim_measure.h"
|
|
+
|
|
+/* default configuration */
|
|
+#define DIM_CORE_HASH_DEFAULT "sha256"
|
|
+#define DIM_CORE_LOG_CAP_DEFAULT 100000
|
|
|
|
/* max measure interval = 1 year */
|
|
#define DIM_INTERVAL_MAX (365 * 24 * 60)
|
|
#define DIM_MINUTE_TO_SEC (60UL)
|
|
#define DIM_MINUTE_TO_NSEC (60UL * 1000 * 1000 * 1000)
|
|
-/* max number of kill tasks */
|
|
-#define DIM_KILL_TASKS_MAX (1024)
|
|
-/* limit of measure parameter */
|
|
-#define MEASURE_LOG_CAP_MAX (UINT_MAX)
|
|
-#define MEASURE_LOG_CAP_MIN (100)
|
|
-#define MEASURE_SCHEDULE_MAX (1000)
|
|
-/* max size of x86 */
|
|
-#define DIM_JUMP_LABEL_NOP_SIZE_MAX 5
|
|
-
|
|
-struct vm_text_area {
|
|
- struct mm_struct *mm;
|
|
- struct vm_area_struct *vma_start;
|
|
- struct vm_area_struct *vma_end;
|
|
-};
|
|
-
|
|
-struct task_measure_ctx {
|
|
- int baseline; /* measure or baseline init */
|
|
- char path_buf[PATH_MAX];
|
|
- const char *path;
|
|
- struct task_struct *task; /* current measured task */
|
|
- bool task_kill;
|
|
- bool task_measure;
|
|
-};
|
|
|
|
-struct task_kill_ctx {
|
|
- struct task_struct **buf;
|
|
- int len;
|
|
- int size;
|
|
- int ret;
|
|
-};
|
|
+extern struct dim_measure dim_core_handle;
|
|
|
|
-typedef int (*task_measurer)(struct task_struct *, struct task_measure_ctx *);
|
|
+/* global init and destroy */
|
|
+int dim_core_measure_init(struct dim_measure_cfg *cfg, unsigned int interval);
|
|
+void dim_core_measure_destroy(void);
|
|
|
|
-extern struct dim_hash dim_core_hash;
|
|
-extern struct dim_measure_log_tree dim_core_log;
|
|
-extern struct dim_tpm dim_core_tpm;
|
|
-extern unsigned int measure_log_capacity;
|
|
-extern unsigned int measure_schedule;
|
|
-extern unsigned int measure_interval;
|
|
-extern unsigned int measure_pcr;
|
|
-extern unsigned long measure_schedule_jiffies;
|
|
-
|
|
-int dim_core_measure_init(const char *alg_name);
|
|
-void dim_core_destroy_measure(void);
|
|
-int dim_core_measure(int baseline_init);
|
|
+/* control function for measurement parameters */
|
|
+const char *dim_core_status_print(void);
|
|
long dim_core_interval_get(void);
|
|
int dim_core_interval_set(unsigned int p);
|
|
long dim_core_tampered_action_get(void);
|
|
int dim_core_tampered_action_set(unsigned int p);
|
|
|
|
-int dim_core_measure_kernel(int baseline_init);
|
|
-int dim_core_measure_module(int baseline_init);
|
|
-int dim_core_measure_task(int baseline_init);
|
|
-
|
|
-int dim_core_add_measure_log(const char *name,
|
|
- struct dim_digest *digest,
|
|
- int flag);
|
|
-int dim_core_check_kernel_digest(int baseline_init,
|
|
- const char *name,
|
|
- struct dim_digest *digest);
|
|
-int dim_core_check_user_digest(int baseline_init,
|
|
- const char *name,
|
|
- struct dim_digest *digest,
|
|
- int *log_flag);
|
|
+/* measurement trigger functions */
|
|
+int dim_core_measure_blocking(void);
|
|
+int dim_core_baseline_blocking(void);
|
|
|
|
-#endif
|
|
+#endif
|
|
\ No newline at end of file
|
|
diff --git a/src/core/dim_core_measure_common.c b/src/core/dim_core_measure_common.c
|
|
deleted file mode 100644
|
|
index 406ed3f..0000000
|
|
--- a/src/core/dim_core_measure_common.c
|
|
+++ /dev/null
|
|
@@ -1,87 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#include "dim_hash.h"
|
|
-#include "dim_tpm.h"
|
|
-#include "dim_measure_log.h"
|
|
-#include "dim_baseline.h"
|
|
-
|
|
-#include "dim_core.h"
|
|
-#include "dim_core_measure.h"
|
|
-#include "dim_core_baseline.h"
|
|
-
|
|
-int dim_core_add_measure_log(const char *name, struct dim_digest *digest, int flag)
|
|
-{
|
|
- int ret = dim_measure_log_add(&dim_core_log, name, digest, flag);
|
|
- if (ret < 0 && ret != -EEXIST) {
|
|
- dim_err("failed to add measure log of %s: %d\n", name, ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int dim_core_check_kernel_digest(int baseline_init,
|
|
- const char *name,
|
|
- struct dim_digest *digest)
|
|
-{
|
|
- int ret = 0;
|
|
- struct dim_digest digest_static = { 0 };
|
|
-
|
|
- /* in the measure stage, do nothing if baseline matched */
|
|
- if (!baseline_init &&
|
|
- !dim_core_match_dynamic_baseline(name, DIM_BASELINE_KERNEL, digest)) {
|
|
- dim_err("mismatch dynamic baseline of kernel %s\n", name);
|
|
- return dim_core_add_measure_log(name, digest, LOG_TAMPERED);
|
|
- }
|
|
-
|
|
- /* in the baseline init stage */
|
|
- /* 1. add digest to dynamic baseline */
|
|
- ret = dim_core_add_dynamic_baseline(name, DIM_BASELINE_KERNEL, digest);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- /* 2. search digest from static baseline */
|
|
- ret = dim_core_search_static_baseline(name, DIM_BASELINE_KERNEL, &digest_static);
|
|
- if (ret < 0)
|
|
- /* 2.1. if not find, log the dynamic baseline */
|
|
- return dim_core_add_measure_log(name, digest, LOG_NO_SATIC_BASELINE);
|
|
-
|
|
- /* 2.2. if find, log the static baseline */
|
|
- return dim_core_add_measure_log(name, &digest_static, LOG_STATIC_BASELINE);
|
|
-}
|
|
-
|
|
-int dim_core_check_user_digest(int baseline_init,
|
|
- const char *name,
|
|
- struct dim_digest *digest,
|
|
- int *log_flag)
|
|
-{
|
|
- int ret = 0;
|
|
- struct dim_digest digest_static = { 0 };
|
|
-
|
|
- /* in the measure stage, do nothing if baseline matched */
|
|
- if (!baseline_init &&
|
|
- !dim_core_match_dynamic_baseline(name, DIM_BASELINE_USER, digest)) {
|
|
- dim_warn("mismatch dynamic baseline of user process %s\n", name);
|
|
- return dim_core_add_measure_log(name, digest, LOG_TAMPERED);
|
|
- }
|
|
-
|
|
- /* in the baseline init stage */
|
|
- /* 1. add digest to dynamic baseline */
|
|
- ret = dim_core_add_dynamic_baseline(name, DIM_BASELINE_USER, digest);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- /* 2. search digest from static baseline */
|
|
- ret = dim_core_search_static_baseline(name, DIM_BASELINE_USER, &digest_static);
|
|
- if (ret < 0) /* 2.1. if not find, log the dynamic baseline */
|
|
- return dim_core_add_measure_log(name, digest, LOG_NO_SATIC_BASELINE);
|
|
-
|
|
- /* 2.2. if find, compare with the static baseline */
|
|
- if (dim_core_match_static_baseline(name, DIM_BASELINE_USER, digest))
|
|
- return dim_core_add_measure_log(name, digest, LOG_STATIC_BASELINE);
|
|
-
|
|
- dim_warn("mismatch static baseline of user process %s\n", name);
|
|
- return dim_core_add_measure_log(name, digest, LOG_TAMPERED);
|
|
-}
|
|
diff --git a/src/core/dim_core_mem_pool.c b/src/core/dim_core_mem_pool.c
|
|
index a16b7bb..160f819 100644
|
|
--- a/src/core/dim_core_mem_pool.c
|
|
+++ b/src/core/dim_core_mem_pool.c
|
|
@@ -4,7 +4,8 @@
|
|
|
|
#include <linux/mm.h>
|
|
|
|
-#include "dim_core.h"
|
|
+#include "dim_utils.h"
|
|
+
|
|
#include "dim_core_mem_pool.h"
|
|
|
|
static struct gen_pool *dim_pool = NULL;
|
|
diff --git a/src/core/dim_core_policy.c b/src/core/dim_core_policy.c
|
|
index 0e7fbf3..50ebcf7 100644
|
|
--- a/src/core/dim_core_policy.c
|
|
+++ b/src/core/dim_core_policy.c
|
|
@@ -14,7 +14,6 @@
|
|
#include "dim_utils.h"
|
|
#include "dim_rb.h"
|
|
|
|
-#include "dim_core.h"
|
|
#include "dim_core_sig.h"
|
|
#include "dim_core_policy.h"
|
|
|
|
@@ -67,7 +66,7 @@ static int policy_add(int obj, int key, const char *val, int action)
|
|
int ret = 0;
|
|
struct dim_policy *policy = NULL;
|
|
|
|
- policy = kmalloc(sizeof(struct dim_policy), GFP_KERNEL);
|
|
+ policy = dim_kmalloc_gfp(sizeof(struct dim_policy));
|
|
if (policy == NULL)
|
|
return -ENOMEM;
|
|
|
|
@@ -112,7 +111,7 @@ static int policy_add_path(const char *path, int action)
|
|
return ret;
|
|
|
|
/* Try to get the absolute path */
|
|
- path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
|
|
+ path_buf = dim_kmalloc_gfp(PATH_MAX);
|
|
if (path_buf == NULL)
|
|
return -ENOMEM;
|
|
|
|
diff --git a/src/core/dim_core_policy.h b/src/core/dim_core_policy.h
|
|
index 48c6f41..2baab12 100644
|
|
--- a/src/core/dim_core_policy.h
|
|
+++ b/src/core/dim_core_policy.h
|
|
@@ -5,6 +5,8 @@
|
|
#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
|
|
|
|
diff --git a/src/core/dim_core_sig.c b/src/core/dim_core_sig.c
|
|
index aae323c..70a3469 100644
|
|
--- a/src/core/dim_core_sig.c
|
|
+++ b/src/core/dim_core_sig.c
|
|
@@ -14,7 +14,6 @@
|
|
#include "dim_hash.h"
|
|
#include "dim_utils.h"
|
|
|
|
-#include "dim_core.h"
|
|
#include "dim_core_sig.h"
|
|
|
|
static struct key *dim_core_keyring = NULL;
|
|
@@ -27,7 +26,7 @@ static char *add_suffix(const char *str, const char *suffix)
|
|
char *buf = NULL;
|
|
|
|
len = strlen(str) + strlen(suffix) + 1;
|
|
- buf = kmalloc(len, GFP_KERNEL);
|
|
+ buf = dim_kmalloc_gfp(len);
|
|
if (buf == NULL)
|
|
return NULL;
|
|
|
|
diff --git a/src/core/dim_core_static_baseline.c b/src/core/dim_core_static_baseline.c
|
|
index 0d99f7b..f23dbce 100644
|
|
--- a/src/core/dim_core_static_baseline.c
|
|
+++ b/src/core/dim_core_static_baseline.c
|
|
@@ -17,10 +17,9 @@
|
|
#include "dim_hash.h"
|
|
#include "dim_baseline.h"
|
|
|
|
-#include "dim_core.h"
|
|
#include "dim_core_sig.h"
|
|
#include "dim_core_policy.h"
|
|
-#include "dim_core_baseline.h"
|
|
+#include "dim_core_measure.h"
|
|
#include "dim_core_static_baseline.h"
|
|
|
|
static bool match_policy(const char *name, int type)
|
|
@@ -110,7 +109,8 @@ static int parse_simple_baseline_line(char* line, int line_no)
|
|
if (!match_policy(line_str, type))
|
|
return 0;
|
|
|
|
- ret = dim_core_add_static_baseline(line_str, type, &digest);
|
|
+ ret = dim_measure_static_baseline_add(&dim_core_handle, line_str,
|
|
+ type, &digest);
|
|
if (ret < 0)
|
|
dim_warn("failed to add static baseline at line %d: %d\n",
|
|
line_no, ret);
|
|
@@ -128,11 +128,11 @@ static int
|
|
static bool
|
|
#endif
|
|
static_baseline_load(struct dir_context *__ctx,
|
|
- const char *name,
|
|
- int name_len,
|
|
- loff_t offset,
|
|
- unsigned long long ino,
|
|
- unsigned d_type)
|
|
+ const char *name,
|
|
+ int name_len,
|
|
+ loff_t offset,
|
|
+ unsigned long long ino,
|
|
+ unsigned d_type)
|
|
{
|
|
struct readdir_ctx *ctx = container_of(__ctx, typeof(*ctx), ctx);
|
|
int ret;
|
|
diff --git a/src/core/dim_core_static_baseline.h b/src/core/dim_core_static_baseline.h
|
|
index bec37d6..af4d1f9 100644
|
|
--- a/src/core/dim_core_static_baseline.h
|
|
+++ b/src/core/dim_core_static_baseline.h
|
|
@@ -5,6 +5,8 @@
|
|
#ifndef __DIM_CORE_STATIC_BASELINE_H
|
|
#define __DIM_CORE_STATIC_BASELINE_H
|
|
|
|
+#include "dim_measure.h"
|
|
+
|
|
#define DIM_STATIC_BASELINE_ROOT "/etc/dim/digest_list"
|
|
#define DIM_STATIC_BASELINE_LINE_MAX 10000
|
|
|
|
diff --git a/src/core/dim_core_status.c b/src/core/dim_core_status.c
|
|
deleted file mode 100644
|
|
index 3b8c08a..0000000
|
|
--- a/src/core/dim_core_status.c
|
|
+++ /dev/null
|
|
@@ -1,42 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#include "dim_status.h"
|
|
-
|
|
-#include "dim_core.h"
|
|
-#include "dim_core_status.h"
|
|
-
|
|
-static const char* dim_core_status_name[DIM_STATUS_LAST] = {
|
|
- [DIM_OFF] = "DIM_OFF",
|
|
- [DIM_NO_BASELINE] = "DIM_NO_BASELINE",
|
|
- [DIM_BASELINE_RUNNING] = "DIM_BASELINE_RUNNING",
|
|
- [DIM_MEASURE_RUNNING] = "DIM_MEASURE_RUNNING",
|
|
- [DIM_PROTECTED] = "DIM_PROTECTED",
|
|
- [DIM_ERROR] = "DIM_ERROR",
|
|
-};
|
|
-
|
|
-struct dim_status dim_core_status = { 0 };
|
|
-
|
|
-int dim_core_status_init(void)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- ret = dim_status_init(&dim_core_status, dim_core_status_name,
|
|
- DIM_STATUS_LAST);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- dim_status_set(&dim_core_status, DIM_NO_BASELINE);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-void dim_core_status_set(unsigned int status)
|
|
-{
|
|
- dim_status_set(&dim_core_status, status);
|
|
-}
|
|
-
|
|
-int dim_core_status_get(void)
|
|
-{
|
|
- return dim_status_get(&dim_core_status);
|
|
-}
|
|
diff --git a/src/core/dim_core_status.h b/src/core/dim_core_status.h
|
|
deleted file mode 100644
|
|
index 64b1e94..0000000
|
|
--- a/src/core/dim_core_status.h
|
|
+++ /dev/null
|
|
@@ -1,24 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
- */
|
|
-
|
|
-#ifndef __DIM_CORE_STATUS_H
|
|
-#define __DIM_CORE_STATUS_H
|
|
-
|
|
-enum dim_core_status {
|
|
- DIM_OFF,
|
|
- DIM_NO_BASELINE,
|
|
- DIM_BASELINE_RUNNING,
|
|
- DIM_MEASURE_RUNNING,
|
|
- DIM_PROTECTED,
|
|
- DIM_ERROR,
|
|
- DIM_STATUS_LAST,
|
|
-};
|
|
-
|
|
-extern struct dim_status dim_core_status;
|
|
-
|
|
-int dim_core_status_init(void);
|
|
-void dim_core_status_set(unsigned int status);
|
|
-int dim_core_status_get(void);
|
|
-
|
|
-#endif
|
|
diff --git a/src/core/dim_core_symbol.c b/src/core/dim_core_symbol.c
|
|
index 3da3df2..eeb9240 100644
|
|
--- a/src/core/dim_core_symbol.c
|
|
+++ b/src/core/dim_core_symbol.c
|
|
@@ -6,8 +6,8 @@
|
|
#include <linux/jump_label.h>
|
|
|
|
#include "dim_symbol.h"
|
|
+#include "dim_utils.h"
|
|
|
|
-#include "dim_core.h"
|
|
#include "dim_core_symbol.h"
|
|
|
|
struct dim_core_kallsyms dim_core_kernel_symbol;
|
|
diff --git a/src/core/dim_core_measure_kernel.c b/src/core/measure_task/dim_core_measure_kernel.c
|
|
similarity index 79%
|
|
rename from src/core/dim_core_measure_kernel.c
|
|
rename to src/core/measure_task/dim_core_measure_kernel.c
|
|
index 3724501..e13e177 100644
|
|
--- a/src/core/dim_core_measure_kernel.c
|
|
+++ b/src/core/measure_task/dim_core_measure_kernel.c
|
|
@@ -8,14 +8,17 @@
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/utsname.h>
|
|
|
|
-#include "dim_hash.h"
|
|
-#include "dim_measure_log.h"
|
|
+#include "dim_measure.h"
|
|
|
|
-#include "dim_core.h"
|
|
#include "dim_core_symbol.h"
|
|
#include "dim_core_measure.h"
|
|
#include "dim_core_policy.h"
|
|
|
|
+#include "dim_core_measure_task.h"
|
|
+
|
|
+/* max size of x86 */
|
|
+#define DIM_JUMP_LABEL_NOP_SIZE_MAX 5
|
|
+
|
|
static int code_cmp(const void *a, const void *b)
|
|
{
|
|
return *(unsigned long *)a - *(unsigned long *)b;
|
|
@@ -46,15 +49,19 @@ static int do_calc_kernel_digest(uintptr_t saddr,
|
|
uintptr_t eaddr,
|
|
uintptr_t *jcode_sort,
|
|
unsigned int jcode_cnt,
|
|
+ struct dim_hash *hash,
|
|
struct dim_digest *digest)
|
|
{
|
|
int ret = 0;
|
|
unsigned int i;
|
|
uintptr_t jump_code;
|
|
uintptr_t cur_addr = saddr;
|
|
- SHASH_DESC_ON_STACK(shash, dim_core_hash.tfm);
|
|
+ SHASH_DESC_ON_STACK(shash, hash->tfm);
|
|
+
|
|
+ shash->tfm = hash->tfm;
|
|
+ if (shash->tfm == NULL)
|
|
+ return -EINVAL;
|
|
|
|
- shash->tfm = dim_core_hash.tfm;
|
|
ret = crypto_shash_init(shash);
|
|
if (ret < 0)
|
|
return ret;
|
|
@@ -92,7 +99,7 @@ static int do_calc_kernel_digest(uintptr_t saddr,
|
|
return crypto_shash_final(shash, digest->data);
|
|
}
|
|
|
|
-static int calc_kernel_digest(struct dim_digest *digest)
|
|
+static int calc_kernel_digest(struct dim_hash *hash, struct dim_digest *digest)
|
|
{
|
|
int ret = 0;
|
|
uintptr_t stext = 0;
|
|
@@ -119,7 +126,8 @@ static int calc_kernel_digest(struct dim_digest *digest)
|
|
jcode_cnt = 0;
|
|
}
|
|
|
|
- ret = do_calc_kernel_digest(stext, etext, jcode_sort, jcode_cnt, digest);
|
|
+ ret = do_calc_kernel_digest(stext, etext, jcode_sort,
|
|
+ jcode_cnt, hash, digest);
|
|
if (ret < 0)
|
|
dim_err("failed to calculate kernel digest: %d\n", ret);
|
|
|
|
@@ -127,25 +135,35 @@ static int calc_kernel_digest(struct dim_digest *digest)
|
|
return ret;
|
|
}
|
|
|
|
-int dim_core_measure_kernel(int baseline_init)
|
|
+static int kernel_text_measure(int mode, struct dim_measure *m)
|
|
{
|
|
int ret = 0;
|
|
const char *kr = init_uts_ns.name.release;
|
|
- struct dim_digest digest = { .algo = dim_core_hash.algo };
|
|
+ struct dim_digest digest = {
|
|
+ .algo = m->hash.algo,
|
|
+ };
|
|
+
|
|
+ if (m == NULL)
|
|
+ return -EINVAL;
|
|
|
|
if (!dim_core_policy_match(DIM_POLICY_OBJ_KERNEL_TEXT,
|
|
DIM_POLICY_KEY_NAME, kr))
|
|
return 0;
|
|
|
|
- ret = calc_kernel_digest(&digest);
|
|
+ ret = calc_kernel_digest(&m->hash, &digest);
|
|
if (ret < 0) {
|
|
dim_err("failed to calculate kernel digest: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
- ret = dim_core_check_kernel_digest(baseline_init, kr, &digest);
|
|
+ ret = dim_measure_process_dynamic_result(m, mode, kr, &digest, NULL);
|
|
if (ret < 0)
|
|
dim_err("failed to check kernel digest: %d\n", ret);
|
|
|
|
return ret;
|
|
}
|
|
+
|
|
+struct dim_measure_task dim_core_measure_task_kernel_text = {
|
|
+ .name = "dim_core_measure_task_kernel_text",
|
|
+ .measure = kernel_text_measure,
|
|
+};
|
|
diff --git a/src/core/dim_core_measure_module.c b/src/core/measure_task/dim_core_measure_module.c
|
|
similarity index 64%
|
|
rename from src/core/dim_core_measure_module.c
|
|
rename to src/core/measure_task/dim_core_measure_module.c
|
|
index 4c4726e..497d3a4 100644
|
|
--- a/src/core/dim_core_measure_module.c
|
|
+++ b/src/core/measure_task/dim_core_measure_module.c
|
|
@@ -10,13 +10,19 @@
|
|
#include "dim_baseline.h"
|
|
#include "dim_measure_log.h"
|
|
|
|
-#include "dim_core.h"
|
|
#include "dim_core_measure.h"
|
|
-#include "dim_core_baseline.h"
|
|
#include "dim_core_policy.h"
|
|
#include "dim_core_symbol.h"
|
|
|
|
+#include "dim_core_measure_task.h"
|
|
+
|
|
+struct module_text_measure_ctx {
|
|
+ struct dim_measure *m;
|
|
+ int mode;
|
|
+};
|
|
+
|
|
static int calculate_module_digest(const char *name,
|
|
+ struct dim_hash *hash,
|
|
struct dim_digest *digest)
|
|
{
|
|
int ret = 0;
|
|
@@ -44,11 +50,11 @@ static int calculate_module_digest(const char *name,
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
ret = dim_hash_calculate(mod->core_layout.base,
|
|
mod->core_layout.text_size,
|
|
- &dim_core_hash, digest);
|
|
+ hash, digest);
|
|
#else
|
|
ret = dim_hash_calculate(mod->mem[MOD_TEXT].base,
|
|
mod->mem[MOD_TEXT].size,
|
|
- &dim_core_hash, digest);
|
|
+ hash, digest);
|
|
#endif
|
|
module_put(mod);
|
|
return ret;
|
|
@@ -57,7 +63,7 @@ static int calculate_module_digest(const char *name,
|
|
static int measure_module(struct dim_policy *policy, void *data)
|
|
{
|
|
int ret = 0;
|
|
- int baseline_init = *(int *)data;
|
|
+ struct module_text_measure_ctx *ctx = data;
|
|
const char *mod_name = policy->val;
|
|
struct dim_digest digest = { 0 };
|
|
|
|
@@ -66,27 +72,41 @@ static int measure_module(struct dim_policy *policy, void *data)
|
|
return 0;
|
|
|
|
/* if module is not inserted in baseline_init stage, ignore it */
|
|
- if (!baseline_init &&
|
|
- dim_core_search_dynamic_baseline(mod_name, DIM_BASELINE_KERNEL,
|
|
- &digest) < 0)
|
|
+ if (ctx->mode == DIM_MEASURE &&
|
|
+ dim_measure_dynamic_baseline_search(ctx->m, mod_name,
|
|
+ DIM_BASELINE_KERNEL, &digest) < 0)
|
|
return 0;
|
|
|
|
- digest.algo = dim_core_hash.algo;
|
|
- ret = calculate_module_digest(mod_name, &digest);
|
|
+ digest.algo = ctx->m->hash.algo;
|
|
+ ret = calculate_module_digest(mod_name, &ctx->m->hash, &digest);
|
|
if (ret < 0) {
|
|
dim_err("fail to calculate digest of module %s: %d\n",
|
|
mod_name, ret);
|
|
return ret == -ENOENT ? 0 : ret;
|
|
}
|
|
|
|
- ret = dim_core_check_kernel_digest(baseline_init, mod_name, &digest);
|
|
+ ret = dim_measure_process_dynamic_result(ctx->m, ctx->mode,
|
|
+ mod_name, &digest, NULL);
|
|
if (ret < 0)
|
|
- dim_err("fail to check kernel digest: %d\n", ret);
|
|
+ dim_err("failed to check module digest: %d\n", ret);
|
|
|
|
return 0;
|
|
}
|
|
|
|
-int dim_core_measure_module(int baseline_init)
|
|
+static int module_text_measure(int mode, struct dim_measure *m)
|
|
{
|
|
- return dim_core_policy_walk(measure_module, &baseline_init);
|
|
+ struct module_text_measure_ctx ctx = {
|
|
+ .m = m,
|
|
+ .mode = mode,
|
|
+ };
|
|
+
|
|
+ if (m == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return dim_core_policy_walk(measure_module, &ctx);
|
|
}
|
|
+
|
|
+struct dim_measure_task dim_core_measure_task_module_text = {
|
|
+ .name = "dim_core_measure_task_module_text",
|
|
+ .measure = module_text_measure,
|
|
+};
|
|
diff --git a/src/core/dim_core_measure_task.c b/src/core/measure_task/dim_core_measure_task.c
|
|
similarity index 88%
|
|
rename from src/core/dim_core_measure_task.c
|
|
rename to src/core/measure_task/dim_core_measure_task.c
|
|
index 6ab60d1..f240ddc 100644
|
|
--- a/src/core/dim_core_measure_task.c
|
|
+++ b/src/core/measure_task/dim_core_measure_task.c
|
|
@@ -16,11 +16,39 @@
|
|
#include "dim_measure_log.h"
|
|
#include "dim_baseline.h"
|
|
|
|
-#include "dim_core.h"
|
|
#include "dim_core_symbol.h"
|
|
#include "dim_core_policy.h"
|
|
#include "dim_core_measure.h"
|
|
-#include "dim_core_baseline.h"
|
|
+
|
|
+#include "dim_core_measure_task.h"
|
|
+
|
|
+/* max number of kill tasks */
|
|
+#define DIM_KILL_TASKS_MAX (1024)
|
|
+
|
|
+struct vm_text_area {
|
|
+ struct mm_struct *mm;
|
|
+ struct vm_area_struct *vma_start;
|
|
+ struct vm_area_struct *vma_end;
|
|
+};
|
|
+
|
|
+struct task_measure_ctx {
|
|
+ struct dim_measure *m;
|
|
+ int mode;
|
|
+ char path_buf[PATH_MAX];
|
|
+ const char *path;
|
|
+ struct task_struct *task; /* current measured task */
|
|
+ bool task_kill;
|
|
+ bool task_measure;
|
|
+};
|
|
+
|
|
+struct task_kill_ctx {
|
|
+ struct task_struct **buf;
|
|
+ int len;
|
|
+ int size;
|
|
+ int ret;
|
|
+};
|
|
+
|
|
+typedef int (*task_measurer)(struct task_struct *, struct task_measure_ctx *);
|
|
|
|
static struct file *get_vm_file(struct vm_area_struct *vma)
|
|
{
|
|
@@ -167,7 +195,7 @@ static int kill_task_tree(struct task_struct *tsk)
|
|
const int def_size = 32;
|
|
struct task_kill_ctx ctx = { .size = def_size };
|
|
|
|
- ctx.buf = kmalloc(def_size * sizeof(struct task_struct *), GFP_KERNEL);
|
|
+ ctx.buf = dim_kmalloc_gfp(def_size * sizeof(struct task_struct *));
|
|
if (ctx.buf == NULL)
|
|
return -ENOMEM;
|
|
|
|
@@ -197,12 +225,12 @@ static bool vm_file_match_policy(struct file *vm_file,
|
|
return false;
|
|
}
|
|
|
|
- if (ctx->baseline)
|
|
+ if (ctx->mode == DIM_BASELINE)
|
|
return dim_core_policy_match(DIM_POLICY_OBJ_BPRM_TEXT,
|
|
DIM_POLICY_KEY_PATH, ctx->path);
|
|
|
|
- return dim_core_search_dynamic_baseline(ctx->path, DIM_BASELINE_USER,
|
|
- &dig) == 0;
|
|
+ return dim_measure_dynamic_baseline_search(ctx->m, ctx->path,
|
|
+ DIM_BASELINE_USER, &dig) == 0;
|
|
}
|
|
|
|
static int update_vma_digest(struct vm_area_struct *vma_start,
|
|
@@ -258,8 +286,8 @@ static int check_user_digest(struct dim_digest *digest,
|
|
int log_flag = 0;
|
|
int action = 0;
|
|
|
|
- ret = dim_core_check_user_digest(ctx->baseline, ctx->path,
|
|
- digest, &log_flag);
|
|
+ ret = dim_measure_process_static_result(ctx->m, ctx->mode, ctx->path,
|
|
+ digest, &log_flag);
|
|
if (ret < 0) {
|
|
dim_err("failed to check user digest: %d\n", ret);
|
|
return ret;
|
|
@@ -281,10 +309,12 @@ static int measure_anon_text_vma(struct vm_area_struct *vma,
|
|
struct task_measure_ctx *ctx)
|
|
{
|
|
int ret = 0;
|
|
- struct dim_digest digest = { .algo = dim_core_hash.algo };
|
|
- SHASH_DESC_ON_STACK(shash, dim_core_hash.tfm);
|
|
+ struct dim_digest digest = {
|
|
+ .algo = ctx->m->hash.algo,
|
|
+ };
|
|
+ SHASH_DESC_ON_STACK(shash, ctx->hash.tfm);
|
|
|
|
- shash->tfm = dim_core_hash.tfm;
|
|
+ shash->tfm = ctx->hash.tfm;
|
|
ret = crypto_shash_init(shash);
|
|
if (ret < 0)
|
|
return ret;
|
|
@@ -333,10 +363,12 @@ static int measure_task_module_file_text(struct vm_area_struct *vma,
|
|
int ret = 0;
|
|
struct vm_area_struct *v = vma;
|
|
struct vm_area_struct *v_end = NULL;
|
|
- struct dim_digest digest = { .algo = dim_core_hash.algo };
|
|
- SHASH_DESC_ON_STACK(shash, dim_core_hash.tfm);
|
|
+ struct dim_digest digest = {
|
|
+ .algo = ctx->m->hash.algo
|
|
+ };
|
|
+ SHASH_DESC_ON_STACK(shash, ctx->m->hash.tfm);
|
|
|
|
- shash->tfm = dim_core_hash.tfm;
|
|
+ shash->tfm = ctx->m->hash.tfm;
|
|
ret = crypto_shash_init(shash);
|
|
if (ret < 0)
|
|
return ret;
|
|
@@ -434,8 +466,8 @@ out:
|
|
}
|
|
|
|
/* do schedule if this task is measured */
|
|
- if (ctx->task_measure && measure_schedule)
|
|
- schedule_timeout_uninterruptible(measure_schedule_jiffies);
|
|
+ if (ctx->task_measure)
|
|
+ dim_measure_schedule(ctx->m);
|
|
|
|
return 0;
|
|
}
|
|
@@ -508,18 +540,23 @@ static int walk_tasks(task_measurer f, struct task_measure_ctx *ctx)
|
|
return 0;
|
|
}
|
|
|
|
-int dim_core_measure_task(int baseline_init)
|
|
+static int user_text_measure(int mode, struct dim_measure *m)
|
|
{
|
|
- int ret = 0;
|
|
struct task_measure_ctx *ctx = NULL;
|
|
|
|
- ctx = kzalloc(sizeof(struct task_measure_ctx), GFP_KERNEL);
|
|
+ if (m == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ctx = vmalloc(sizeof(struct task_measure_ctx));
|
|
if (ctx == NULL)
|
|
return -ENOMEM;
|
|
|
|
- ctx->baseline = baseline_init;
|
|
- ret = walk_tasks(measure_task, ctx);
|
|
- kfree(ctx);
|
|
- return ret;
|
|
+ ctx->mode = mode;
|
|
+ ctx->m = m;
|
|
+ return walk_tasks(measure_task, ctx);
|
|
}
|
|
|
|
+struct dim_measure_task dim_core_measure_task_user_text = {
|
|
+ .name = "dim_core_measure_task_user_text",
|
|
+ .measure = user_text_measure,
|
|
+};
|
|
diff --git a/src/core/measure_task/dim_core_measure_task.h b/src/core/measure_task/dim_core_measure_task.h
|
|
new file mode 100644
|
|
index 0000000..0e26af2
|
|
--- /dev/null
|
|
+++ b/src/core/measure_task/dim_core_measure_task.h
|
|
@@ -0,0 +1,8 @@
|
|
+#ifndef __DIM_CORE_MEASURE_TASK_H
|
|
+#define __DIM_CORE_MEASURE_TASK_H
|
|
+
|
|
+extern struct dim_measure_task dim_core_measure_task_module_text;
|
|
+extern struct dim_measure_task dim_core_measure_task_kernel_text;
|
|
+extern struct dim_measure_task dim_core_measure_task_user_text;
|
|
+
|
|
+#endif
|
|
diff --git a/src/measure/dim_measure.c b/src/measure/dim_measure.c
|
|
new file mode 100644
|
|
index 0000000..06e9bb5
|
|
--- /dev/null
|
|
+++ b/src/measure/dim_measure.c
|
|
@@ -0,0 +1,100 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include "dim_measure.h"
|
|
+
|
|
+static int cfg_check(struct dim_measure_cfg *cfg)
|
|
+{
|
|
+ if (cfg->log_cap < MEASURE_LOG_CAP_MIN ||
|
|
+ cfg->log_cap > MEASURE_LOG_CAP_MAX) {
|
|
+ dim_err("invalid log capacity: %d\n", cfg->log_cap);
|
|
+ return -ERANGE;
|
|
+ }
|
|
+
|
|
+ if (cfg->schedule_ms > MEASURE_SCHEDULE_MAX) {
|
|
+ dim_err("invalid measure schedule: %d\n", cfg->schedule_ms);
|
|
+ return -ERANGE;
|
|
+ }
|
|
+
|
|
+ if (cfg->pcr > DIM_PCR_MAX) {
|
|
+ dim_err("invalid TPM pcr number: %d\n", cfg->pcr);
|
|
+ return -ERANGE;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int dim_measure_init(struct dim_measure *m, struct dim_measure_cfg *cfg)
|
|
+{
|
|
+ int ret = 0;
|
|
+
|
|
+ if (m == NULL || cfg == NULL || cfg_check(cfg) < 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ INIT_LIST_HEAD(&m->task_list);
|
|
+
|
|
+ /* 1. init hash algorithm */
|
|
+ ret = dim_hash_init(cfg->alg_name, &m->hash);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to init hash algorithm: %d\n", ret);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ /* 2. init TPM, dont break if init fail */
|
|
+ if (cfg->pcr > 0) {
|
|
+ ret = dim_tpm_init(&m->tpm, HASH_ALGO_SHA256);
|
|
+ if (ret < 0)
|
|
+ dim_warn("failed to init tpm chip: %d\n", ret);
|
|
+ } else {
|
|
+ memset(&m->tpm, 0, sizeof(struct dim_tpm));
|
|
+ }
|
|
+
|
|
+ /* 3. init baseline data (static and dynamic) */
|
|
+ ret = dim_baseline_init_tree(cfg->sta_malloc, cfg->sta_free,
|
|
+ &m->static_baseline);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to init static baseline root: %d\n", ret);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ ret = dim_baseline_init_tree(cfg->dyn_malloc, cfg->dyn_free,
|
|
+ &m->dynamic_baseline);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to init dynamic baseline root: %d\n", ret);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ /* 4. init measure log */
|
|
+ ret = dim_measure_log_init_tree(&m->log, &m->hash, &m->tpm,
|
|
+ cfg->log_cap, cfg->pcr);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to init measure log: %d\n", ret);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ /* 5. set measure schedule time */
|
|
+ m->schedule_jiffies = cfg->schedule_ms == 0 ? 0 :
|
|
+ msecs_to_jiffies(cfg->schedule_ms);
|
|
+
|
|
+ /* 6. set initial status */
|
|
+ atomic_set(&m->status, MEASURE_STATUS_NO_BASELINE);
|
|
+ return 0;
|
|
+err:
|
|
+ dim_measure_destroy(m);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+void dim_measure_destroy(struct dim_measure *m)
|
|
+{
|
|
+ if (m == NULL)
|
|
+ return;
|
|
+
|
|
+ mutex_lock(&m->measure_lock);
|
|
+ dim_measure_log_destroy_tree(&m->log);
|
|
+ dim_baseline_destroy_tree(&m->static_baseline);
|
|
+ dim_baseline_destroy_tree(&m->dynamic_baseline);
|
|
+ dim_tpm_destroy(&m->tpm);
|
|
+ dim_hash_destroy(&m->hash);
|
|
+ mutex_unlock(&m->measure_lock);
|
|
+}
|
|
diff --git a/src/measure/dim_measure.h b/src/measure/dim_measure.h
|
|
new file mode 100644
|
|
index 0000000..d2ca326
|
|
--- /dev/null
|
|
+++ b/src/measure/dim_measure.h
|
|
@@ -0,0 +1,117 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __DIM_MEASURE_H
|
|
+#define __DIM_MEASURE_H
|
|
+
|
|
+#include <linux/list.h>
|
|
+#include <linux/mutex.h>
|
|
+
|
|
+#include "dim_baseline.h"
|
|
+#include "dim_hash.h"
|
|
+#include "dim_measure_log.h"
|
|
+#include "dim_tpm.h"
|
|
+#include "dim_utils.h"
|
|
+
|
|
+#define DIM_MEASURE 0
|
|
+#define DIM_BASELINE 1
|
|
+
|
|
+/* limit of measure parameter */
|
|
+#define MEASURE_LOG_CAP_MAX (UINT_MAX)
|
|
+#define MEASURE_LOG_CAP_MIN (100)
|
|
+#define MEASURE_SCHEDULE_MAX (1000)
|
|
+
|
|
+/* status of measurement */
|
|
+enum dim_measure_status {
|
|
+ MEASURE_STATUS_OFF,
|
|
+ MEASURE_STATUS_NO_BASELINE,
|
|
+ MEASURE_STATUS_BASELINE_RUNNING,
|
|
+ MEASURE_STATUS_MEASURE_RUNNING,
|
|
+ MEASURE_STATUS_PROTECTED,
|
|
+ MEASURE_STATUS_ERROR,
|
|
+ MEASURE_STATUS_LAST,
|
|
+};
|
|
+
|
|
+/* the common configuration for measurement */
|
|
+struct dim_measure_cfg {
|
|
+ /* hash algorithm for measurement */
|
|
+ char *alg_name;
|
|
+ /* schedule time (ms) after one valid measurement */
|
|
+ unsigned int schedule_ms;
|
|
+ /* PCR number for TPM extending */
|
|
+ unsigned int pcr;
|
|
+ /* max measure log number */
|
|
+ unsigned int log_cap;
|
|
+ /* memory function for baseline store */
|
|
+ malloc_func dyn_malloc;
|
|
+ free_func dyn_free;
|
|
+ malloc_func sta_malloc;
|
|
+ free_func sta_free;
|
|
+};
|
|
+
|
|
+/* the dim measurement global handle */
|
|
+struct dim_measure {
|
|
+ /* schedule time (jittfies) after one valid measurement */
|
|
+ unsigned long schedule_jiffies;
|
|
+ /* lock to prevent concurrent measurement */
|
|
+ struct mutex measure_lock;
|
|
+ /* measure hash algorithm */
|
|
+ struct dim_hash hash;
|
|
+ /* TPM chip handle */
|
|
+ struct dim_tpm tpm;
|
|
+ /* measure log */
|
|
+ struct dim_measure_log_tree log;
|
|
+ /* measure baseline */
|
|
+ struct dim_baseline_tree static_baseline;
|
|
+ struct dim_baseline_tree dynamic_baseline;
|
|
+ /* function called before doing baseline */
|
|
+ int (*baseline_prepare)(struct dim_measure *m);
|
|
+ /* measure status */
|
|
+ atomic_t status;
|
|
+ /* task list */
|
|
+ struct list_head task_list;
|
|
+};
|
|
+
|
|
+/* the task definition for measurement function */
|
|
+struct dim_measure_task {
|
|
+ struct list_head node;
|
|
+ /* task name for log printing */
|
|
+ const char *name;
|
|
+ /* measure function */
|
|
+ int (*measure)(int mode, struct dim_measure *m);
|
|
+};
|
|
+
|
|
+/* functions for dim measure handle */
|
|
+int dim_measure_init(struct dim_measure *m, struct dim_measure_cfg *cfg);
|
|
+void dim_measure_destroy(struct dim_measure *m);
|
|
+
|
|
+/* functions for measurement results processing */
|
|
+int dim_measure_process_static_result(struct dim_measure *m, int mode,
|
|
+ const char *name,
|
|
+ struct dim_digest *digest,
|
|
+ int *log_flag);
|
|
+int dim_measure_process_dynamic_result(struct dim_measure *m, int mode,
|
|
+ const char *name,
|
|
+ struct dim_digest *digest,
|
|
+ int *log_flag);
|
|
+int dim_measure_static_baseline_add(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest);
|
|
+int dim_measure_dynamic_baseline_search(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest);
|
|
+/* functions for dim measurement task */
|
|
+int dim_measure_tasks_register(struct dim_measure *m,
|
|
+ struct dim_measure_task **tasks,
|
|
+ unsigned int num);
|
|
+void dim_measure_task_measure(int mode, struct dim_measure *m);
|
|
+
|
|
+/* functions for dim measurement status */
|
|
+const char *dim_measure_status_print(struct dim_measure *m);
|
|
+bool dim_measure_status_error(struct dim_measure *m);
|
|
+
|
|
+/* tool functions used for implementing measure tasks */
|
|
+void dim_measure_schedule(struct dim_measure *m);
|
|
+
|
|
+#endif
|
|
diff --git a/src/measure/dim_measure_baseline.c b/src/measure/dim_measure_baseline.c
|
|
new file mode 100644
|
|
index 0000000..dc358a7
|
|
--- /dev/null
|
|
+++ b/src/measure/dim_measure_baseline.c
|
|
@@ -0,0 +1,235 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include <linux/utsname.h>
|
|
+
|
|
+#include "dim_measure.h"
|
|
+
|
|
+static inline bool is_valid_mode(int mode)
|
|
+{
|
|
+ return mode == DIM_BASELINE || mode == DIM_MEASURE;
|
|
+}
|
|
+
|
|
+static const char *process_static_name(const char *name, int type,
|
|
+ char *buf, int buf_len)
|
|
+{
|
|
+ const char *kr = init_uts_ns.name.release;
|
|
+
|
|
+ if (type != DIM_BASELINE_KERNEL || strcmp(name, kr) == 0)
|
|
+ return name;
|
|
+
|
|
+ /* name of kernel module has a kernel prefix in static baseline */
|
|
+ if (sprintf(buf, "%s/%s", kr, name) < 0)
|
|
+ return NULL;
|
|
+
|
|
+ return buf;
|
|
+}
|
|
+
|
|
+static int static_baseline_add(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest)
|
|
+{
|
|
+ int ret = dim_baseline_add(&m->static_baseline, name, type, digest);
|
|
+ if (ret < 0 && ret != -EEXIST) {
|
|
+ dim_err("failed to add static baseline of %s\n", name);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int dynamic_baseline_add(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest)
|
|
+{
|
|
+ int ret = dim_baseline_add(&m->dynamic_baseline, name, type, digest);
|
|
+ if (ret < 0 && ret != -EEXIST) {
|
|
+ dim_err("failed to add dynamic baseline of %s\n", name);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static bool static_baseline_match(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest)
|
|
+{
|
|
+ char buf[NAME_MAX + NAME_MAX + 1 + 1] = { 0 };
|
|
+ return dim_baseline_match(&m->static_baseline,
|
|
+ process_static_name(name, type, buf, sizeof(buf)),
|
|
+ type, digest);
|
|
+}
|
|
+
|
|
+static bool dynamic_baseline_match(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest)
|
|
+{
|
|
+ return dim_baseline_match(&m->dynamic_baseline, name, type, digest);
|
|
+}
|
|
+
|
|
+static int static_baseline_search(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest)
|
|
+{
|
|
+ char buf[NAME_MAX + NAME_MAX + 1 + 1] = { 0 };
|
|
+ return dim_baseline_search_digest(&m->static_baseline,
|
|
+ process_static_name(name, type, buf, sizeof(buf)),
|
|
+ type, digest);
|
|
+}
|
|
+
|
|
+static int dynamic_baseline_search(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest)
|
|
+{
|
|
+ return dim_baseline_search_digest(&m->dynamic_baseline, name,
|
|
+ type, digest);
|
|
+}
|
|
+
|
|
+static int measure_log_add(struct dim_measure *m, const char *name,
|
|
+ struct dim_digest *digest, int flag)
|
|
+{
|
|
+ int ret = dim_measure_log_add(&m->log, name, digest, flag);
|
|
+ if (ret < 0 && ret != -EEXIST) {
|
|
+ dim_err("failed to add measure log of %s: %d\n", name, ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* check dynamic measurement result in baseline stage */
|
|
+static int process_dynamic_baseline(struct dim_measure *m, const char *name,
|
|
+ struct dim_digest *digest, int *log_flag) // TODO
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct dim_digest digest_static = { 0 };
|
|
+ int def_flag = log_flag == NULL ? LOG_NO_SATIC_BASELINE : *log_flag;
|
|
+
|
|
+ if (m == NULL || name == NULL || digest == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* 1. add digest to dynamic baseline */
|
|
+ ret = dynamic_baseline_add(m, name, DIM_BASELINE_KERNEL, digest);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ /* 2. search digest from static baseline */
|
|
+ ret = static_baseline_search(m, name, DIM_BASELINE_KERNEL, &digest_static);
|
|
+ if (ret < 0)
|
|
+ /* 2.1. if not find, log the dynamic baseline */
|
|
+ return measure_log_add(m, name, digest, def_flag);
|
|
+
|
|
+ /* 2.2. if find, log the static baseline */
|
|
+ return measure_log_add(m, name, &digest_static, LOG_STATIC_BASELINE);
|
|
+}
|
|
+
|
|
+/* process dynamic measurement result in measure stage */
|
|
+static int process_dynamic_measure(struct dim_measure *m, const char *name,
|
|
+ struct dim_digest *digest, int *log_flag)
|
|
+{
|
|
+ if (m == NULL || name == NULL || digest == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if(!dynamic_baseline_match(m, name, DIM_BASELINE_KERNEL, digest)) {
|
|
+ dim_err("mismatch dynamic baseline of kernel %s\n", name);
|
|
+ if (log_flag != NULL) // TODO
|
|
+ *log_flag = LOG_TAMPERED;
|
|
+
|
|
+ return measure_log_add(m, name, digest, LOG_TAMPERED);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* process static measurement result in baseline stage */
|
|
+static int process_static_baseline(struct dim_measure *m, const char *name,
|
|
+ struct dim_digest *digest, int *log_flag)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct dim_digest digest_static = { 0 };
|
|
+
|
|
+ /* 1. add digest to dynamic baseline */
|
|
+ ret = dynamic_baseline_add(m, name, DIM_BASELINE_USER, digest);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ /* 2. search digest from static baseline */
|
|
+ ret = static_baseline_search(m, name, DIM_BASELINE_USER, &digest_static);
|
|
+ if (ret < 0) /* 2.1. if not find, log the dynamic baseline */
|
|
+ return measure_log_add(m, name, digest, LOG_NO_SATIC_BASELINE);
|
|
+
|
|
+ /* 2.2. if find, compare with the static baseline */
|
|
+ if (static_baseline_match(m, name, DIM_BASELINE_USER, digest))
|
|
+ return measure_log_add(m, name, digest, LOG_STATIC_BASELINE);
|
|
+
|
|
+ dim_warn("mismatch static baseline of user process %s\n", name);
|
|
+ if (log_flag != NULL) // TODO
|
|
+ *log_flag = LOG_TAMPERED;
|
|
+
|
|
+ return measure_log_add(m, name, digest, LOG_TAMPERED);
|
|
+}
|
|
+
|
|
+/* process static measurement result in measure stage */
|
|
+static int process_static_measure(struct dim_measure *m, const char *name,
|
|
+ struct dim_digest *digest, int *log_flag)
|
|
+{
|
|
+ if(!dynamic_baseline_match(m, name, DIM_BASELINE_USER, digest)) {
|
|
+ dim_err("mismatch dynamic baseline of user %s\n", name);
|
|
+ if (log_flag != NULL) // TODO
|
|
+ *log_flag = LOG_TAMPERED;
|
|
+
|
|
+ return measure_log_add(m, name, digest, LOG_TAMPERED);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int dim_measure_process_static_result(struct dim_measure *m, int mode,
|
|
+ const char *name,
|
|
+ struct dim_digest *digest,
|
|
+ int *log_flag)
|
|
+{
|
|
+ if (m == NULL || name == NULL || digest == NULL ||
|
|
+ !is_valid_mode(mode))
|
|
+ return -EINVAL;
|
|
+
|
|
+ return mode == DIM_BASELINE ?
|
|
+ process_static_baseline(m, name, digest, log_flag) :
|
|
+ process_static_measure(m, name, digest, log_flag);
|
|
+}
|
|
+
|
|
+int dim_measure_process_dynamic_result(struct dim_measure *m, int mode,
|
|
+ const char *name,
|
|
+ struct dim_digest *digest,
|
|
+ int *log_flag)
|
|
+{
|
|
+ if (m == NULL || name == NULL || digest == NULL ||
|
|
+ !is_valid_mode(mode))
|
|
+ return -EINVAL;
|
|
+
|
|
+ return mode == DIM_BASELINE ?
|
|
+ process_dynamic_baseline(m, name, digest, log_flag) :
|
|
+ process_dynamic_measure(m, name, digest, log_flag);
|
|
+}
|
|
+
|
|
+int dim_measure_static_baseline_add(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest)
|
|
+{
|
|
+ if (m == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return static_baseline_add(m, name, type, digest);
|
|
+}
|
|
+
|
|
+int dim_measure_dynamic_baseline_search(struct dim_measure *m,
|
|
+ const char *name, int type,
|
|
+ struct dim_digest *digest)
|
|
+{
|
|
+ if (m == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return dynamic_baseline_search(m, name, type, digest);
|
|
+}
|
|
diff --git a/src/measure/dim_measure_status.c b/src/measure/dim_measure_status.c
|
|
new file mode 100644
|
|
index 0000000..28cfb43
|
|
--- /dev/null
|
|
+++ b/src/measure/dim_measure_status.c
|
|
@@ -0,0 +1,34 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include "dim_measure.h"
|
|
+
|
|
+static const char* status_name[MEASURE_STATUS_LAST + 1] = {
|
|
+ [MEASURE_STATUS_OFF] = "DIM_OFF",
|
|
+ [MEASURE_STATUS_NO_BASELINE] = "DIM_NO_BASELINE",
|
|
+ [MEASURE_STATUS_BASELINE_RUNNING] = "DIM_BASELINE_RUNNING",
|
|
+ [MEASURE_STATUS_MEASURE_RUNNING] = "DIM_MEASURE_RUNNING",
|
|
+ [MEASURE_STATUS_PROTECTED] = "DIM_PROTECTED",
|
|
+ [MEASURE_STATUS_ERROR] = "DIM_ERROR",
|
|
+ [MEASURE_STATUS_LAST] = "DIM_UNKNOWN",
|
|
+};
|
|
+
|
|
+const char *dim_measure_status_print(struct dim_measure *m)
|
|
+{
|
|
+ int status = 0;
|
|
+
|
|
+ if (m == NULL)
|
|
+ return status_name[MEASURE_STATUS_LAST];
|
|
+
|
|
+ status = atomic_read(&m->status);
|
|
+ if (status < 0 || status >= MEASURE_STATUS_LAST)
|
|
+ status = MEASURE_STATUS_LAST;
|
|
+
|
|
+ return status_name[status];
|
|
+}
|
|
+
|
|
+bool dim_measure_status_error(struct dim_measure *m)
|
|
+{
|
|
+ return atomic_read(&m->status) == MEASURE_STATUS_ERROR;
|
|
+}
|
|
diff --git a/src/measure/dim_measure_task.c b/src/measure/dim_measure_task.c
|
|
new file mode 100644
|
|
index 0000000..ed97388
|
|
--- /dev/null
|
|
+++ b/src/measure/dim_measure_task.c
|
|
@@ -0,0 +1,91 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include "dim_measure.h"
|
|
+
|
|
+static void call_measure_func(int mode, struct dim_measure_task *t,
|
|
+ struct dim_measure *m)
|
|
+{
|
|
+ int ret = 0;
|
|
+
|
|
+ if (t->measure == NULL) {
|
|
+ dim_warn("no measure function in %s task", t->name);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ dim_info("start to call %s measure task\n", t->name);
|
|
+ ret = t->measure(mode, m);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to call measure task %s: %d\n", t->name, ret);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ dim_info("succeed to call measure task %s\n", t->name);
|
|
+}
|
|
+
|
|
+void dim_measure_task_measure(int mode, struct dim_measure *m)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int status = 0;
|
|
+ struct dim_measure_task *task = NULL;
|
|
+
|
|
+ if (m == NULL)
|
|
+ return;
|
|
+
|
|
+ mutex_lock(&m->measure_lock);
|
|
+ status = atomic_read(&m->status);
|
|
+ if (mode == DIM_MEASURE && status != MEASURE_STATUS_PROTECTED) {
|
|
+ dim_info("no baseline, do baseline init instead\n");
|
|
+ mode = DIM_BASELINE;
|
|
+ }
|
|
+
|
|
+ atomic_set(&m->status, mode == DIM_BASELINE ?
|
|
+ MEASURE_STATUS_BASELINE_RUNNING :
|
|
+ MEASURE_STATUS_MEASURE_RUNNING);
|
|
+
|
|
+ if (mode == DIM_BASELINE && m->baseline_prepare != NULL) {
|
|
+ ret = m->baseline_prepare(m);
|
|
+ if (ret < 0) {
|
|
+ atomic_set(&m->status, MEASURE_STATUS_ERROR);
|
|
+ mutex_unlock(&m->measure_lock);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ list_for_each_entry(task, &m->task_list, node)
|
|
+ call_measure_func(mode, task, m);
|
|
+
|
|
+ atomic_set(&m->status, MEASURE_STATUS_PROTECTED);
|
|
+ mutex_unlock(&m->measure_lock);
|
|
+}
|
|
+
|
|
+static int task_register(struct dim_measure *m, struct dim_measure_task *t)
|
|
+{
|
|
+ if (t == NULL || t->name == NULL || t->measure == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ list_add_tail(&t->node, &m->task_list);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int dim_measure_tasks_register(struct dim_measure *m,
|
|
+ struct dim_measure_task **tasks,
|
|
+ unsigned int num)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int i = 0;
|
|
+
|
|
+ if (m == NULL || tasks == NULL || num == 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ for (; i < num; i++) {
|
|
+ ret = task_register(m, tasks[i]);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ dim_info("register measure task: %s\n", tasks[i]->name);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/src/measure/dim_measure_utils.c b/src/measure/dim_measure_utils.c
|
|
new file mode 100644
|
|
index 0000000..049d362
|
|
--- /dev/null
|
|
+++ b/src/measure/dim_measure_utils.c
|
|
@@ -0,0 +1,13 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include "dim_measure.h"
|
|
+
|
|
+void dim_measure_schedule(struct dim_measure *m)
|
|
+{
|
|
+ if (m == NULL || m->schedule_jiffies == 0)
|
|
+ return;
|
|
+
|
|
+ schedule_timeout_uninterruptible(m->schedule_jiffies);
|
|
+}
|
|
diff --git a/src/monitor/dim_monitor.h b/src/monitor/dim_monitor.h
|
|
index ce3c676..8f1f0f7 100644
|
|
--- a/src/monitor/dim_monitor.h
|
|
+++ b/src/monitor/dim_monitor.h
|
|
@@ -5,37 +5,24 @@
|
|
#ifndef __DIM_MONITOR_H
|
|
#define __DIM_MONITOR_H
|
|
|
|
-#include "dim_status.h"
|
|
-#include "dim_utils.h"
|
|
+#include "dim_measure.h"
|
|
|
|
#define DIM_MONITOR_HASH_DEFAULT "sha256"
|
|
-#define DIM_MODULE "dim_monitor"
|
|
+#define DIM_MONITOR_LOG_CAP_DEFAULT 100000
|
|
+
|
|
#define DIM_CORE "dim_core"
|
|
#define DIM_CORE_TEXT "dim_core.text"
|
|
#define DIM_CORE_DATA "dim_core.data"
|
|
|
|
-/* limit of measure parameter */
|
|
-#define MEASURE_LOG_CAP_MAX (UINT_MAX)
|
|
-#define MEASURE_LOG_CAP_MIN (100)
|
|
-
|
|
-enum dim_monitor_status {
|
|
- DIM_MONITOR_READY,
|
|
- DIM_MONITOR_RUNNING,
|
|
- DIM_MONITOR_PROTECTED,
|
|
- DIM_MONITOR_ERROR,
|
|
- DIM_MONITOR_STATUS_LAST,
|
|
-};
|
|
-
|
|
-extern struct dim_status dim_monitor_status;
|
|
-extern struct dim_measure_log_tree dim_monitor_log;
|
|
-extern unsigned int measure_log_capacity;
|
|
-extern unsigned int measure_pcr;
|
|
+extern struct dim_measure dim_monitor_handle;
|
|
|
|
void dim_monitor_destroy_fs(void);
|
|
int dim_monitor_create_fs(void);
|
|
|
|
-int dim_monitor_measure_init(const char *alg_name);
|
|
-void dim_monitor_destroy_measure(void);
|
|
-int dim_monitor_measure(int baseline);
|
|
+int dim_monitor_measure_init(struct dim_measure_cfg *cfg);
|
|
+void dim_monitor_measure_destroy(void);
|
|
+int dim_monitor_measure_blocking(void);
|
|
+int dim_monitor_baseline_blocking(void);
|
|
+const char *dim_monitor_status_print(void);
|
|
|
|
-#endif
|
|
\ No newline at end of file
|
|
+#endif
|
|
diff --git a/src/monitor/dim_monitor_fs.c b/src/monitor/dim_monitor_fs.c
|
|
index 5535e59..8bb3120 100644
|
|
--- a/src/monitor/dim_monitor_fs.c
|
|
+++ b/src/monitor/dim_monitor_fs.c
|
|
@@ -7,6 +7,8 @@
|
|
#include "dim_entry.h"
|
|
#include "dim_utils.h"
|
|
|
|
+#include "dim_measure.h"
|
|
+
|
|
#include "dim_monitor.h"
|
|
|
|
extern struct dim_entry *dim_root_entry(void);
|
|
@@ -15,25 +17,25 @@ extern struct dim_entry *dim_root_entry(void);
|
|
* monitor trigger interface
|
|
* dim_entry struct: dim_monitor_measure_entry
|
|
* file entry name: monitor_run
|
|
- * function: dim_monitor_measure(0)
|
|
+ * function: dim_monitor_measure_blocking()
|
|
*/
|
|
-dim_trigger_entry(dim_monitor_measure, monitor_run, dim_monitor_measure, 0);
|
|
+dim_trigger_entry(dim_monitor_measure, monitor_run, dim_monitor_measure_blocking);
|
|
|
|
/*
|
|
* monitor baseline trigger interface
|
|
* dim_entry struct: dim_monitor_baseline_entry
|
|
* file entry name: monitor_baseline
|
|
- * function: dim_monitor_measure(1)
|
|
+ * function: dim_monitor_baseline_blocking()
|
|
*/
|
|
-dim_trigger_entry(dim_monitor_baseline, monitor_baseline, dim_monitor_measure, 1);
|
|
+dim_trigger_entry(dim_monitor_baseline, monitor_baseline, dim_monitor_baseline_blocking);
|
|
|
|
/*
|
|
- * status read interface
|
|
- * dim_entry struct: dim_monitor_status_entry
|
|
+ * status print interface
|
|
+ * dim_entry struct: dim_status_entry
|
|
* file entry name: monitor_status
|
|
- * data to read: dim_monitor_status
|
|
+ * print function: dim_core_status_print
|
|
*/
|
|
-dim_status_entry(dim_monitor_status, monitor_status, &dim_monitor_status);
|
|
+dim_string_print_entry(dim_monitor_status, monitor_status, dim_monitor_status_print);
|
|
|
|
/*
|
|
* measure log read interface
|
|
@@ -42,7 +44,7 @@ dim_status_entry(dim_monitor_status, monitor_status, &dim_monitor_status);
|
|
* status to read: dim_measure_log_tree
|
|
*/
|
|
dim_measure_log_entry(dim_monitor_log, monitor_ascii_runtime_measurements,
|
|
- &dim_monitor_log);
|
|
+ &dim_monitor_handle.log);
|
|
|
|
static struct dim_entry *dim_monitor_files[] = {
|
|
&dim_monitor_measure_entry,
|
|
@@ -66,4 +68,4 @@ int dim_monitor_create_fs(void)
|
|
return -ENOENT;
|
|
|
|
return dim_entry_create_list(dim_monitor_files, len, dim_root->dentry);
|
|
-}
|
|
\ No newline at end of file
|
|
+}
|
|
diff --git a/src/monitor/dim_monitor_main.c b/src/monitor/dim_monitor_main.c
|
|
index 0165d3a..4b3505d 100644
|
|
--- a/src/monitor/dim_monitor_main.c
|
|
+++ b/src/monitor/dim_monitor_main.c
|
|
@@ -4,18 +4,24 @@
|
|
|
|
#include <linux/module.h>
|
|
|
|
+#include "dim_measure.h"
|
|
+
|
|
#include "dim_monitor.h"
|
|
#include "dim_monitor_symbol.h"
|
|
|
|
-static char *measure_hash = NULL;
|
|
+/* common measurement configuration */
|
|
+static struct dim_measure_cfg cfg = {
|
|
+ .alg_name = DIM_MONITOR_HASH_DEFAULT,
|
|
+ .log_cap = DIM_MONITOR_LOG_CAP_DEFAULT,
|
|
+};
|
|
|
|
-module_param(measure_log_capacity, uint, 0);
|
|
+module_param_named(measure_log_capacity, cfg.log_cap, uint, 0);
|
|
MODULE_PARM_DESC(measure_log_capacity, "Max number of measure log");
|
|
|
|
-module_param(measure_hash, charp, 0);
|
|
+module_param_named(measure_hash, cfg.alg_name, charp, 0);
|
|
MODULE_PARM_DESC(measure_hash, "Hash algorithm for measurement");
|
|
|
|
-module_param(measure_pcr, uint, 0);
|
|
+module_param_named(measure_pcr, cfg.pcr, uint, 0);
|
|
MODULE_PARM_DESC(measure_pcr, "TPM PCR index to extend measure log");
|
|
|
|
static int __init dim_monitor_init(void)
|
|
@@ -28,8 +34,7 @@ static int __init dim_monitor_init(void)
|
|
goto err;
|
|
}
|
|
|
|
- ret = dim_monitor_measure_init(measure_hash == NULL ?
|
|
- DIM_MONITOR_HASH_DEFAULT : measure_hash);
|
|
+ ret = dim_monitor_measure_init(&cfg);
|
|
if (ret < 0) {
|
|
dim_err("fail to initialize dim measurement: %d\n", ret);
|
|
goto err;
|
|
@@ -43,17 +48,17 @@ static int __init dim_monitor_init(void)
|
|
|
|
return 0;
|
|
err:
|
|
- dim_monitor_destroy_measure();
|
|
+ dim_monitor_measure_destroy();
|
|
dim_monitor_destroy_fs();
|
|
return ret;
|
|
}
|
|
|
|
static void __exit dim_monitor_exit(void)
|
|
{
|
|
- dim_monitor_destroy_measure();
|
|
+ dim_monitor_measure_destroy();
|
|
dim_monitor_destroy_fs();
|
|
}
|
|
|
|
module_init(dim_monitor_init);
|
|
module_exit(dim_monitor_exit);
|
|
-MODULE_LICENSE("GPL");
|
|
\ No newline at end of file
|
|
+MODULE_LICENSE("GPL");
|
|
diff --git a/src/monitor/dim_monitor_measure.c b/src/monitor/dim_monitor_measure.c
|
|
index 10a1e7b..f21ed0e 100644
|
|
--- a/src/monitor/dim_monitor_measure.c
|
|
+++ b/src/monitor/dim_monitor_measure.c
|
|
@@ -2,253 +2,94 @@
|
|
* Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
*/
|
|
|
|
-#include <linux/fs.h>
|
|
#include <linux/version.h>
|
|
#include <linux/genalloc.h>
|
|
|
|
-#include "dim_baseline.h"
|
|
-#include "dim_hash.h"
|
|
-#include "dim_measure_log.h"
|
|
-#include "dim_tpm.h"
|
|
-#include "dim_utils.h"
|
|
+#include "dim_measure.h"
|
|
|
|
#include "dim_core_mem_pool.h"
|
|
|
|
#include "dim_monitor.h"
|
|
#include "dim_monitor_symbol.h"
|
|
|
|
-static const char *dim_monitor_status_name[DIM_MONITOR_STATUS_LAST] = {
|
|
- [DIM_MONITOR_READY] = "ready",
|
|
- [DIM_MONITOR_RUNNING] = "running",
|
|
- [DIM_MONITOR_PROTECTED] = "protected",
|
|
- [DIM_MONITOR_ERROR] = "error",
|
|
-};
|
|
-
|
|
-static struct dim_hash dim_monitor_hash = { 0 };
|
|
-static struct dim_tpm dim_monitor_tpm = { 0 };
|
|
-static struct dim_baseline_tree dim_monitor_baseline = { 0 };
|
|
+#include "measure_task/dim_monitor_measure_task.h"
|
|
|
|
-struct dim_status dim_monitor_status = { 0 };
|
|
-struct dim_measure_log_tree dim_monitor_log = { 0 };
|
|
+/* measurement tasks */
|
|
+static struct dim_measure_task *dim_core_tasks[] = {
|
|
+ &dim_monitor_measure_data,
|
|
+ &dim_monitor_measure_text,
|
|
+};
|
|
|
|
-unsigned int measure_log_capacity = 100000;
|
|
-unsigned int measure_pcr = 0;
|
|
+/* the global measurement handle */
|
|
+struct dim_measure dim_monitor_handle = { 0 };
|
|
|
|
-/* lock to prevent concurrent measurement */
|
|
+/* lock to prevent trigger multiple measurement */
|
|
DEFINE_MUTEX(dim_monitor_measure_lock);
|
|
|
|
-static void dim_monitor_status_set(unsigned int status)
|
|
+const char *dim_monitor_status_print(void)
|
|
{
|
|
- dim_status_set(&dim_monitor_status, status);
|
|
+ return dim_measure_status_print(&dim_monitor_handle);
|
|
}
|
|
|
|
-static int add_measure_log(const char *name, struct dim_digest *digest, int type)
|
|
+int dim_monitor_measure_blocking(void)
|
|
{
|
|
- int ret = 0;
|
|
-
|
|
- ret = dim_measure_log_add(&dim_monitor_log, name, digest, type);
|
|
- if (ret < 0 && ret != -EEXIST) {
|
|
- dim_err("fail to add measure log of %s: %d\n", name, ret);
|
|
- return ret;
|
|
- }
|
|
+ if (!mutex_trylock(&dim_monitor_measure_lock))
|
|
+ return -EBUSY;
|
|
|
|
+ dim_measure_task_measure(DIM_MEASURE, &dim_monitor_handle);
|
|
+ mutex_unlock(&dim_monitor_measure_lock);
|
|
return 0;
|
|
}
|
|
|
|
-static int add_baseline(const char *name, struct dim_digest *digest, int type)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- ret = dim_baseline_add(&dim_monitor_baseline, name, type, digest);
|
|
- if (ret < 0) {
|
|
- dim_err("fail to add dim baseline of %s: %d\n", name, ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- return add_measure_log(name, digest, LOG_DYNAMIC_BASELINE);
|
|
-}
|
|
-
|
|
-static int check_digest(const char *name, struct dim_digest *digest, int type)
|
|
-{
|
|
- return dim_baseline_match(&dim_monitor_baseline, name, type, digest) ?
|
|
- 0 : add_measure_log(name, digest, LOG_TAMPERED);
|
|
-}
|
|
-
|
|
-static void calculate_chunk(struct gen_pool *pool,
|
|
- struct gen_pool_chunk *chunk,
|
|
- void *data)
|
|
-{
|
|
- struct shash_desc *shash = (struct shash_desc *)data;
|
|
-
|
|
- if (chunk == NULL || shash == NULL)
|
|
- return;
|
|
-
|
|
- (void)crypto_shash_update(shash, (char *)chunk->start_addr,
|
|
- chunk->end_addr - chunk->start_addr);
|
|
-}
|
|
-
|
|
-static int measure_data(int baseline_init)
|
|
-{
|
|
- int ret = 0;
|
|
- struct dim_digest digest = { .algo = dim_monitor_hash.algo };
|
|
-
|
|
- SHASH_DESC_ON_STACK(shash, dim_monitor_hash.tfm);
|
|
- shash->tfm = dim_monitor_hash.tfm;
|
|
- ret = crypto_shash_init(shash);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- dim_mem_pool_walk_chunk(calculate_chunk, shash);
|
|
- ret = crypto_shash_final(shash, digest.data);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- return baseline_init ?
|
|
- add_baseline(DIM_CORE_DATA, &digest, DIM_BASELINE_DATA) :
|
|
- check_digest(DIM_CORE_DATA, &digest, DIM_BASELINE_DATA);
|
|
-}
|
|
-
|
|
-static int measure_text(int baseline_init)
|
|
+int dim_monitor_baseline_blocking(void)
|
|
{
|
|
- int ret = 0;
|
|
- struct module *mod = NULL;
|
|
- struct dim_digest digest = { 0 };
|
|
-
|
|
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
- mutex_lock(&module_mutex);
|
|
- mod = find_module(DIM_CORE);
|
|
-#else
|
|
- rcu_read_lock_sched();
|
|
- mod = dim_monitor_kernel_symbol.find_module(DIM_CORE);
|
|
-#endif
|
|
- if (mod == NULL || mod->state != MODULE_STATE_LIVE ||
|
|
- !try_module_get(mod))
|
|
- mod = NULL; /* target module not exist or is not alive */
|
|
-
|
|
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
- mutex_unlock(&module_mutex);
|
|
-#else
|
|
- rcu_read_unlock_sched();
|
|
-#endif
|
|
- if (mod == NULL)
|
|
- return -ENOENT;
|
|
-
|
|
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
- ret = dim_hash_calculate(mod->core_layout.base,
|
|
- mod->core_layout.text_size,
|
|
- &dim_monitor_hash, &digest);
|
|
-#else
|
|
- ret = dim_hash_calculate(mod->mem[MOD_TEXT].base,
|
|
- mod->mem[MOD_TEXT].size,
|
|
- &dim_monitor_hash, &digest);
|
|
-#endif
|
|
- module_put(mod);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- return baseline_init ?
|
|
- add_baseline(DIM_CORE_TEXT, &digest, DIM_BASELINE_KERNEL) :
|
|
- check_digest(DIM_CORE_TEXT, &digest, DIM_BASELINE_KERNEL);
|
|
-}
|
|
-
|
|
-int dim_monitor_measure(int baseline_init)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
if (!mutex_trylock(&dim_monitor_measure_lock))
|
|
return -EBUSY;
|
|
|
|
- dim_monitor_status_set(DIM_MONITOR_RUNNING);
|
|
- dim_info("start dim monitor measure, baseline_init = %d\n",
|
|
- baseline_init);
|
|
-
|
|
- if (baseline_init) {
|
|
- dim_baseline_destroy_tree(&dim_monitor_baseline);
|
|
- dim_measure_log_refresh(&dim_monitor_log);
|
|
- }
|
|
-
|
|
- ret = measure_text(baseline_init);
|
|
- if (ret < 0) {
|
|
- dim_err("fail to measure dim_core text");
|
|
- goto out;
|
|
- }
|
|
-
|
|
- ret = measure_data(baseline_init);
|
|
- if (ret < 0)
|
|
- dim_err("fail to measure dim_core data");
|
|
-out:
|
|
+ dim_measure_task_measure(DIM_BASELINE, &dim_monitor_handle);
|
|
mutex_unlock(&dim_monitor_measure_lock);
|
|
- dim_monitor_status_set(ret < 0 ? DIM_MONITOR_ERROR :
|
|
- DIM_MONITOR_PROTECTED);
|
|
- return ret;
|
|
+ return 0;
|
|
}
|
|
|
|
-int dim_monitor_measure_init(const char *alg_name)
|
|
+static int baseline_prepare(struct dim_measure *m)
|
|
{
|
|
- int ret = 0;
|
|
-
|
|
- /* 1. check the measure parameter */
|
|
- if (measure_log_capacity < MEASURE_LOG_CAP_MIN ||
|
|
- measure_log_capacity > MEASURE_LOG_CAP_MAX) {
|
|
- dim_err("invalid measure_log_capacity parameter\n");
|
|
- return -ERANGE;
|
|
- }
|
|
-
|
|
- if (measure_pcr > DIM_PCR_MAX) {
|
|
- dim_err("invalid measure_pcr parameter\n");
|
|
- return -ERANGE;
|
|
- }
|
|
-
|
|
- /* init TPM, dont break if init fail */
|
|
- if (measure_pcr > 0) {
|
|
- ret = dim_tpm_init(&dim_monitor_tpm, HASH_ALGO_SHA256);
|
|
- if (ret < 0)
|
|
- dim_warn("fail to initialize tpm chip: %d\n", ret);
|
|
- }
|
|
+ dim_baseline_destroy_tree(&m->static_baseline);
|
|
+ dim_baseline_destroy_tree(&m->dynamic_baseline);
|
|
+ dim_measure_log_refresh(&m->log);
|
|
+ return 0;
|
|
+}
|
|
|
|
- ret = dim_hash_init(alg_name, &dim_monitor_hash);
|
|
- if (ret < 0) {
|
|
- dim_err("fail to initialize hash algorithm: %d\n", ret);
|
|
- goto err;
|
|
- }
|
|
+int dim_monitor_measure_init(struct dim_measure_cfg *cfg)
|
|
+{
|
|
+ int ret = 0;
|
|
|
|
- ret = dim_status_init(&dim_monitor_status, dim_monitor_status_name,
|
|
- DIM_MONITOR_STATUS_LAST);
|
|
+ /* init the measurement handle */
|
|
+ ret = dim_measure_init(&dim_monitor_handle, cfg);
|
|
if (ret < 0) {
|
|
- dim_err("fail to initialize status: %d\n", ret);
|
|
- goto err;
|
|
+ dim_err("failed to init measurement handle\n");
|
|
+ return ret;
|
|
}
|
|
|
|
- ret = dim_baseline_init_tree(dim_kmalloc_gfp, dim_kfree,
|
|
- &dim_monitor_baseline);
|
|
- if (ret < 0) {
|
|
- dim_err("fail to initialize static baseline root: %d\n", ret);
|
|
- goto err;
|
|
- }
|
|
+ /* set the baseline prepare function */
|
|
+ dim_monitor_handle.baseline_prepare = baseline_prepare;
|
|
|
|
- ret = dim_measure_log_init_tree(&dim_monitor_log, &dim_monitor_hash,
|
|
- &dim_monitor_tpm, measure_log_capacity,
|
|
- measure_pcr);
|
|
+ /* register all measurement tasks */
|
|
+ ret = dim_measure_tasks_register(&dim_monitor_handle, dim_core_tasks,
|
|
+ DIM_ARRAY_LEN(dim_core_tasks));
|
|
if (ret < 0) {
|
|
- dim_err("fail to initialize measure log: %d\n", ret);
|
|
+ dim_err("failed to register measure tasks: %d\n", ret);
|
|
goto err;
|
|
}
|
|
|
|
- dim_status_set(&dim_monitor_status, DIM_MONITOR_READY);
|
|
return 0;
|
|
err:
|
|
- dim_measure_log_destroy_tree(&dim_monitor_log);
|
|
- dim_baseline_destroy_tree(&dim_monitor_baseline);
|
|
- dim_hash_destroy(&dim_monitor_hash);
|
|
- dim_tpm_destroy(&dim_monitor_tpm);
|
|
+ dim_measure_destroy(&dim_monitor_handle);
|
|
return ret;
|
|
}
|
|
|
|
-void dim_monitor_destroy_measure(void)
|
|
+void dim_monitor_measure_destroy(void)
|
|
{
|
|
mutex_lock(&dim_monitor_measure_lock);
|
|
- dim_measure_log_destroy_tree(&dim_monitor_log);
|
|
- dim_baseline_destroy_tree(&dim_monitor_baseline);
|
|
- dim_hash_destroy(&dim_monitor_hash);
|
|
- dim_tpm_destroy(&dim_monitor_tpm);
|
|
+ dim_measure_destroy(&dim_monitor_handle);
|
|
+ mutex_unlock(&dim_monitor_measure_lock);
|
|
}
|
|
diff --git a/src/monitor/dim_monitor_symbol.c b/src/monitor/dim_monitor_symbol.c
|
|
index 975c140..4054099 100644
|
|
--- a/src/monitor/dim_monitor_symbol.c
|
|
+++ b/src/monitor/dim_monitor_symbol.c
|
|
@@ -30,4 +30,4 @@ int dim_monitor_kallsyms_init(void)
|
|
#else
|
|
return 0;
|
|
#endif
|
|
-}
|
|
\ No newline at end of file
|
|
+}
|
|
diff --git a/src/monitor/measure_task/dim_monitor_measure_data.c b/src/monitor/measure_task/dim_monitor_measure_data.c
|
|
new file mode 100644
|
|
index 0000000..5762dc1
|
|
--- /dev/null
|
|
+++ b/src/monitor/measure_task/dim_monitor_measure_data.c
|
|
@@ -0,0 +1,56 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include "dim_measure.h"
|
|
+#include "dim_core_mem_pool.h"
|
|
+
|
|
+#include "dim_monitor.h"
|
|
+
|
|
+#include "dim_monitor_measure_task.h"
|
|
+
|
|
+static void calculate_chunk(struct gen_pool *pool,
|
|
+ struct gen_pool_chunk *chunk,
|
|
+ void *data)
|
|
+{
|
|
+ struct shash_desc *shash = (struct shash_desc *)data;
|
|
+
|
|
+ if (chunk == NULL || shash == NULL)
|
|
+ return;
|
|
+
|
|
+ (void)crypto_shash_update(shash, (char *)chunk->start_addr,
|
|
+ chunk->end_addr - chunk->start_addr);
|
|
+}
|
|
+
|
|
+static int module_text_measure(int mode, struct dim_measure *m)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int log_flag = LOG_DYNAMIC_BASELINE;
|
|
+ struct dim_digest digest = {
|
|
+ .algo = m->hash.algo,
|
|
+ };
|
|
+
|
|
+ SHASH_DESC_ON_STACK(shash, m->hash.tfm);
|
|
+ shash->tfm = m->hash.tfm;
|
|
+
|
|
+ ret = crypto_shash_init(shash);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ dim_mem_pool_walk_chunk(calculate_chunk, shash);
|
|
+ ret = crypto_shash_final(shash, digest.data);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ ret = dim_measure_process_dynamic_result(m, mode, DIM_CORE_DATA,
|
|
+ &digest, &log_flag);
|
|
+ if (ret < 0)
|
|
+ dim_err("failed to check dim_core data digest: %d\n", ret);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+struct dim_measure_task dim_monitor_measure_data = {
|
|
+ .name = "dim_monitor_measure_data",
|
|
+ .measure = module_text_measure,
|
|
+};
|
|
diff --git a/src/monitor/measure_task/dim_monitor_measure_task.h b/src/monitor/measure_task/dim_monitor_measure_task.h
|
|
new file mode 100644
|
|
index 0000000..326fd48
|
|
--- /dev/null
|
|
+++ b/src/monitor/measure_task/dim_monitor_measure_task.h
|
|
@@ -0,0 +1,11 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __DIM_MONITOR_MEASURE_TASK_H
|
|
+#define __DIM_MONITOR_MEASURE_TASK_H
|
|
+
|
|
+extern struct dim_measure_task dim_monitor_measure_data;
|
|
+extern struct dim_measure_task dim_monitor_measure_text;
|
|
+
|
|
+#endif
|
|
diff --git a/src/monitor/measure_task/dim_monitor_measure_text.c b/src/monitor/measure_task/dim_monitor_measure_text.c
|
|
new file mode 100644
|
|
index 0000000..de6c77d
|
|
--- /dev/null
|
|
+++ b/src/monitor/measure_task/dim_monitor_measure_text.c
|
|
@@ -0,0 +1,64 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include <linux/version.h>
|
|
+#include <linux/module.h>
|
|
+
|
|
+#include "dim_measure.h"
|
|
+
|
|
+#include "dim_monitor.h"
|
|
+#include "dim_monitor_symbol.h"
|
|
+#include "dim_monitor_measure_task.h"
|
|
+
|
|
+static int module_text_measure(int mode, struct dim_measure *m)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int log_flag = LOG_DYNAMIC_BASELINE;
|
|
+ struct module *mod = NULL;
|
|
+ struct dim_digest digest = { 0 };
|
|
+
|
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
+ mutex_lock(&module_mutex);
|
|
+ mod = find_module(DIM_CORE);
|
|
+#else
|
|
+ rcu_read_lock_sched();
|
|
+ mod = dim_monitor_kernel_symbol.find_module(DIM_CORE);
|
|
+#endif
|
|
+ if (mod == NULL || mod->state != MODULE_STATE_LIVE ||
|
|
+ !try_module_get(mod))
|
|
+ mod = NULL; /* target module not exist or is not alive */
|
|
+
|
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
+ mutex_unlock(&module_mutex);
|
|
+#else
|
|
+ rcu_read_unlock_sched();
|
|
+#endif
|
|
+ if (mod == NULL)
|
|
+ return -ENOENT;
|
|
+
|
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
+ ret = dim_hash_calculate(mod->core_layout.base,
|
|
+ mod->core_layout.text_size,
|
|
+ &m->hash, &digest);
|
|
+#else
|
|
+ ret = dim_hash_calculate(mod->mem[MOD_TEXT].base,
|
|
+ mod->mem[MOD_TEXT].size,
|
|
+ &m->hash, &digest);
|
|
+#endif
|
|
+ module_put(mod);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ ret = dim_measure_process_dynamic_result(m, mode, DIM_CORE_TEXT,
|
|
+ &digest, &log_flag);
|
|
+ if (ret < 0)
|
|
+ dim_err("failed to check dim_core text digest: %d\n", ret);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+struct dim_measure_task dim_monitor_measure_text = {
|
|
+ .name = "dim_monitor_measure_text",
|
|
+ .measure = module_text_measure,
|
|
+};
|
|
--
|
|
2.33.0
|
|
|