Signed-off-by: carmincol <changchen5@huawei.com>
Change-Id: I45b71b20874d18cdb1a31a1038e1456f0a03d065
Signed-off-by: carmincol <changchen5@huawei.com>
This commit is contained in:
carmincol
2023-12-09 17:55:35 +08:00
parent 330cbc4b11
commit f21b8491ec
14 changed files with 498 additions and 17 deletions
+15 -1
View File
@@ -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
+17 -1
View File
@@ -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
+20
View File
@@ -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 */
+21
View File
@@ -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 <linux/sched.h>
#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
+22
View File
@@ -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 */
@@ -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 */
+20
View File
@@ -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
+38
View File
@@ -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 <linux/list.h>
#include <linux/slab.h>
#include <linux/rbtree.h>
#include <linux/spinlock.h>
#include <asm-generic/errno-base.h>
#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
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/module.h>
#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);
@@ -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);
}
+96
View File
@@ -0,0 +1,96 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/mman.h>
#include <linux/mm_types.h>
#include <linux/sched.h>
#include <linux/mm.h>
#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);
}
}
+21
View File
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/module.h>
#include <linux/hck/lite_hck_jit_memory.h>
#include <linux/hck/lite_vendor_hooks.h>
#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");
+92
View File
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/sched.h>
#include <linux/types.h>
#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;
}
+91
View File
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/list.h>
#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);
}
}