1 Star 0 Fork 10

jinlun/dim_9

forked from src-openEuler/dim 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
backport-Support-user-process-measurement-by-ELF-parsing.patch 33.09 KB
一键复制 编辑 原始数据 按行查看 历史
jinlun 提交于 2024-04-16 10:12 . backport some patches
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
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
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jinlun123123/dim_9.git
git@gitee.com:jinlun123123/dim_9.git
jinlun123123
dim_9
dim_9
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385