From f1751e2438811f861e24e7be285a333942132b47 Mon Sep 17 00:00:00 2001 From: Huaxin Lu 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 #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 - -#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 - -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 -#include - -#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 -#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 -#include -#include +#include -#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 -#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 + #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 #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 #include -#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 +#include + +#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 + +#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 +#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 #include #include -#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 +#include + +#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