添加panic时打印出对应KPM信息的情况
This commit is contained in:
@@ -688,6 +688,7 @@ __maybe_unused int ksu_kprobe_init(void)
|
|||||||
|
|
||||||
#ifdef CONFIG_KPM
|
#ifdef CONFIG_KPM
|
||||||
kpm_cfi_bypass_init();
|
kpm_cfi_bypass_init();
|
||||||
|
kpm_stack_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -699,6 +700,7 @@ __maybe_unused int ksu_kprobe_exit(void)
|
|||||||
unregister_kprobe(&renameat_kp);
|
unregister_kprobe(&renameat_kp);
|
||||||
#ifdef CONFIG_KPM
|
#ifdef CONFIG_KPM
|
||||||
kpm_cfi_bypass_exit();
|
kpm_cfi_bypass_exit();
|
||||||
|
kpm_stack_exit();
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ struct CompactAliasSymbol {
|
|||||||
const char* compact_symbol_name;
|
const char* compact_symbol_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CompactProxySymbol {
|
||||||
|
const char* symbol_name;
|
||||||
|
const char* compact_symbol_name;
|
||||||
|
void* cached_address;
|
||||||
|
};
|
||||||
|
|
||||||
struct CompactAddressSymbol address_symbol [] = {
|
struct CompactAddressSymbol address_symbol [] = {
|
||||||
{ "kallsyms_lookup_name", &kallsyms_lookup_name },
|
{ "kallsyms_lookup_name", &kallsyms_lookup_name },
|
||||||
{ "compact_find_symbol", &sukisu_compact_find_symbol },
|
{ "compact_find_symbol", &sukisu_compact_find_symbol },
|
||||||
@@ -53,12 +59,31 @@ struct CompactAddressSymbol address_symbol [] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct CompactAliasSymbol alias_symbol[] = {
|
struct CompactAliasSymbol alias_symbol[] = {
|
||||||
{"kf_strncat", "strncat"},
|
|
||||||
{"kf_strlen", "strlen" },
|
|
||||||
{"kf_strcpy", "strcpy"},
|
|
||||||
{"compat_copy_to_user", "__arch_copy_to_user"}
|
{"compat_copy_to_user", "__arch_copy_to_user"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CompactProxySymbol proxy_symbol[] = {
|
||||||
|
{"kf_strncat", "strncat", NULL },
|
||||||
|
{"kf_strlen", "strlen", NULL },
|
||||||
|
{"kf_strcpy", "strcpy", NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned long sukisu_find_proxy_symbol(const char* name) {
|
||||||
|
// 查不到就查查兼容的符号
|
||||||
|
for(i = 0; i < (sizeof(proxy_symbol) / sizeof(struct CompactProxySymbol)); i++) {
|
||||||
|
struct CompactProxySymbol* symbol = &alias_symbol[i];
|
||||||
|
if(strcmp(name, symbol->symbol_name) == 0) {
|
||||||
|
if(symbol->cached_address == NULL) {
|
||||||
|
symbol->cached_address = kallsyms_lookup_name(name);
|
||||||
|
}
|
||||||
|
if(symbol->cached_address != NULL) {
|
||||||
|
return (unsigned long) &symbol->cached_address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long sukisu_compact_find_symbol(const char* name) {
|
unsigned long sukisu_compact_find_symbol(const char* name) {
|
||||||
int i;
|
int i;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
@@ -73,9 +98,8 @@ unsigned long sukisu_compact_find_symbol(const char* name) {
|
|||||||
|
|
||||||
/* 如果符号名以 "kf__" 开头,尝试解析去掉前缀的部分 */
|
/* 如果符号名以 "kf__" 开头,尝试解析去掉前缀的部分 */
|
||||||
if (strncmp(name, "kf__", 4) == 0) {
|
if (strncmp(name, "kf__", 4) == 0) {
|
||||||
const char *real_name = name + 4; // 去掉 "kf__"
|
addr = sukisu_find_proxy_symbol(name);
|
||||||
addr = (unsigned long)kallsyms_lookup_name(real_name);
|
if(addr != 0) {
|
||||||
if (addr) {
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
122
kernel/kpm/kpm.c
122
kernel/kpm/kpm.c
@@ -35,6 +35,9 @@
|
|||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <asm/insn.h>
|
#include <asm/insn.h>
|
||||||
|
#include <linux/kprobes.h>
|
||||||
|
#include <linux/stacktrace.h>
|
||||||
|
#include <linux/kallsyms.h>
|
||||||
#include "kpm.h"
|
#include "kpm.h"
|
||||||
#include "compact.h"
|
#include "compact.h"
|
||||||
|
|
||||||
@@ -1100,36 +1103,6 @@ free_data:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------- 地址过滤逻辑 ---------------------*/
|
|
||||||
/**
|
|
||||||
* is_allow_address - 自定义地址放行规则
|
|
||||||
* @addr: 目标函数地址
|
|
||||||
*
|
|
||||||
* 返回值: true 放行 | false 拦截
|
|
||||||
*/
|
|
||||||
bool kpm_is_allow_address(unsigned long addr)
|
|
||||||
{
|
|
||||||
struct kpm_module *pos;
|
|
||||||
bool allow = false;
|
|
||||||
|
|
||||||
spin_lock(&kpm_module_lock);
|
|
||||||
list_for_each_entry(pos, &kpm_module_list, list) {
|
|
||||||
unsigned long start_address = (unsigned long) pos->start;
|
|
||||||
unsigned long end_address = start_address + pos->size;
|
|
||||||
|
|
||||||
/* 规则1:地址在KPM允许范围内 */
|
|
||||||
if (addr >= start_address && addr <= end_address) {
|
|
||||||
allow = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock(&kpm_module_lock);
|
|
||||||
|
|
||||||
// TODO: 增加Hook跳板放行机制
|
|
||||||
|
|
||||||
return allow;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------
|
/*-----------------------------------------------------------
|
||||||
* 模块管理查询接口
|
* 模块管理查询接口
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
@@ -1266,6 +1239,95 @@ EXPORT_SYMBOL(sukisu_kpm_load_module_path);
|
|||||||
EXPORT_SYMBOL(sukisu_kpm_unload_module);
|
EXPORT_SYMBOL(sukisu_kpm_unload_module);
|
||||||
EXPORT_SYMBOL(sukisu_kpm_find_module);
|
EXPORT_SYMBOL(sukisu_kpm_find_module);
|
||||||
|
|
||||||
|
// ===========================================================================================
|
||||||
|
|
||||||
|
/*--------------------- 地址过滤逻辑 ---------------------*/
|
||||||
|
/**
|
||||||
|
* is_allow_address - 自定义地址放行规则
|
||||||
|
* @addr: 目标函数地址
|
||||||
|
*
|
||||||
|
* 返回值: true 放行 | false 拦截
|
||||||
|
*/
|
||||||
|
bool kpm_is_allow_address(unsigned long addr)
|
||||||
|
{
|
||||||
|
struct kpm_module *pos;
|
||||||
|
bool allow = false;
|
||||||
|
|
||||||
|
spin_lock(&kpm_module_lock);
|
||||||
|
list_for_each_entry(pos, &kpm_module_list, list) {
|
||||||
|
unsigned long start_address = (unsigned long) pos->start;
|
||||||
|
unsigned long end_address = start_address + pos->size;
|
||||||
|
|
||||||
|
/* 规则1:地址在KPM允许范围内 */
|
||||||
|
if (addr >= start_address && addr <= end_address) {
|
||||||
|
allow = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock(&kpm_module_lock);
|
||||||
|
|
||||||
|
// TODO: 增加Hook跳板放行机制
|
||||||
|
|
||||||
|
return allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kprobe dump_stack_kp = {
|
||||||
|
.symbol_name = "dump_stack",
|
||||||
|
};
|
||||||
|
|
||||||
|
static int handler_dump_stack_pre(struct kprobe *p, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
struct stack_trace trace = {
|
||||||
|
.nr_entries = 0,
|
||||||
|
.max_entries = 32,
|
||||||
|
.entries = (unsigned long *)kmalloc(32*sizeof(unsigned long), GFP_ATOMIC),
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* 捕获当前调用栈 */
|
||||||
|
save_stack_trace(&trace);
|
||||||
|
|
||||||
|
/* 遍历栈地址并匹配 KPM 模块 */
|
||||||
|
printk(KERN_EMERG "KPM Stack Trace:\n");
|
||||||
|
for (i = 0; i < trace.nr_entries; i++) {
|
||||||
|
struct kpm_module *pos;
|
||||||
|
unsigned long addr = trace.entries[i];
|
||||||
|
|
||||||
|
list_for_each_entry(pos, &kpm_module_list, list) {
|
||||||
|
unsigned long start_address = (unsigned long) pos->start;
|
||||||
|
unsigned long end_address = start_address + pos->size;
|
||||||
|
|
||||||
|
/* 规则1:地址在KPM允许范围内 */
|
||||||
|
if (addr >= start_address && addr <= end_address) {
|
||||||
|
printk(KERN_EMERG "[KPM: <%px>] %s+%px\n",
|
||||||
|
(void *)addr, pos->info.name, addr - ((unsigned long)pos->start));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(trace.entries);
|
||||||
|
return 0; // 继续执行原始 dump_stack
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 模块初始化 */
|
||||||
|
int kpm_stack_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
if ((ret = register_kprobe(&dump_stack_kp)) < 0) {
|
||||||
|
printk(KERN_ERR "Failed to hook dump_stack: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
dump_stack_kp.pre_handler = handler_dump_stack_pre;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 模块卸载 */
|
||||||
|
void kpm_stack_exit(void)
|
||||||
|
{
|
||||||
|
unregister_kprobe(&dump_stack_kp);
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================================
|
// ============================================================================================
|
||||||
|
|
||||||
int sukisu_handle_kpm(unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
int sukisu_handle_kpm(unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ int sukisu_is_kpm_control_code(unsigned long arg2);
|
|||||||
|
|
||||||
int kpm_cfi_bypass_init(void);
|
int kpm_cfi_bypass_init(void);
|
||||||
void kpm_cfi_bypass_exit(void);
|
void kpm_cfi_bypass_exit(void);
|
||||||
|
int kpm_stack_init(void);
|
||||||
|
void kpm_stack_exit(void);
|
||||||
|
|
||||||
// KPM控制代码
|
// KPM控制代码
|
||||||
#define CMD_KPM_CONTROL 28
|
#define CMD_KPM_CONTROL 28
|
||||||
|
|||||||
Reference in New Issue
Block a user