mirror of
https://github.com/openharmony/kernel_linux_common_modules.git
synced 2026-08-27 01:31:36 -04:00
Init
Signed-off-by: carmincol <changchen5@huawei.com> Change-Id: I45b71b20874d18cdb1a31a1038e1456f0a03d065 Signed-off-by: carmincol <changchen5@huawei.com>
This commit is contained in:
+15
-1
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user