Files
SukiSU-Ultra/kernel/kpm/bypasscfi.c
2025-03-30 16:14:23 +08:00

74 lines
2.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <linux/kprobes.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kallsyms.h>
/* CFI 检查函数符号 */
#define CFI_CHECK_FUNC "__cfi_check"
/* Kprobe 实例 */
static struct kprobe cfi_kp;
bool kpm_is_allow_address(unsigned long addr);
/*--------------------- kprobe 处理逻辑 ---------------------*/
static int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
unsigned long target_addr;
/* 从寄存器获取目标地址(架构相关) */
#if defined(__aarch64__)
target_addr = regs->regs[1]; // ARM64: 第二个参数在 X1
#elif defined(__x86_64__)
target_addr = regs->si; // x86_64: 第二个参数在 RSI
#else
#error "Unsupported architecture"
#endif
/* 根据自定义规则放行 */
if (kpm_is_allow_address(target_addr)) {
printk(KERN_INFO "CFI bypass at 0x%lx\n", target_addr);
#if defined(__aarch64__)
regs->regs[0] = 0; // 修改返回值0 表示校验通过
#elif defined(__x86_64__)
regs->ax = 0; // x86 返回值在 RAX
#endif
return 0; // 跳过原始 CFI 检查
}
return 0; // 继续执行原始检查
}
/*--------------------- 模块初始化/卸载 ---------------------*/
int kpm_cfi_bypass_init(void)
{
unsigned long cfi_check_addr;
/* 动态查找 CFI 检查函数 */
cfi_check_addr = kallsyms_lookup_name(CFI_CHECK_FUNC);
if (!cfi_check_addr) {
printk(KERN_ERR "CFI check function not found\n");
return -ENOENT;
}
/* 初始化 kprobe */
memset(&cfi_kp, 0, sizeof(cfi_kp));
cfi_kp.addr = (kprobe_opcode_t *)cfi_check_addr;
cfi_kp.pre_handler = handler_pre;
/* 注册 kprobe */
if (register_kprobe(&cfi_kp) < 0) {
printk(KERN_ERR "Register kprobe failed\n");
return -EINVAL;
}
printk(KERN_INFO "CFI bypass module loaded\n");
return 0;
}
void kpm_cfi_bypass_exit(void)
{
unregister_kprobe(&cfi_kp);
printk(KERN_INFO "CFI bypass module unloaded\n");
}