diff --git a/memory_security/Kconfig b/memory_security/Kconfig index f3a27626b0b96736ae8369beafbcb91514320215..ba823947465e53a96bdaed3ab909165984abeca8 100755 --- a/memory_security/Kconfig +++ b/memory_security/Kconfig @@ -6,11 +6,25 @@ menu "Hide memory address manager" +config MEMORY_SECURITY + default n + bool "Enable memory protection for render process" + help + Enable this to enable following two options. + config HIDE_MEM_ADDRESS default n bool "Hide excutable memory address in proc/[pid]/maps " - help + depends on MEMORY_SECURITY + help Select show address about anonymous area of the process memory with -rx- permissions or not. + +config JIT_MEM_CONTROL + default n + bool "Enable memory protection for Just-In-Time compiler's codespace" + depends on MEMORY_SECURITY + help + Restrict mmap and mprotect interface for process which use JIT compiler. endmenu # a blank line must be existed \ No newline at end of file diff --git a/memory_security/Makefile b/memory_security/Makefile index 41e5324254d928de6f6ad973698078c3afd51bb8..72f60caae85bc051b89e61b564c10d306f1c04e2 100755 --- a/memory_security/Makefile +++ b/memory_security/Makefile @@ -4,10 +4,26 @@ # # Makefile for memory_security manager module # -obj-$(CONFIG_HIDE_MEM_ADDRESS) += hideaddr.o +obj-$(CONFIG_HIDE_MEM_ADDRESS) += \ + src/hideaddr.o \ + module.o + +obj-$(CONFIG_JIT_MEM_CONTROL) += \ + src/jit_space_list.o \ + src/jit_process.o \ + src/jit_memory.o \ + src/jit_memory_module.o \ + module.o ccflags-$(CONFIG_HIDE_MEM_ADDRESS) += \ -I$(srctree)/fs/proc \ + -I$(srctree)/fs/proc/memory_security/include \ + -I$(srctree)/security/selinux/include \ + -I$(srctree)/security/selinux + +ccflags-$(CONFIG_JIT_MEM_CONTROL) += \ + -I$(srctree)/fs/proc \ + -I$(srctree)/fs/proc/memory_security/include \ -I$(srctree)/security/selinux/include \ -I$(srctree)/security/selinux diff --git a/memory_security/include/hideaddr.h b/memory_security/include/hideaddr.h new file mode 100644 index 0000000000000000000000000000000000000000..9c19f56cb168013fc8430a7f390c52613de4e1e3 --- /dev/null +++ b/memory_security/include/hideaddr.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _HIDE_ADDR_MODULE_H +#define _HIDE_ADDR_MODULE_H + + +#ifdef CONFIG_HIDE_MEM_ADDRESS +void hideaddr_header_prefix_lhck_register(void); + +#else +inline void hideaddr_header_prefix_lhck_register(void) +{ +} + +#endif // CONFIG_HIDE_MEM_ADDRESS + +#endif /* _HIDE_ADDR_MODULE_H */ \ No newline at end of file diff --git a/memory_security/include/jit_memory.h b/memory_security/include/jit_memory.h new file mode 100644 index 0000000000000000000000000000000000000000..d548795bc2110c8185e705c027b26b1b12979961 --- /dev/null +++ b/memory_security/include/jit_memory.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _JIT_MEMORY_H +#define _JIT_MEMORY_H + +#include +#include "jit_space_list.h" +#include "jit_process.h" + +extern void find_jit_memory(struct task_struct *task, unsigned long start, unsigned long size, int *err); +extern void check_jit_memory(struct task_struct *task, unsigned long cookie, unsigned long prot, + unsigned long start, unsigned long size, int *err); +extern void delete_jit_memory(struct task_struct *task, unsigned long start, unsigned long size, int *err); +extern void exit_jit_memory(struct task_struct *task); + +static bool jit_avc_has_perm(u16 tclass, u32 requested, struct task_struct *task); + +#endif //_JIT_MEMORY_H \ No newline at end of file diff --git a/memory_security/include/jit_memory_log.h b/memory_security/include/jit_memory_log.h new file mode 100644 index 0000000000000000000000000000000000000000..647da0b2f468e02dc2e97a4e0084db4d36fa085f --- /dev/null +++ b/memory_security/include/jit_memory_log.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _JIT_MEMORY_LOG_H +#define _JIT_MEMORY_LOG_H + +#define JIT_MEMORY_CHECK_FAILED (-1024) + +#define JIT_MEMORY_TAG "jit_memory_kernel" +#define JIT_MEMORY_INFO_TAG "I" +#define JIT_MEMORY_ERROR_TAG "E" + +#define jit_memory_log_info(fmt, args...) \ + pr_info("[%s/%s]%s: " fmt "\n", JIT_MEMORY_INFO_TAG, JIT_MEMORY_TAG, \ + __func__, ##args) + +#define jit_memory_log_error(fmt, args...) \ + pr_err("[%s/%s]%s: " fmt "\n", JIT_MEMORY_ERROR_TAG, JIT_MEMORY_TAG, \ + __func__, ##args) +#endif /* _JIT_MEMORY_LOG_H */ \ No newline at end of file diff --git a/memory_security/include/jit_memory_module.h b/memory_security/include/jit_memory_module.h new file mode 100644 index 0000000000000000000000000000000000000000..a17eec5dcedbbd984a438e3c4f596f7171a8bca9 --- /dev/null +++ b/memory_security/include/jit_memory_module.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _JIT_MEMORY_MODULE_H +#define _JIT_MEMORY_MODULE_H + + +#ifdef CONFIG_JIT_MEM_CONTROL +void jit_memory_register_hooks(void); + +#else +inline void jit_memory_register_hooks(void) +{ +} + +#endif // CONFIG_JIT_MEM_CONTROL + +#endif /* _JIT_MEMORY_MODULE_H */ \ No newline at end of file diff --git a/memory_security/include/jit_process.h b/memory_security/include/jit_process.h new file mode 100644 index 0000000000000000000000000000000000000000..269bff821dd326584250856dc036c71fbf3be348 --- /dev/null +++ b/memory_security/include/jit_process.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _JIT_PROCESS_H +#define _JIT_PROCESS_H + +#include "jit_space_list.h" + +struct result_of_find_process { + struct rb_node **node, *parent; + struct list_head *head; +}; + + +struct result_of_find_process find_process_jit_space(struct rb_root *root, int pid); +struct list_head *update_process_jit_space(struct rb_root *root, int pid, unsigned long cookie, int *err); +struct jit_process *delete_process_jit_space(struct rb_root *root, int pid); +#endif // _JIT_PROCESS_H \ No newline at end of file diff --git a/memory_security/include/jit_space_list.h b/memory_security/include/jit_space_list.h new file mode 100644 index 0000000000000000000000000000000000000000..17729c6e7c1d2aa5ea405614a0304083f736c966 --- /dev/null +++ b/memory_security/include/jit_space_list.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _JIT_SPACE_LIST_H +#define _JIT_SPACE_LIST_H + +#include +#include +#include +#include +#include + +#include "jit_memory_log.h" +static struct rb_root root_tree = RB_ROOT; + +extern struct jit_process { + int pid; // pid is the key and cookie is value in rbTree + unsigned long cookie; + struct rb_node node; + struct list_head head; +}; + +extern struct jit_space_node { + unsigned long begin, end; + struct list_head head; +}; + +inline struct jit_space_node *init_jit_space_node(unsigned long begin, unsigned long end); + +const void find_jit_space(struct list_head *head, unsigned long begin, unsigned long size, int *err); +void update_jit_space(struct list_head *head, unsigned long begin, unsigned long size); +void delete_jit_space(struct list_head *head, unsigned long begin, unsigned long size, int *err); +void exit_jit_space(struct list_head *head); + + +#endif //_JIT_SPACE_LIST_H \ No newline at end of file diff --git a/memory_security/module.c b/memory_security/module.c new file mode 100644 index 0000000000000000000000000000000000000000..7b3f5b39a9f40ba48aeb1fcf8e6dfcd5c09266bf --- /dev/null +++ b/memory_security/module.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#include +#include "jit_memory_module.h" +#include "hideaddr.h" + +int __init mem_security_hooks_init(void) +{ + hideaddr_header_prefix_lhck_register(); + jit_memory_register_hooks(); + return 0; +} + +static void __exit mem_security_hooks_exit(void) +{ +} + +module_init(mem_security_hooks_init); +module_exit(mem_security_hooks_exit); \ No newline at end of file diff --git a/memory_security/hideaddr.c b/memory_security/src/hideaddr.c similarity index 85% rename from memory_security/hideaddr.c rename to memory_security/src/hideaddr.c index 259d382195784ec75c602e0b783ca9892e4c822c..c34bbcd38f4632eeb78c6db0e6a5373f7a948128 100644 --- a/memory_security/hideaddr.c +++ b/memory_security/src/hideaddr.c @@ -16,6 +16,7 @@ #include "avc.h" #include "objsec.h" +#include "hideaddr.h" static bool is_anon_exec(struct vm_area_struct *vma) { @@ -64,20 +65,7 @@ static void hideaddr_header_prefix(unsigned long *start, unsigned long *end, *flags = 0; } -static void hideaddr_header_prefix_lhck_register(void) +void hideaddr_header_prefix_lhck_register(void) { REGISTER_HCK_LITE_HOOK(hideaddr_header_prefix_lhck, hideaddr_header_prefix); -} - -static int __init hideaddr_hooks_init(void) -{ - hideaddr_header_prefix_lhck_register(); - return 0; -} - -static void __exit hideaddr_hooks_exit(void) -{ -} - -module_init(hideaddr_hooks_init); -module_exit(hideaddr_hooks_exit); +} \ No newline at end of file diff --git a/memory_security/src/jit_memory.c b/memory_security/src/jit_memory.c new file mode 100644 index 0000000000000000000000000000000000000000..aa60a8645ccf23091bbd4d5f790002d3df507e5d --- /dev/null +++ b/memory_security/src/jit_memory.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +*/ +#include +#include +#include +#include + +#include "jit_memory.h" +#include "jit_space_list.h" +#include "avc.h" +#include "objsec.h" + +DEFINE_SPINLOCK(list_lock); + +static bool jit_avc_has_perm(u16 tclass, u32 requested, struct task_struct *task) +{ + // Bypass 'init' + if (task_pid_nr(current) == 1) { + return false; + } + + struct av_decision avd; + u32 secid; + security_cred_getsecid(task->cred, &secid); + + return (avc_has_perm_noaudit(&selinux_state, secid, secid, tclass, requested, + AVC_STRICT, &avd) == 0); +} + +void find_jit_memory(struct task_struct *task, unsigned long start, unsigned long size, int *err) +{ + if (!jit_avc_has_perm(SECCLASS_JIT_MEMORY, JIT_MEMORY__EXEC_MEM_CTRL, task)) + return; + + struct list_head *head = (find_process_jit_space(&root_tree, task->pid).head); + if (head != NULL) { + spin_lock(&list_lock); + find_jit_space(head, start, size, err); + spin_unlock(&list_lock); + } + +} + +void check_jit_memory(struct task_struct *task, unsigned long cookie, unsigned long prot, + unsigned long start, unsigned long size, int *err) +{ + if (!jit_avc_has_perm(SECCLASS_JIT_MEMORY, JIT_MEMORY__EXEC_MEM_CTRL, task)) + return; + + if (prot & PROT_EXEC) { + jit_memory_log_info("JITINFO can not apply prot_exec"); + *err = -EACCES; + vm_munmap(start, size); + return; + } + struct list_head *head = update_process_jit_space(&root_tree, task->pid, cookie, err); + if (*err) { + vm_munmap(start, size); + return; + } + if (head != NULL) { + spin_lock(&list_lock); + update_jit_space(head, start, size); + spin_unlock(&list_lock); + } +} + +void delete_jit_memory(struct task_struct *task, unsigned long start, unsigned long size, int *err) +{ + if (!jit_avc_has_perm(SECCLASS_JIT_MEMORY, JIT_MEMORY__EXEC_MEM_CTRL, task)) + return; + jit_memory_log_info("JITINFO delete jit memory"); + + struct list_head *head = (find_process_jit_space(&root_tree, task->pid).head); + if (head != NULL) { + spin_lock(&list_lock); + delete_jit_space(head, start, size, err); + spin_unlock(&list_lock); + } +} + +void exit_jit_memory(struct task_struct *task) +{ + if (!jit_avc_has_perm(SECCLASS_JIT_MEMORY, JIT_MEMORY__EXEC_MEM_CTRL, task)) + return; + + struct jit_process *process = delete_process_jit_space(&root_tree, task->pid); + if (process != NULL) { + spin_lock(&list_lock); + exit_jit_space(&(process->head)); + spin_unlock(&list_lock); + kfree(process); + } +} \ No newline at end of file diff --git a/memory_security/src/jit_memory_module.c b/memory_security/src/jit_memory_module.c new file mode 100644 index 0000000000000000000000000000000000000000..3c16d30e624b3595850468f9da7a18705d061f61 --- /dev/null +++ b/memory_security/src/jit_memory_module.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#include +#include +#include +#include "jit_memory.h" +#include "jit_memory_module.h" + +void jit_memory_register_hooks(void) +{ + REGISTER_HCK_LITE_HOOK(find_jit_memory_lhck, find_jit_memory); + REGISTER_HCK_LITE_HOOK(check_jit_memory_lhck, check_jit_memory); + REGISTER_HCK_LITE_HOOK(delete_jit_memory_lhck, delete_jit_memory); + REGISTER_HCK_LITE_HOOK(exit_jit_memory_lhck, exit_jit_memory); + jit_memory_log_info("jit_memory_register_hooks"); +} + +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/memory_security/src/jit_process.c b/memory_security/src/jit_process.c new file mode 100644 index 0000000000000000000000000000000000000000..6a1ada33d20386cc7225e7d9de6b505d8a15ba9e --- /dev/null +++ b/memory_security/src/jit_process.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#include +#include +#include "avc.h" +#include "jit_process.h" + +DEFINE_SPINLOCK(rbtree_lock); + +struct result_of_find_process find_process_jit_space(struct rb_root *root, int pid) +{ + struct rb_node **node = &(root->rb_node), *parent = NULL; + struct result_of_find_process result = {NULL, NULL, NULL}; + + spin_lock(&rbtree_lock); + while (*node) { + struct jit_process *now = container_of(*node, struct jit_process, node); + + parent = *node; + if (now->pid == pid) { + result.head = &(now->head); + break; + } + else if (now->pid < pid) { + node = &((*node)->rb_left); + } + else if (now->pid > pid) { + node = &((*node)->rb_right); + } + } + spin_unlock(&rbtree_lock); + + result.node = node; + result.parent = parent; + return result; +} + +struct list_head *update_process_jit_space(struct rb_root *root, + int pid, unsigned long cookie, int *err) +{ + struct result_of_find_process result = find_process_jit_space(root, pid); + + if (result.head != NULL) { + // find node which already exist + struct jit_process *now = container_of(result.head, struct jit_process, head); + if (now->cookie == cookie) { + return result.head; + } else { + *err = -EACCES; + return NULL; + } + } else { + // init node + struct jit_process *process = kmalloc(sizeof(struct jit_process), GFP_KERNEL); + if (process == NULL) { + jit_memory_log_error("malloc for rbTree node failed"); + *err = -ENOMEM; + return NULL; + } + process->cookie = cookie; + process->pid = pid; + process->head.next = &(process->head); + process->head.prev = &(process->head); + /* Add new node and rebalance tree. */ + spin_lock(&rbtree_lock); + rb_link_node(&(process->node), result.parent, result.node); + rb_insert_color(&(process->node), root); + spin_unlock(&rbtree_lock); + + return &(process->head); + } +} + +struct jit_process *delete_process_jit_space(struct rb_root *root, int pid) +{ + struct list_head *head = (find_process_jit_space(root, pid).head); + if (head == NULL) + return NULL; + + struct jit_process *victim = container_of(head, struct jit_process, head); + if (victim == NULL) + return NULL; + + spin_lock(&rbtree_lock); + rb_erase(&(victim->node), root); + spin_unlock(&rbtree_lock); + + return victim; +} \ No newline at end of file diff --git a/memory_security/src/jit_space_list.c b/memory_security/src/jit_space_list.c new file mode 100644 index 0000000000000000000000000000000000000000..7bae725e9f5bb829ea7795dbf032ca34b4c462a1 --- /dev/null +++ b/memory_security/src/jit_space_list.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#include +#include "jit_space_list.h" + +inline struct jit_space_node *init_jit_space_node(unsigned long begin, unsigned long end) +{ + struct jit_space_node *new = kmalloc(sizeof(struct jit_space_node), GFP_KERNEL); + if (new == NULL) { + jit_memory_log_error("malloc for jit_space_node failed"); + return NULL; + } + new->begin = begin; + new->end = end; + return new; +} + +const void find_jit_space(struct list_head *head, unsigned long begin, unsigned long size, int *err) +{ + unsigned long end = begin + size; + struct jit_space_node *node; + struct list_head *cur; + + list_for_each(cur, head) + { + node = list_entry(cur, struct jit_space_node, head); + if (node->begin <= begin && node->end >= end) { + *err = 0; + return; + } + } + *err = -EACCES; +} + +void update_jit_space(struct list_head *head, unsigned long begin, unsigned long size) +{ + unsigned long end = begin + size; + + struct jit_space_node *new = init_jit_space_node(begin, end); + if (new == NULL) + return; + list_add(&(new->head), head); + + struct jit_space_node *now = list_entry(head->next, struct jit_space_node, head); +} + +void delete_jit_space(struct list_head *head, unsigned long begin, unsigned long size, int *err) +{ + unsigned long end = begin + size; + struct jit_space_node *node; + struct list_head *cur; + + list_for_each(cur, head) { + node = list_entry(cur, struct jit_space_node, head); + + if (begin >= node->begin && end <= node->end) { + if (begin == node->begin && end == node->end) { // [| cut&node |] + list_del(cur); + kfree(node); + } else if (begin != node->begin && end != node->end) { // [ node | cut | node ] + struct jit_space_node *new = init_jit_space_node(end, node->end); + if (new == NULL) { + *err = -ENOMEM; + return; + } + node->end = begin; + list_add(&(new->head), cur); + } else if (begin != node->begin) { // [ node | cut |] + node->end == begin; + } else if (end != node->end) { // [| cut | node ] + node->begin = end; + } + return; + } + } +} + +void exit_jit_space(struct list_head *head) +{ + struct list_head *cur, *next; + struct jit_space_node *node; + + list_for_each_safe(cur, next, head) { + node = list_entry(cur, struct jit_space_node, head); + list_del(cur); + kfree(node); + } +} \ No newline at end of file