1164 lines
33 KiB
Diff
1164 lines
33 KiB
Diff
From a0d84883a2ebd71715bc044218341c645eb9b06b Mon Sep 17 00:00:00 2001
|
|
From: Huaxin Lu <luhuaxin1@huawei.com>
|
|
Date: Tue, 13 Feb 2024 17:09:46 +0800
|
|
Subject: [PATCH 15/26] Support user process measurement by ELF parsing
|
|
|
|
1. Refactor the implement for process measurement, separate the process
|
|
modules (different binary files) measurement and process walking,
|
|
to make it easier to extend different measurement methods.
|
|
2. Implement a user process measurement method based on ELF parsing.
|
|
Support to measure memory of the ELF segment and section.
|
|
---
|
|
src/Makefile | 18 +-
|
|
.../dim_core_measure_kernel.c | 0
|
|
.../dim_core_measure_module.c | 0
|
|
.../dim_core_measure_process.c} | 279 +--------------
|
|
.../dim_core_measure_process.h | 82 +++++
|
|
.../dim_core_measure_process_elf.c | 338 ++++++++++++++++++
|
|
.../dim_core_measure_process_vma.c | 93 +++++
|
|
.../dim_core_measure_process/dim_vm_hash.c | 107 ++++++
|
|
.../dim_core_measure_process/dim_vm_hash.h | 25 ++
|
|
.../dim_core_measure_task.h | 17 +-
|
|
10 files changed, 686 insertions(+), 273 deletions(-)
|
|
rename src/core/{measure_task => tasks}/dim_core_measure_kernel.c (100%)
|
|
rename src/core/{measure_task => tasks}/dim_core_measure_module.c (100%)
|
|
rename src/core/{measure_task/dim_core_measure_task.c => tasks/dim_core_measure_process/dim_core_measure_process.c} (51%)
|
|
create mode 100644 src/core/tasks/dim_core_measure_process/dim_core_measure_process.h
|
|
create mode 100644 src/core/tasks/dim_core_measure_process/dim_core_measure_process_elf.c
|
|
create mode 100644 src/core/tasks/dim_core_measure_process/dim_core_measure_process_vma.c
|
|
create mode 100644 src/core/tasks/dim_core_measure_process/dim_vm_hash.c
|
|
create mode 100644 src/core/tasks/dim_core_measure_process/dim_vm_hash.h
|
|
rename src/core/{measure_task => tasks}/dim_core_measure_task.h (74%)
|
|
|
|
diff --git a/src/Makefile b/src/Makefile
|
|
index 8f94052..af058d9 100644
|
|
--- a/src/Makefile
|
|
+++ b/src/Makefile
|
|
@@ -9,13 +9,20 @@ dim_core-objs += core/dim_core_mem_pool.o
|
|
dim_core-objs += core/dim_core_measure.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 += core/static_baseline/dim_core_static_baseline.o
|
|
dim_core-objs += core/static_baseline/dim_core_static_baseline_complex.o
|
|
+dim_core-objs += core/tasks/dim_core_measure_kernel.o
|
|
+dim_core-objs += core/tasks/dim_core_measure_module.o
|
|
+dim_core-objs += core/tasks/dim_core_measure_process/dim_core_measure_process_elf.o
|
|
+dim_core-objs += core/tasks/dim_core_measure_process/dim_core_measure_process_vma.o
|
|
+dim_core-objs += core/tasks/dim_core_measure_process/dim_core_measure_process.o
|
|
+dim_core-objs += core/tasks/dim_core_measure_process/dim_vm_hash.o
|
|
+
|
|
dim_core-objs += core/policy/dim_core_policy.o
|
|
dim_core-objs += core/policy/dim_core_policy_complex.o
|
|
+dim_core-objs += core/static_baseline/dim_core_static_baseline.o
|
|
+dim_core-objs += core/static_baseline/dim_core_static_baseline_complex.o
|
|
+
|
|
dim_core-objs += common/dim_entry.o
|
|
dim_core-objs += common/dim_utils.o
|
|
dim_core-objs += common/dim_baseline.o
|
|
@@ -50,14 +57,15 @@ dim_monitor-objs += monitor/measure_task/dim_monitor_measure_text.o
|
|
|
|
ccflags-y := -I$(src)/core
|
|
ccflags-y += -I$(src)/core/static_baseline
|
|
-ccflags-y += -I$(src)/core/measure_task
|
|
+ccflags-y += -I$(src)/core/tasks
|
|
+ccflags-y += -I$(src)/core/tasks/dim_core_measure_process
|
|
ccflags-y += -I$(src)/core/policy
|
|
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
|
|
+EXTRA_CFLAGS += -Wall -Werror -D_FORTIFY_SOURCE=2 -O2 -fstack-protector-strong
|
|
|
|
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
|
|
PWD := $(shell pwd)
|
|
diff --git a/src/core/measure_task/dim_core_measure_kernel.c b/src/core/tasks/dim_core_measure_kernel.c
|
|
similarity index 100%
|
|
rename from src/core/measure_task/dim_core_measure_kernel.c
|
|
rename to src/core/tasks/dim_core_measure_kernel.c
|
|
diff --git a/src/core/measure_task/dim_core_measure_module.c b/src/core/tasks/dim_core_measure_module.c
|
|
similarity index 100%
|
|
rename from src/core/measure_task/dim_core_measure_module.c
|
|
rename to src/core/tasks/dim_core_measure_module.c
|
|
diff --git a/src/core/measure_task/dim_core_measure_task.c b/src/core/tasks/dim_core_measure_process/dim_core_measure_process.c
|
|
similarity index 51%
|
|
rename from src/core/measure_task/dim_core_measure_task.c
|
|
rename to src/core/tasks/dim_core_measure_process/dim_core_measure_process.c
|
|
index c9d21b1..513f5a0 100644
|
|
--- a/src/core/measure_task/dim_core_measure_task.c
|
|
+++ b/src/core/tasks/dim_core_measure_process/dim_core_measure_process.c
|
|
@@ -7,8 +7,6 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/mm_types.h>
|
|
#include <linux/vmalloc.h>
|
|
-#include <linux/highmem.h>
|
|
-#include <linux/hugetlb_inline.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/version.h>
|
|
|
|
@@ -21,26 +19,11 @@
|
|
#include "dim_core_measure.h"
|
|
|
|
#include "dim_core_measure_task.h"
|
|
+#include "dim_core_measure_process.h"
|
|
|
|
-/* max number of kill tasks */
|
|
+/* max number of tasks to kill */
|
|
#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;
|
|
@@ -48,86 +31,6 @@ struct task_kill_ctx {
|
|
int ret;
|
|
};
|
|
|
|
-typedef int (*task_measurer)(struct task_struct *, struct task_measure_ctx *);
|
|
-
|
|
-static struct file *get_vm_file(struct vm_area_struct *vma)
|
|
-{
|
|
-#ifdef CONFIG_EULEROS_EXEC_HUGEPAGES
|
|
- if (is_vm_exec_hugepages(vma) && vma->vm_real_file != NULL)
|
|
- return vma->vm_real_file;
|
|
-#endif
|
|
- return vma->vm_file;
|
|
-}
|
|
-
|
|
-/* Dont process vsyscall and vdso vma currently */
|
|
-static bool vma_is_special_text(struct vm_area_struct *vma)
|
|
-{
|
|
- const char *name = NULL;
|
|
-
|
|
- if (vma->vm_ops == NULL || vma->vm_ops->name == NULL)
|
|
- return false;
|
|
-
|
|
- name = vma->vm_ops->name(vma);
|
|
- if (name == NULL)
|
|
- return false;
|
|
-
|
|
- return (strcmp(name, "[vsyscall]") == 0) ||
|
|
- (strcmp(name, "[vdso]") == 0);
|
|
-}
|
|
-
|
|
-static inline bool vma_is_text(struct vm_area_struct *vma)
|
|
-{
|
|
- return (vma->vm_flags & VM_READ) && (vma->vm_flags & VM_EXEC) &&
|
|
- !(vma->vm_flags & VM_WRITE) && !vma_is_special_text(vma);
|
|
-}
|
|
-
|
|
-static inline bool vma_is_file_text(struct vm_area_struct *vma)
|
|
-{
|
|
- return vma_is_text(vma) && get_vm_file(vma) != NULL;
|
|
-}
|
|
-
|
|
-static inline bool vma_is_anon_text(struct vm_area_struct *vma)
|
|
-{
|
|
- return vma_is_text(vma) && get_vm_file(vma) == NULL;
|
|
-}
|
|
-
|
|
-static inline bool vma_file_is_same(struct vm_area_struct *first,
|
|
- struct vm_area_struct *second)
|
|
-{
|
|
- return get_vm_file(first) == get_vm_file(second);
|
|
-}
|
|
-
|
|
-static inline bool vma_can_merge(struct vm_area_struct *first,
|
|
- struct vm_area_struct *second)
|
|
-{
|
|
- return (first->vm_end == second->vm_start) &&
|
|
- (vma_file_is_same(first, second));
|
|
-}
|
|
-
|
|
-static inline bool vma_is_not_same_module(struct vm_area_struct *a,
|
|
- struct vm_area_struct *b)
|
|
-{
|
|
- struct file *fa = get_vm_file(a);
|
|
- struct file *fb = get_vm_file(b);
|
|
- return (fa != NULL && fb != NULL && fa != fb);
|
|
-}
|
|
-
|
|
-static struct vm_area_struct *next_file_text_vma(struct vm_area_struct *vma)
|
|
-{
|
|
- struct vm_area_struct *v = NULL;
|
|
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
- for (v = vma->vm_next; v != NULL &&
|
|
- !vma_is_file_text(v); v = v->vm_next) {}
|
|
-#else
|
|
- VMA_ITERATOR(vmi, vma->vm_mm, vma->vm_end);
|
|
- for_each_vma(vmi, v) {
|
|
- if (vma_is_file_text(v))
|
|
- break;
|
|
- }
|
|
-#endif
|
|
- return v;
|
|
-}
|
|
-
|
|
static struct vm_area_struct *next_module_text_vma(struct vm_area_struct *vma)
|
|
{
|
|
struct vm_area_struct *v = NULL;
|
|
@@ -145,25 +48,6 @@ static struct vm_area_struct *next_module_text_vma(struct vm_area_struct *vma)
|
|
return v;
|
|
}
|
|
|
|
-static struct vm_area_struct *find_text_vma_end(struct vm_area_struct *vma)
|
|
-{
|
|
- struct vm_area_struct *v = NULL;
|
|
- struct vm_area_struct *vma_end = vma;
|
|
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
- for (v = vma->vm_next; v != NULL &&
|
|
- vma_can_merge(vma_end, v); v = v->vm_next) {}
|
|
-#else
|
|
- VMA_ITERATOR(vmi, vma->vm_mm, vma->vm_end);
|
|
- for_each_vma(vmi, v) {
|
|
- if (!vma_is_file_text(v) || !vma_can_merge(vma_end, v))
|
|
- break;
|
|
-
|
|
- vma_end = v;
|
|
- }
|
|
-#endif
|
|
- return vma_end;
|
|
-}
|
|
-
|
|
static int store_task_tree(struct task_struct *p, void *data)
|
|
{
|
|
unsigned int new_size = 0;
|
|
@@ -233,58 +117,16 @@ static bool vm_file_match_policy(struct file *vm_file,
|
|
DIM_BASELINE_USER, &dig) == 0;
|
|
}
|
|
|
|
-static int update_vma_digest(struct vm_area_struct *vma_start,
|
|
- struct vm_area_struct *vma_end,
|
|
- struct shash_desc *shash)
|
|
-{
|
|
- long i;
|
|
- long ret_pages = 0;
|
|
- void *page_ptr = NULL;
|
|
- struct page **pages = NULL;
|
|
- unsigned long addr_start = vma_start->vm_start;
|
|
- unsigned long addr_end = vma_end->vm_end;
|
|
- unsigned long addr_len = addr_end - addr_start;
|
|
- unsigned long nr_pages = DIV_ROUND_UP(addr_len, PAGE_SIZE);
|
|
-
|
|
- pages = vzalloc(nr_pages * sizeof(struct page *));
|
|
- if (pages == NULL)
|
|
- return -ENOMEM;
|
|
-
|
|
- ret_pages = get_user_pages_remote(vma_start->vm_mm, addr_start, nr_pages,
|
|
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(6,4,0)
|
|
- 0, pages, NULL, NULL);
|
|
-#else
|
|
- 0, pages, NULL);
|
|
-#endif
|
|
- if (ret_pages < 0) {
|
|
- dim_err("failed to get vma pages: %ld\n", ret_pages);
|
|
- vfree(pages);
|
|
- return ret_pages;
|
|
- }
|
|
-
|
|
- for (i = 0; i < ret_pages; i++) {
|
|
- page_ptr = kmap(pages[i]);
|
|
- if (page_ptr == NULL) {
|
|
- dim_err("failed to kmap page\n");
|
|
- put_page(pages[i]);
|
|
- continue;
|
|
- }
|
|
-
|
|
- (void)crypto_shash_update(shash, page_ptr, PAGE_SIZE);
|
|
- kunmap(pages[i]);
|
|
- put_page(pages[i]);
|
|
- }
|
|
-
|
|
- vfree(pages);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int check_user_digest(struct dim_digest *digest,
|
|
- struct task_measure_ctx *ctx)
|
|
+static int check_process_digest(struct dim_digest *digest,
|
|
+ void *data)
|
|
{
|
|
int ret = 0;
|
|
int log_flag = 0;
|
|
int action = 0;
|
|
+ struct task_measure_ctx *ctx = data;
|
|
+
|
|
+ if (digest == NULL || data == NULL)
|
|
+ return -EINVAL;
|
|
|
|
ret = dim_measure_process_static_result(ctx->m, ctx->mode, ctx->path,
|
|
digest, &log_flag);
|
|
@@ -308,91 +150,6 @@ static int check_user_digest(struct dim_digest *digest,
|
|
return 0;
|
|
}
|
|
|
|
-#ifdef DIM_CORE_MEASURE_ANON_TEXT
|
|
-static int measure_anon_text_vma(struct vm_area_struct *vma,
|
|
- struct task_measure_ctx *ctx)
|
|
-{
|
|
- int ret = 0;
|
|
- struct dim_digest digest = {
|
|
- .algo = ctx->m->hash.algo,
|
|
- };
|
|
- SHASH_DESC_ON_STACK(shash, ctx->hash.tfm);
|
|
-
|
|
- shash->tfm = ctx->hash.tfm;
|
|
- ret = crypto_shash_init(shash);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- ret = update_vma_digest(vma, vma, shash);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- ret = crypto_shash_final(shash, digest.data);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- return check_user_digest(&digest, ctx);
|
|
-}
|
|
-
|
|
-/* For anonymous text segment, measure individual vma */
|
|
-static int measure_task_module_anon_text(struct vm_area_struct *vma,
|
|
- struct task_measure_ctx *ctx)
|
|
-{
|
|
- int ret = 0;
|
|
- struct vm_area_struct *v = vma;
|
|
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
- for (; v != NULL && !vma_is_not_same_module(v, vma); v = v->vm_next) {
|
|
-#else
|
|
- VMA_ITERATOR(vmi, vma->vm_mm, vma->vm_start);
|
|
- for_each_vma(vmi, v) {
|
|
- if (vma_is_not_same_module(v, vma))
|
|
- break;
|
|
-#endif
|
|
- if (!vma_is_anon_text(v))
|
|
- continue;
|
|
-
|
|
- ret = measure_anon_text_vma(v, ctx);
|
|
- if (ret < 0)
|
|
- dim_err("failed to measure anon text vma: %d\n", ret);
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-#endif
|
|
-
|
|
-/* For file text segment, merge all file mapping text vma and measure */
|
|
-static int measure_task_module_file_text(struct vm_area_struct *vma,
|
|
- struct task_measure_ctx *ctx)
|
|
-{
|
|
- int ret = 0;
|
|
- struct vm_area_struct *v = vma;
|
|
- struct vm_area_struct *v_end = NULL;
|
|
- struct dim_digest digest = {
|
|
- .algo = ctx->m->hash.algo
|
|
- };
|
|
- SHASH_DESC_ON_STACK(shash, ctx->m->hash.tfm);
|
|
-
|
|
- shash->tfm = ctx->m->hash.tfm;
|
|
- ret = crypto_shash_init(shash);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- while (v != NULL && vma_file_is_same(v, vma)) {
|
|
- v_end = find_text_vma_end(v);
|
|
- ret = update_vma_digest(v, v_end, shash);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- v = next_file_text_vma(v_end);
|
|
- }
|
|
-
|
|
- ret = crypto_shash_final(shash, digest.data);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- return check_user_digest(&digest, ctx);
|
|
-}
|
|
-
|
|
static void measure_task_module(struct vm_area_struct *vma,
|
|
struct task_measure_ctx *ctx)
|
|
{
|
|
@@ -405,14 +162,11 @@ static void measure_task_module(struct vm_area_struct *vma,
|
|
|
|
ctx->task_measure = true;
|
|
|
|
- ret = measure_task_module_file_text(vma, ctx);
|
|
+ /* now we only measure the text memory */
|
|
+ ret = measure_process_text(vma, ctx);
|
|
if (ret < 0)
|
|
dim_err("failed to measure module file text: %d", ret);
|
|
-#ifdef DIM_CORE_MEASURE_ANON_TEXT
|
|
- ret = measure_task_module_anon_text(vma, ctx);
|
|
- if (ret < 0)
|
|
- dim_err("failed to measure module anon text: %d", ret);
|
|
-#endif
|
|
+
|
|
}
|
|
|
|
static int measure_task(struct task_struct *task, struct task_measure_ctx *ctx)
|
|
@@ -510,7 +264,7 @@ static int store_task_pids(pid_t **pid_buf, unsigned int *pid_cnt)
|
|
return 0;
|
|
}
|
|
|
|
-static int walk_tasks(task_measurer f, struct task_measure_ctx *ctx)
|
|
+static int walk_measure_tasks(struct task_measure_ctx *ctx)
|
|
{
|
|
int ret = 0;
|
|
unsigned int i = 0;
|
|
@@ -531,7 +285,7 @@ static int walk_tasks(task_measurer f, struct task_measure_ctx *ctx)
|
|
if (task == NULL)
|
|
continue;
|
|
|
|
- ret = f(task, ctx);
|
|
+ ret = measure_task(task, ctx);
|
|
put_task_struct(task);
|
|
if (ret < 0) {
|
|
dim_err("failed to measure task, pid = %d: %d", pid_buf[i], ret);
|
|
@@ -546,6 +300,7 @@ static int walk_tasks(task_measurer f, struct task_measure_ctx *ctx)
|
|
|
|
static int user_text_measure(int mode, struct dim_measure *m)
|
|
{
|
|
+ int ret = 0;
|
|
struct task_measure_ctx *ctx = NULL;
|
|
|
|
if (m == NULL)
|
|
@@ -557,7 +312,11 @@ static int user_text_measure(int mode, struct dim_measure *m)
|
|
|
|
ctx->mode = mode;
|
|
ctx->m = m;
|
|
- return walk_tasks(measure_task, ctx);
|
|
+ ctx->check = check_process_digest;
|
|
+
|
|
+ ret = walk_measure_tasks(ctx);
|
|
+ vfree(ctx);
|
|
+ return ret;
|
|
}
|
|
|
|
struct dim_measure_task dim_core_measure_task_user_text = {
|
|
diff --git a/src/core/tasks/dim_core_measure_process/dim_core_measure_process.h b/src/core/tasks/dim_core_measure_process/dim_core_measure_process.h
|
|
new file mode 100644
|
|
index 0000000..6d2ceba
|
|
--- /dev/null
|
|
+++ b/src/core/tasks/dim_core_measure_process/dim_core_measure_process.h
|
|
@@ -0,0 +1,82 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __DIM_CORE_MEASURE_PROCESS_H
|
|
+#define __DIM_CORE_MEASURE_PROCESS_H
|
|
+
|
|
+#include <linux/fs.h>
|
|
+#include <linux/mm.h>
|
|
+
|
|
+/* callback funtion to check results when do measurement */
|
|
+typedef int (*process_digest_check_func) (struct dim_digest *digest,
|
|
+ void *ctx);
|
|
+
|
|
+/* the context used in user process measurement */
|
|
+struct task_measure_ctx {
|
|
+ struct dim_measure *m;
|
|
+ /* DIM_BASELINE or DIM_MEASURE */
|
|
+ int mode;
|
|
+ char path_buf[PATH_MAX];
|
|
+ /* current measured process name */
|
|
+ const char *path;
|
|
+ /* current measured process */
|
|
+ struct task_struct *task;
|
|
+ /* this process need to be killed */
|
|
+ bool task_kill;
|
|
+ /* this process is measured */
|
|
+ bool task_measure;
|
|
+ /* check function */
|
|
+ process_digest_check_func check;
|
|
+};
|
|
+
|
|
+static inline struct file *get_vm_file(struct vm_area_struct *vma)
|
|
+{
|
|
+ return vma == NULL ? NULL : vma->vm_file;
|
|
+}
|
|
+
|
|
+static inline bool vma_is_text(struct vm_area_struct *vma)
|
|
+{
|
|
+ return (vma->vm_flags & VM_READ) && (vma->vm_flags & VM_EXEC) &&
|
|
+ !(vma->vm_flags & VM_WRITE);
|
|
+}
|
|
+
|
|
+static inline bool vma_is_file_text(struct vm_area_struct *vma)
|
|
+{
|
|
+ return vma_is_text(vma) && get_vm_file(vma) != NULL;
|
|
+}
|
|
+
|
|
+static inline bool vma_file_is_same(struct vm_area_struct *first,
|
|
+ struct vm_area_struct *second)
|
|
+{
|
|
+ return get_vm_file(first) == get_vm_file(second);
|
|
+}
|
|
+
|
|
+static inline bool vma_can_merge(struct vm_area_struct *first,
|
|
+ struct vm_area_struct *second)
|
|
+{
|
|
+ return (first->vm_end == second->vm_start) &&
|
|
+ (vma_file_is_same(first, second));
|
|
+}
|
|
+
|
|
+static inline bool vma_is_not_same_module(struct vm_area_struct *a,
|
|
+ struct vm_area_struct *b)
|
|
+{
|
|
+ struct file *fa = get_vm_file(a);
|
|
+ struct file *fb = get_vm_file(b);
|
|
+ return (fa != NULL && fb != NULL && fa != fb);
|
|
+}
|
|
+
|
|
+#ifdef DIM_CORE_MEASURE_PROCESS_ELF
|
|
+int measure_process_module_text_elf(struct vm_area_struct *vma,
|
|
+ struct task_measure_ctx *ctx);
|
|
+#define measure_process_text measure_process_module_text_elf
|
|
+#else
|
|
+int measure_process_module_text_vma(struct vm_area_struct *vma,
|
|
+ struct task_measure_ctx *ctx);
|
|
+#define measure_process_text measure_process_module_text_vma
|
|
+#endif
|
|
+
|
|
+extern struct dim_measure_task dim_core_measure_task_user_text;
|
|
+
|
|
+#endif
|
|
\ No newline at end of file
|
|
diff --git a/src/core/tasks/dim_core_measure_process/dim_core_measure_process_elf.c b/src/core/tasks/dim_core_measure_process/dim_core_measure_process_elf.c
|
|
new file mode 100644
|
|
index 0000000..9210f47
|
|
--- /dev/null
|
|
+++ b/src/core/tasks/dim_core_measure_process/dim_core_measure_process_elf.c
|
|
@@ -0,0 +1,338 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include <linux/elf.h>
|
|
+#include <linux/fs.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/vmalloc.h>
|
|
+
|
|
+#include "dim_hash.h"
|
|
+#include "dim_utils.h"
|
|
+#include "dim_measure.h"
|
|
+
|
|
+#include "dim_vm_hash.h"
|
|
+#include "dim_core_measure_process.h"
|
|
+
|
|
+#define TRAMPOLINE_SECTION_NAME ".vos_patch_trampoline_seg"
|
|
+
|
|
+static inline bool is_text_phdr(struct elf_phdr *phdr)
|
|
+{
|
|
+ return (phdr->p_type == PT_LOAD) && (phdr->p_flags & PF_R) &&
|
|
+ (phdr->p_flags & PF_X) && !(phdr->p_flags & PF_W);
|
|
+}
|
|
+
|
|
+/* parse ELF header from an ELF file */
|
|
+static int get_elf_ehdr(struct file *elf_file, struct elfhdr *ehdr)
|
|
+{
|
|
+ loff_t pos = 0;
|
|
+ ssize_t size = 0;
|
|
+
|
|
+ size = kernel_read(elf_file, ehdr, sizeof(struct elfhdr), &pos);
|
|
+ if (size != sizeof(struct elfhdr))
|
|
+ return size < 0 ? (int)size : -EIO;
|
|
+
|
|
+ /* check elf header valid, now we only support the little end */
|
|
+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0 ||
|
|
+ ehdr->e_ident[EI_CLASS] != ELF_CLASS ||
|
|
+ ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
|
|
+ (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN))
|
|
+ return -ENOEXEC;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* parse ELF phders from an ELF file */
|
|
+static int get_elf_phdrs(struct file *elf_file, struct elfhdr *ehdr,
|
|
+ struct elf_phdr **phdrs, unsigned int *num)
|
|
+{
|
|
+ struct elf_phdr *elf_phdata = NULL;
|
|
+ size_t phdr_size = 0;
|
|
+ ssize_t read_size = 0;
|
|
+
|
|
+ if (ehdr->e_phentsize != sizeof(struct elf_phdr) ||
|
|
+ ehdr->e_phnum < 1 ||
|
|
+ ehdr->e_phnum > 65536U / sizeof(struct elf_phdr))
|
|
+ return -ENOEXEC;
|
|
+
|
|
+ phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
|
|
+ elf_phdata = dim_kmalloc_gfp(phdr_size);
|
|
+ if (elf_phdata == NULL)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ read_size = kernel_read(elf_file, elf_phdata, phdr_size,
|
|
+ &ehdr->e_phoff);
|
|
+ if (read_size != phdr_size) {
|
|
+ dim_kfree(elf_phdata);
|
|
+ return read_size < 0 ? (int)read_size : -EIO;
|
|
+ }
|
|
+
|
|
+ *phdrs = elf_phdata;
|
|
+ *num = ehdr->e_phnum;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* parse ELF section by name from an ELF file */
|
|
+static int get_elf_section(struct file *elf_file, struct elfhdr *ehdr,
|
|
+ const char *name, struct elf_shdr *shdr)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int i = 0;
|
|
+ ssize_t size = 0;
|
|
+ ssize_t name_len = 0;
|
|
+ ssize_t str_size = 0;
|
|
+ struct elf_shdr *sh_table = NULL;
|
|
+ char *sh_str = NULL;
|
|
+ loff_t pos;
|
|
+
|
|
+ if (ehdr->e_shentsize != sizeof(struct elf_shdr))
|
|
+ return -EBADF;
|
|
+
|
|
+ sh_table = dim_kmalloc_gfp(ehdr->e_shentsize);
|
|
+ if (sh_table == NULL)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ /* find the shdr for section name */
|
|
+ pos = ehdr->e_shoff + ehdr->e_shentsize * ehdr->e_shstrndx;
|
|
+ size = kernel_read(elf_file, sh_table, ehdr->e_shentsize, &pos);
|
|
+ if (size != ehdr->e_shentsize) {
|
|
+ dim_kfree(sh_table);
|
|
+ return size < 0 ? (int)size : -EBADF;
|
|
+ }
|
|
+
|
|
+ str_size = sh_table->sh_size;
|
|
+ if (str_size > i_size_read(file_inode(elf_file))) {
|
|
+ kfree(sh_table);
|
|
+ return -EBADF;
|
|
+ }
|
|
+
|
|
+ sh_str = vmalloc(str_size);
|
|
+ if (sh_str == NULL) {
|
|
+ kfree(sh_table);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ pos = sh_table->sh_offset;
|
|
+ size = kernel_read(elf_file, sh_str, sh_table->sh_size, &pos);
|
|
+ if (size != sh_table->sh_size) {
|
|
+ kfree(sh_table);
|
|
+ vfree(sh_str);
|
|
+ return size < 0 ? (int)size : -EBADF;
|
|
+ }
|
|
+
|
|
+ ret = -ENOENT;
|
|
+ pos = ehdr->e_shoff;
|
|
+ name_len = strlen(name);
|
|
+ for (i = 0; i < ehdr->e_shnum; i++) {
|
|
+ size = kernel_read(elf_file, sh_table, ehdr->e_shentsize, &pos);
|
|
+ if (size != ehdr->e_shentsize) {
|
|
+ ret = size < 0 ? (int)size : -EBADF;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (sh_table->sh_name + name_len < sh_table->sh_name ||
|
|
+ sh_table->sh_name + name_len >= str_size)
|
|
+ break;
|
|
+
|
|
+ if (strcmp(name, sh_str + sh_table->sh_name) == 0) {
|
|
+ memcpy(shdr, sh_table, sizeof(struct elf_shdr));
|
|
+ ret = 0;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ kfree(sh_table);
|
|
+ vfree(sh_str);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int get_elf_text_phdrs(struct file *elf_file,
|
|
+ struct elfhdr *ehdr,
|
|
+ struct elf_phdr **phdrs_find,
|
|
+ unsigned int *phdrs_find_num)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int i = 0;
|
|
+ struct elf_phdr *phdr = NULL;
|
|
+ unsigned int phdr_idx = 0;
|
|
+ struct elf_phdr *phdrs_get = NULL;
|
|
+ unsigned int phdrs_get_num = 0;
|
|
+ struct elf_phdr *phdrs_text = NULL;
|
|
+ unsigned int phdrs_text_num = 0;
|
|
+
|
|
+ /* get all elf program headers */
|
|
+ ret = get_elf_phdrs(elf_file, ehdr, &phdrs_get, &phdrs_get_num);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ /* get the number of the text phdr */
|
|
+ for (i = 0, phdr = phdrs_get; i < phdrs_get_num; i++, phdr++) {
|
|
+ if (!is_text_phdr(phdr))
|
|
+ continue;
|
|
+ phdrs_text_num++;
|
|
+ }
|
|
+
|
|
+ if (phdrs_text_num == 0) {
|
|
+ dim_kfree(phdrs_get);
|
|
+ return -ENOEXEC;
|
|
+ }
|
|
+
|
|
+ /* alloc memory buffer for phdrs */
|
|
+ phdrs_text = dim_kmalloc_gfp(phdrs_text_num * sizeof(struct elf_phdr));
|
|
+ if (phdrs_text == NULL) {
|
|
+ dim_kfree(phdrs_get);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ /* store the text phdrs */
|
|
+ for (i = 0, phdr = phdrs_get; i < phdrs_get_num; i++, phdr++) {
|
|
+ if (!is_text_phdr(phdr))
|
|
+ continue;
|
|
+
|
|
+ memcpy(&phdrs_text[phdr_idx], phdr, sizeof(struct elf_phdr));
|
|
+ if (++phdr_idx >= phdrs_text_num)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ *phdrs_find = phdrs_text;
|
|
+ *phdrs_find_num = phdrs_text_num;
|
|
+ dim_kfree(phdrs_get);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int get_elf_measure_area(struct file *elf_file,
|
|
+ struct elf_phdr **phdrs_text,
|
|
+ unsigned int *phdrs_text_num,
|
|
+ struct elf_shdr *shdr_trampoline,
|
|
+ bool *shdr_trampoline_find)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct elfhdr ehdr = { 0 };
|
|
+
|
|
+ ret = get_elf_ehdr(elf_file, &ehdr);
|
|
+ if (ret < 0) {
|
|
+ dim_err("fail to get ELF header: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = get_elf_text_phdrs(elf_file, &ehdr, phdrs_text, phdrs_text_num);
|
|
+ if (ret < 0) {
|
|
+ dim_err("fail to get ELF text phdrs: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ // TODO
|
|
+ ret = get_elf_section(elf_file, &ehdr, TRAMPOLINE_SECTION_NAME, shdr_trampoline);
|
|
+ if (ret == 0)
|
|
+ *shdr_trampoline_find = true;
|
|
+ else if (ret < 0 && ret != -ENOENT)
|
|
+ dim_warn("fail to get ELF trampoline shdr: %d\n", ret);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int measure_elf_trampoline(struct vm_area_struct *vma,
|
|
+ struct elf_shdr *shdr_trampoline,
|
|
+ struct task_measure_ctx *ctx)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct vm_area_struct *vma_trampoline = NULL;
|
|
+ unsigned long addr_trampoline = 0;
|
|
+ struct dim_digest digest = {
|
|
+ .algo = ctx->m->hash.algo,
|
|
+ };
|
|
+
|
|
+ addr_trampoline = vma->vm_start + shdr_trampoline->sh_addr;
|
|
+ vma_trampoline = find_vma(vma->vm_mm, addr_trampoline);
|
|
+ if (vma_trampoline == NULL || !vma_is_text(vma_trampoline) ||
|
|
+ vma_trampoline->vm_start != addr_trampoline)
|
|
+ return -ENOENT;
|
|
+
|
|
+ ret = dim_vm_hash_calculate_vma(vma_trampoline, &ctx->m->hash, &digest);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to calculate trampoline vma digest\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return ctx->check(&digest, ctx);
|
|
+}
|
|
+
|
|
+static int measure_elf_text(struct vm_area_struct *vma,
|
|
+ struct elf_phdr *phdrs_text,
|
|
+ unsigned int phdrs_text_num,
|
|
+ struct task_measure_ctx *ctx)
|
|
+{
|
|
+ int ret = 0;
|
|
+ unsigned int i = 0;
|
|
+ unsigned long addr = 0;
|
|
+ struct elf_phdr *phdr = NULL;
|
|
+ struct dim_digest digest = {
|
|
+ .algo = ctx->m->hash.algo,
|
|
+ };
|
|
+ SHASH_DESC_ON_STACK(shash, ctx->m->hash.tfm);
|
|
+
|
|
+ shash->tfm = ctx->m->hash.tfm;
|
|
+ ret = crypto_shash_init(shash);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ for (; i < phdrs_text_num; i++) {
|
|
+ phdr = &phdrs_text[i];
|
|
+ addr = vma->vm_start + phdr->p_vaddr - vma->vm_pgoff * PAGE_SIZE;
|
|
+ ret = dim_vm_hash_update_address(vma->vm_mm, addr,
|
|
+ phdr->p_memsz, shash);
|
|
+ if (ret < 0)
|
|
+ dim_err("failed to update elf text: %d\n", ret);
|
|
+ }
|
|
+
|
|
+ ret = crypto_shash_final(shash, digest.data);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ return ctx->check(&digest, ctx);
|
|
+}
|
|
+
|
|
+int measure_process_module_text_elf(struct vm_area_struct *vma,
|
|
+ struct task_measure_ctx *ctx)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct file *elf_file = get_vm_file(vma);
|
|
+ struct elf_phdr *phdrs_text = NULL;
|
|
+ unsigned int phdrs_text_num = 0;
|
|
+ struct elf_shdr shdr_trampoline = { 0 };
|
|
+ bool shdr_trampoline_find = false;
|
|
+
|
|
+ if (vma == NULL || !vma_is_file_text(vma) || ctx == NULL
|
|
+ || ctx->m == NULL || ctx->check == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (elf_file == NULL) {
|
|
+ dim_err("failed to get elf file from vma\n");
|
|
+ return -ENOEXEC;
|
|
+ }
|
|
+
|
|
+ ret = get_elf_measure_area(elf_file, &phdrs_text, &phdrs_text_num,
|
|
+ &shdr_trampoline, &shdr_trampoline_find);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to get elf measure area from vma\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = measure_elf_text(vma, phdrs_text, phdrs_text_num, ctx);
|
|
+ dim_kfree(phdrs_text);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to measure elf text: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (shdr_trampoline_find) {
|
|
+ ret = measure_elf_trampoline(vma, &shdr_trampoline, ctx);
|
|
+ if (ret < 0) {
|
|
+ dim_err("failed to measure elf trampoline: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/src/core/tasks/dim_core_measure_process/dim_core_measure_process_vma.c b/src/core/tasks/dim_core_measure_process/dim_core_measure_process_vma.c
|
|
new file mode 100644
|
|
index 0000000..d3ba241
|
|
--- /dev/null
|
|
+++ b/src/core/tasks/dim_core_measure_process/dim_core_measure_process_vma.c
|
|
@@ -0,0 +1,93 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include <linux/version.h>
|
|
+#include <linux/mm.h>
|
|
+
|
|
+#include "dim_measure.h"
|
|
+#include "dim_vm_hash.h"
|
|
+#include "dim_core_measure_process.h"
|
|
+
|
|
+static struct vm_area_struct *find_text_vma_end(struct vm_area_struct *vma)
|
|
+{
|
|
+ struct vm_area_struct *v = NULL;
|
|
+ struct vm_area_struct *vma_end = vma;
|
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
+ for (v = vma->vm_next; v != NULL && vma_is_file_text(v) &&
|
|
+ vma_can_merge(vma_end, v); v = v->vm_next)
|
|
+ vma_end = v;
|
|
+#else
|
|
+ VMA_ITERATOR(vmi, vma->vm_mm, vma->vm_end);
|
|
+ for_each_vma(vmi, v) {
|
|
+ if (!vma_is_file_text(v) || !vma_can_merge(vma_end, v))
|
|
+ break;
|
|
+
|
|
+ vma_end = v;
|
|
+ }
|
|
+#endif
|
|
+ return vma_end;
|
|
+}
|
|
+
|
|
+static struct vm_area_struct *next_file_text_vma(struct vm_area_struct *vma)
|
|
+{
|
|
+ struct vm_area_struct *v = NULL;
|
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
|
+ for (v = vma->vm_next; v != NULL &&
|
|
+ !vma_is_file_text(v); v = v->vm_next) {}
|
|
+#else
|
|
+ VMA_ITERATOR(vmi, vma->vm_mm, vma->vm_end);
|
|
+ for_each_vma(vmi, v) {
|
|
+ if (vma_is_file_text(v))
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (!vma_is_file_text(v))
|
|
+ v = NULL;
|
|
+#endif
|
|
+ return v;
|
|
+}
|
|
+
|
|
+/* For file text segment, merge all file mapping text vma and measure */
|
|
+int measure_text_vma(struct vm_area_struct *vma, struct task_measure_ctx *ctx)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct vm_area_struct *v = vma;
|
|
+ struct vm_area_struct *v_end = NULL;
|
|
+ struct dim_digest digest = {
|
|
+ .algo = ctx->m->hash.algo
|
|
+ };
|
|
+ SHASH_DESC_ON_STACK(shash, ctx->m->hash.tfm);
|
|
+
|
|
+ shash->tfm = ctx->m->hash.tfm;
|
|
+ ret = crypto_shash_init(shash);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ /* now the vma is the first file text vma of a process module */
|
|
+ while (v != NULL && vma_file_is_same(v, vma)) {
|
|
+ v_end = find_text_vma_end(v);
|
|
+ /* update all the continuous text vma */
|
|
+ ret = dim_vm_hash_update_vmas(v, v_end, shash);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ v = next_file_text_vma(v_end);
|
|
+ }
|
|
+
|
|
+ ret = crypto_shash_final(shash, digest.data);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ return ctx->check(&digest, ctx);
|
|
+}
|
|
+
|
|
+int measure_process_module_text_vma(struct vm_area_struct *vma,
|
|
+ struct task_measure_ctx *ctx)
|
|
+{
|
|
+ if (vma == NULL || !vma_is_file_text(vma) || ctx == NULL
|
|
+ || ctx->m == NULL || ctx->check == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return measure_text_vma(vma, ctx);
|
|
+}
|
|
diff --git a/src/core/tasks/dim_core_measure_process/dim_vm_hash.c b/src/core/tasks/dim_core_measure_process/dim_vm_hash.c
|
|
new file mode 100644
|
|
index 0000000..0c59b9e
|
|
--- /dev/null
|
|
+++ b/src/core/tasks/dim_core_measure_process/dim_vm_hash.c
|
|
@@ -0,0 +1,107 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include <linux/version.h>
|
|
+#include <linux/vmalloc.h>
|
|
+#include <linux/highmem.h>
|
|
+
|
|
+#include "dim_utils.h"
|
|
+
|
|
+#include "dim_vm_hash.h"
|
|
+
|
|
+int dim_vm_hash_update_address(struct mm_struct *mm,
|
|
+ unsigned long addr_start,
|
|
+ unsigned long addr_len,
|
|
+ struct shash_desc *shash)
|
|
+{
|
|
+ int ret = 0;
|
|
+ unsigned long i = 0;
|
|
+ long ret_pages = 0;
|
|
+ void *page_ptr = NULL;
|
|
+ struct page **pages = NULL;
|
|
+ unsigned int update_size = PAGE_SIZE;
|
|
+ unsigned long nr_pages = DIV_ROUND_UP(addr_len, PAGE_SIZE);
|
|
+
|
|
+ if (mm == NULL || addr_len == 0 || shash == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ pages = vzalloc(nr_pages * sizeof(struct page *));
|
|
+ if (pages == NULL)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ ret_pages = get_user_pages_remote(mm, addr_start, nr_pages,
|
|
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(6,4,0)
|
|
+ 0, pages, NULL, NULL);
|
|
+#else
|
|
+ 0, pages, NULL);
|
|
+#endif
|
|
+ if (ret_pages < 0) {
|
|
+ dim_err("failed to get remote pages: %ld\n", ret_pages);
|
|
+ vfree(pages);
|
|
+ return ret_pages;
|
|
+ } else if (ret_pages != nr_pages) {
|
|
+ dim_warn("failed to get all remote pages\n");
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < ret_pages; i++) {
|
|
+ page_ptr = kmap(pages[i]);
|
|
+ if (page_ptr == NULL) {
|
|
+ dim_err("failed to kmap remote page\n");
|
|
+ put_page(pages[i]);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (i == ret_pages - 1)
|
|
+ update_size = addr_len % PAGE_SIZE ?
|
|
+ addr_len % PAGE_SIZE : PAGE_SIZE;
|
|
+
|
|
+ ret = crypto_shash_update(shash, page_ptr, update_size);
|
|
+ if (ret < 0)
|
|
+ dim_warn("failed to update hash: %d\n", ret);
|
|
+
|
|
+ kunmap(pages[i]);
|
|
+ put_page(pages[i]);
|
|
+ }
|
|
+
|
|
+ vfree(pages);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* calculate hash digest of continuous vma */
|
|
+int dim_vm_hash_update_vmas(struct vm_area_struct *vma_start,
|
|
+ struct vm_area_struct *vma_end,
|
|
+ struct shash_desc *shash)
|
|
+{
|
|
+ if (vma_start == NULL || vma_end == NULL || shash == NULL ||
|
|
+ vma_start->vm_mm != vma_end->vm_mm ||
|
|
+ vma_start->vm_start >= vma_end->vm_end)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return dim_vm_hash_update_address(vma_start->vm_mm, vma_start->vm_start,
|
|
+ vma_end->vm_end - vma_start->vm_start, shash);
|
|
+}
|
|
+
|
|
+/* calculate hash digest of vma */
|
|
+int dim_vm_hash_calculate_vma(struct vm_area_struct *vma,
|
|
+ struct dim_hash *hash,
|
|
+ struct dim_digest *digest)
|
|
+{
|
|
+ int ret = 0;
|
|
+ /* check here to avoid code check warning */
|
|
+ SHASH_DESC_ON_STACK(shash, hash == NULL ? NULL : hash->tfm);
|
|
+
|
|
+ if (vma == NULL || hash == NULL || digest == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ shash->tfm = hash->tfm;
|
|
+ ret = crypto_shash_init(shash);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ ret = dim_vm_hash_update_vmas(vma, vma, shash);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ return crypto_shash_final(shash, digest->data);
|
|
+}
|
|
diff --git a/src/core/tasks/dim_core_measure_process/dim_vm_hash.h b/src/core/tasks/dim_core_measure_process/dim_vm_hash.h
|
|
new file mode 100644
|
|
index 0000000..7c996e9
|
|
--- /dev/null
|
|
+++ b/src/core/tasks/dim_core_measure_process/dim_vm_hash.h
|
|
@@ -0,0 +1,25 @@
|
|
+/*
|
|
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __DIM_VM_HASH_H
|
|
+#define __DIM_VM_HASH_H
|
|
+
|
|
+#include <linux/mm.h>
|
|
+
|
|
+#include "dim_hash.h"
|
|
+
|
|
+int dim_vm_hash_update_address(struct mm_struct *mm,
|
|
+ unsigned long addr_start,
|
|
+ unsigned long addr_len,
|
|
+ struct shash_desc *shash);
|
|
+
|
|
+int dim_vm_hash_update_vmas(struct vm_area_struct *vma_start,
|
|
+ struct vm_area_struct *vma_end,
|
|
+ struct shash_desc *shash);
|
|
+
|
|
+int dim_vm_hash_calculate_vma(struct vm_area_struct *vma,
|
|
+ struct dim_hash *hash,
|
|
+ struct dim_digest *digest);
|
|
+
|
|
+#endif
|
|
\ No newline at end of file
|
|
diff --git a/src/core/measure_task/dim_core_measure_task.h b/src/core/tasks/dim_core_measure_task.h
|
|
similarity index 74%
|
|
rename from src/core/measure_task/dim_core_measure_task.h
|
|
rename to src/core/tasks/dim_core_measure_task.h
|
|
index 0e26af2..145e0f3 100644
|
|
--- a/src/core/measure_task/dim_core_measure_task.h
|
|
+++ b/src/core/tasks/dim_core_measure_task.h
|
|
@@ -1,8 +1,9 @@
|
|
-#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
|
|
+#ifndef __DIM_CORE_MEASURE_TASK_H
|
|
+#define __DIM_CORE_MEASURE_TASK_H
|
|
+
|
|
+#include "dim_core_measure_process.h"
|
|
+
|
|
+extern struct dim_measure_task dim_core_measure_task_module_text;
|
|
+extern struct dim_measure_task dim_core_measure_task_kernel_text;
|
|
+
|
|
+#endif
|
|
--
|
|
2.33.0
|
|
|