diff --git a/kernel/core_hook.c b/kernel/core_hook.c index d6a696d4..2f2c090c 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -686,12 +686,6 @@ __maybe_unused int ksu_kprobe_init(void) rc = register_kprobe(&renameat_kp); pr_info("renameat kp: %d\n", rc); - #ifdef CONFIG_KPM - // KPM初始化状态 - kpm_cfi_bypass_init(); - // kpm_stack_init(); - #endif - return rc; } @@ -699,11 +693,6 @@ __maybe_unused int ksu_kprobe_exit(void) { unregister_kprobe(&prctl_kp); unregister_kprobe(&renameat_kp); - #ifdef CONFIG_KPM - // KPM取消状态 - kpm_cfi_bypass_exit(); - // kpm_stack_exit(); - #endif return 0; } diff --git a/kernel/kpm/Makefile b/kernel/kpm/Makefile index b264c68d..10cf7d44 100644 --- a/kernel/kpm/Makefile +++ b/kernel/kpm/Makefile @@ -1,3 +1,2 @@ obj-y += kpm.o -obj-y += compact.o -obj-y += bypasscfi.o \ No newline at end of file +obj-y += compact.o \ No newline at end of file diff --git a/kernel/kpm/bypasscfi.c b/kernel/kpm/bypasscfi.c deleted file mode 100644 index 223e54cc..00000000 --- a/kernel/kpm/bypasscfi.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include -#include - -/* 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"); -} diff --git a/kernel/kpm/compact.c b/kernel/kpm/compact.c index d57bc53e..a30fdae9 100644 --- a/kernel/kpm/compact.c +++ b/kernel/kpm/compact.c @@ -31,62 +31,17 @@ unsigned long sukisu_compact_find_symbol(const char* name); // ====================================================================== -const char* kpver = "0.10"; - struct CompactAddressSymbol { const char* symbol_name; void* addr; }; -struct CompactAliasSymbol { - const char* symbol_name; - const char* compact_symbol_name; -}; - -struct CompactProxySymbol { - const char* symbol_name; - const char* compact_symbol_name; - void* cached_address; -}; - static struct CompactAddressSymbol address_symbol [] = { { "kallsyms_lookup_name", &kallsyms_lookup_name }, { "compact_find_symbol", &sukisu_compact_find_symbol }, - { "compat_copy_to_user", ©_to_user }, - { "compat_strncpy_from_user", &strncpy_from_user }, - { "kpver", &kpver }, { "is_run_in_sukisu_ultra", (void*)1 } }; -static struct CompactAliasSymbol alias_symbol[] = { - {"compat_copy_to_user", "__arch_copy_to_user"} -}; - -static 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) { - // 查找proxy符号 - int i; - for(i = 0; i < (sizeof(proxy_symbol) / sizeof(struct CompactProxySymbol)); i++) { - struct CompactProxySymbol* symbol = &proxy_symbol[i]; - if(strcmp(name, symbol->symbol_name) == 0) { - if(symbol->cached_address == NULL) { - symbol->cached_address = (void*) kallsyms_lookup_name(symbol->compact_symbol_name); - } - if(symbol->cached_address != NULL) { - return (unsigned long) &symbol->cached_address; - } else { - return 0; - } - } - } - return 0; -} - unsigned long sukisu_compact_find_symbol(const char* name) { int i; unsigned long addr; @@ -100,34 +55,13 @@ unsigned long sukisu_compact_find_symbol(const char* name) { } } - /* 如果符号名以 "kf_" 开头,尝试解析去掉前缀的部分 */ - if (strncmp(name, "kf_", 3) == 0) { - addr = sukisu_find_proxy_symbol(name); - isFoundedProxy = 1; - if(addr != 0) { - return addr; - } - } - // 通过内核来查 addr = kallsyms_lookup_name(name); if(addr) { return addr; } - // 查不到就查查兼容的符号 - for(i = 0; i < (sizeof(alias_symbol) / sizeof(struct CompactAliasSymbol)); i++) { - struct CompactAliasSymbol* symbol = &alias_symbol[i]; - if(strcmp(name, symbol->symbol_name) == 0) { - addr = kallsyms_lookup_name(symbol->compact_symbol_name); - if(addr) - return addr; - } - } - - if(!isFoundedProxy) { - return sukisu_find_proxy_symbol(name); - } - return 0; -} \ No newline at end of file +} + +EXPORT_SYMBOL(sukisu_compact_find_symbol); diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index b7876796..69538973 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -44,1301 +44,47 @@ #include "kpm.h" #include "compact.h" -static inline void local_flush_icache_all(void) -{ - asm volatile("ic iallu"); - asm volatile("dsb nsh" : : : "memory"); - asm volatile("isb" : : : "memory"); -} - -static inline void flush_icache_all(void) -{ - asm volatile("dsb ish" : : : "memory"); - asm volatile("ic ialluis"); - asm volatile("dsb ish" : : : "memory"); - asm volatile("isb" : : : "memory"); -} - -/** - * kpm_malloc_exec - 分配可执行内存 - * @size: 需要分配的内存大小(字节) - * - * 返回值: 成功返回内存指针,失败返回 NULL - */ -void *kpm_malloc_exec(size_t size) -{ - void *addr = NULL; - unsigned long nr_pages; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) - /* 内核 5.0+ 方案 */ -#if defined(CONFIG_MODULES) - // 使用 module_alloc + set_memory_x - addr = module_alloc(size); - if (!addr) - return NULL; - - nr_pages = DIV_ROUND_UP(size, PAGE_SIZE); - if (set_memory_x((unsigned long)addr, nr_pages)) { - vfree(addr); // 注意:某些内核版本用 module_memfree - return NULL; - } -#else - // 如果未启用模块支持,回退到 vmalloc + 手动设置权限(可能有安全风险) - addr = __vmalloc(size, GFP_KERNEL, PAGE_KERNEL_EXEC); - if (addr) { - nr_pages = DIV_ROUND_UP(size, PAGE_SIZE); - if (set_memory_x((unsigned long)addr, nr_pages)) { - vfree(addr); - addr = NULL; - } - } -#endif -#else - /* 内核 <5.0 方案 */ -#if defined(vmalloc_exec) - // 旧版直接使用 vmalloc_exec - addr = vmalloc_exec(size); -#else - // 兼容某些旧版本变种 - addr = __vmalloc(size, GFP_KERNEL, PAGE_KERNEL_EXEC); -#endif -#endif - - flush_icache_all(); - - return addr; -} - -/** - * kpm_free_exec - 释放可执行内存 - * @addr: alloc_exec_memory 返回的指针 - * @size: 分配时的大小 - */ -void kpm_free_exec(void *addr, size_t size) -{ - unsigned long nr_pages; - if (!addr) - return; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) - nr_pages = DIV_ROUND_UP(size, PAGE_SIZE); - set_memory_nx((unsigned long)addr, nr_pages); -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES) - module_memfree(addr); // 5.0+ 且启用模块支持 -#else - vfree(addr); // 旧版或未启用模块 -#endif -} - - -/* KPM 模块头部结构体,存放于 ELF 的 .kpm 段中 */ -struct kpm_header { - u32 magic; /* 魔数,要求为 'KPM' -> 0x4B504D */ - u32 version;/* 版本号,目前要求为 1 */ - int (*entry)(const char *args, const char *event, void *__user reserved); - void (*exit)(void *__user reserved); -}; - -#define KPM_MAGIC 0x4B504D -#define KPM_VERSION 1 - -typedef long (*mod_initcall_t)(const char *args, const char *event, void *reserved); -typedef long (*mod_ctl0call_t)(const char *ctl_args, char *__user out_msg, int outlen); -typedef long (*mod_ctl1call_t)(void *a1, void *a2, void *a3); -typedef long (*mod_exitcall_t)(void *reserved); - -/* 加载信息结构体,避免与内核已有 load_info 冲突 */ -struct kpm_load_info { - const void *hdr; /* ELF 数据 */ - Elf64_Ehdr *ehdr; /* ELF 头 */ - Elf64_Shdr *sechdrs; /* 段表 */ - const char *secstrings; /* 段名字符串表 */ - unsigned long len; /* 文件长度 */ - struct { - const char *base; - const char *name; - const char *version; - const char *license; - const char *author; - const char *description; - unsigned long size; - } info; - struct { - int info; - int sym; - int str; - } index; - char *strtab; /* 符号表对应的字符串表 */ - unsigned long symoffs, stroffs; -}; - -/* 模块数据结构,改名为 kpm_module 避免冲突 */ -struct kpm_module { - struct list_head list; - char *args; - char *ctl_args; - void *start; /* 分配的连续内存区域 */ - unsigned int size; /* 总大小 */ - unsigned int text_size; - unsigned int ro_size; - - mod_initcall_t *init; - mod_ctl0call_t *ctl0; - mod_ctl1call_t *ctl1; - mod_exitcall_t *exit; - - struct { - const char *base; - const char *name; - const char *version; - const char *license; - const char *author; - const char *description; - } info; -}; - -/* 全局模块列表,改名为 kpm_module_list */ -static LIST_HEAD(kpm_module_list); -static DEFINE_SPINLOCK(kpm_module_lock); - -/*----------------------------------------------------------- - * ELF 头和段表解析(针对 ARM64 检查) - *----------------------------------------------------------*/ -#define kpm_elf_check_arch(x) ((x)->e_machine == EM_AARCH64) - -static int kpm_elf_header_check(struct kpm_load_info *info) -{ - if (info->len < sizeof(Elf64_Ehdr)) - return -EINVAL; - info->ehdr = (Elf64_Ehdr *)info->hdr; - if (memcmp(info->ehdr->e_ident, ELFMAG, SELFMAG) != 0) - return -EINVAL; - if (info->ehdr->e_shoff + info->ehdr->e_shnum * sizeof(Elf64_Shdr) > info->len) - return -EINVAL; - info->sechdrs = (Elf64_Shdr *)((const char *)info->hdr + info->ehdr->e_shoff); - if (info->ehdr->e_shstrndx >= info->ehdr->e_shnum) - return -EINVAL; - info->secstrings = (const char *)info->hdr + info->sechdrs[info->ehdr->e_shstrndx].sh_offset; - return 0; -} - -/* 在 ELF 文件中查找指定段 */ -Elf64_Shdr *find_sec(struct kpm_load_info *info, const char *sec_name) -{ - Elf64_Ehdr *ehdr = info->ehdr; - Elf64_Shdr *shdr = (Elf64_Shdr *)((char *)ehdr + ehdr->e_shoff); - const char *shstrtab = (char *)ehdr + shdr[ehdr->e_shstrndx].sh_offset; - int i; - - for (i = 0; i < ehdr->e_shnum; i++) { - if (strcmp(shstrtab + shdr[i].sh_name, sec_name) == 0) - return &shdr[i]; - } - - return NULL; -} - -int find_sec_num(struct kpm_load_info *info, const char *sec_name) { - Elf64_Ehdr *ehdr = info->ehdr; - Elf64_Shdr *shdr = (Elf64_Shdr *)((char *)ehdr + ehdr->e_shoff); - const char *shstrtab = (char *)ehdr + shdr[ehdr->e_shstrndx].sh_offset; - int i; - - for (i = 0; i < ehdr->e_shnum; i++) { - if (strcmp(shstrtab + shdr[i].sh_name, sec_name) == 0) - return i; - } +// ============================================================================================ +int sukisu_kpm_load_module_path(const char* path, const char* args, void* ptr) { + // This is a KPM module stub. return -1; } -/*----------------------------------------------------------- - * 模块 modinfo 提取 - *----------------------------------------------------------*/ -static char *kpm_next_string(char *string, unsigned long *secsize) -{ - while (string[0]) { - string++; - if ((*secsize)-- <= 1) - return NULL; - } - while (!string[0]) { - string++; - if ((*secsize)-- <= 1) - return NULL; - } - return string; +int sukisu_kpm_unload_module(const char* name, void* ptr) { + // This is a KPM module stub. + return -1; } -static char *kpm_get_next_modinfo(const struct kpm_load_info *info, const char *tag, char *prev) -{ - char *p; - unsigned int taglen = strlen(tag); - Elf_Shdr *infosec = &info->sechdrs[info->index.info]; - unsigned long size = infosec->sh_size; - char *modinfo = (char *)info->hdr + infosec->sh_offset; - if (prev) { - size -= prev - modinfo; - modinfo = kpm_next_string(prev, &size); - } - for (p = modinfo; p; p = kpm_next_string(p, &size)) { - if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') - return p + taglen + 1; - } - return NULL; -} - -static char *kpm_get_modinfo(const struct kpm_load_info *info, const char *tag) -{ - return kpm_get_next_modinfo(info, tag, NULL); -} - -/*----------------------------------------------------------- - * 内存布局与段复制 - *----------------------------------------------------------*/ -/*static long kpm_get_offset(struct kpm_module *mod, unsigned int *size, Elf64_Shdr *sechdr) -{ - long ret = ALIGN(*size, sechdr->sh_addralign ? sechdr->sh_addralign : 1); - *size = ret + sechdr->sh_size; - return ret; -}*/ - -static long kpm_get_offset2(struct kpm_module *mod, unsigned int *size, Elf_Shdr *sechdr, unsigned int section) -{ - long ret = ALIGN(*size, sechdr->sh_addralign ?: 1); - *size = ret + sechdr->sh_size; - return ret; -} - -/*static void kpm_layout_sections(struct kpm_module *mod, struct kpm_load_info *info) -{ - int i; - for (i = 0; i < info->ehdr->e_shnum; i++) - info->sechdrs[i].sh_entsize = ~0UL; - - for (i = 0; i < info->ehdr->e_shnum; i++) { - Elf64_Shdr *s = &info->sechdrs[i]; - if (!(s->sh_flags & SHF_ALLOC)) - continue; - s->sh_entsize = kpm_get_offset(mod, &mod->size, s); - } - - mod->size = ALIGN(mod->size, 8); -}*/ - -#ifndef ARCH_SHF_SMALL -#define ARCH_SHF_SMALL 0 -#endif - -#ifndef align -#define KP_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) -#define KP_ALIGN(x, a) KP_ALIGN_MASK(x, (typeof(x))(a)-1) -#define kp_align(X) KP_ALIGN(X, 4096) -#endif - -static void kpm_layout_sections(struct kpm_module *mod, struct kpm_load_info *info) -{ - static unsigned long const masks[][2] = { - /* NOTE: all executable code must be the first section in this array; otherwise modify the text_size finder in the two loops below */ - { SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL }, - { SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL }, - { SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL }, - { ARCH_SHF_SMALL | SHF_ALLOC, 0 } - }; - int i, m; - - for (i = 0; i < info->ehdr->e_shnum; i++) - info->sechdrs[i].sh_entsize = ~0UL; - - // todo: tslf alloc all rwx and not page aligned - for (m = 0; m < sizeof(masks) / sizeof(masks[0]); ++m) { - for (i = 0; i < info->ehdr->e_shnum; ++i) { - Elf_Shdr *s = &info->sechdrs[i]; - if ((s->sh_flags & masks[m][0]) != masks[m][0] || (s->sh_flags & masks[m][1]) || s->sh_entsize != ~0UL) - continue; - s->sh_entsize = kpm_get_offset2(mod, &mod->size, s, i); - // const char *sname = info->secstrings + s->sh_name; - } - switch (m) { - case 0: /* executable */ - mod->size = (unsigned int) kp_align(mod->size); - mod->text_size = mod->size; - break; - case 1: /* RO: text and ro-data */ - mod->size = (unsigned int) kp_align(mod->size); - mod->ro_size = mod->size; - break; - case 2: - break; - case 3: /* whole */ - mod->size = (unsigned int) kp_align(mod->size); - break; - } - } -} - -/*----------------------------------------------------------- - * 符号处理与重定位(针对 ARM64) - *----------------------------------------------------------*/ -static bool kpm_is_core_symbol(const Elf64_Sym *src, const Elf64_Shdr *sechdrs, unsigned int shnum) -{ - const Elf64_Shdr *sec; - if (src->st_shndx == SHN_UNDEF || src->st_shndx >= shnum || !src->st_name) - return false; - sec = &sechdrs[src->st_shndx]; - if (!(sec->sh_flags & SHF_ALLOC)) - return false; - return true; -} - -static int kpm_simplify_symbols(struct kpm_module *mod, const struct kpm_load_info *info) -{ - Elf64_Shdr *symsec = &info->sechdrs[info->index.sym]; - Elf64_Sym *sym = (Elf64_Sym *)symsec->sh_addr; - unsigned long secbase; - int ret = 0; - unsigned int i; - unsigned long addr = 0; - - for (i = 1; i < symsec->sh_size / sizeof(Elf64_Sym); i++) { - const char *name = info->strtab + sym[i].st_name; - switch (sym[i].st_shndx) { - case SHN_COMMON: - if (!strncmp(name, "__gnu_lto", 9)) { - printk(KERN_ERR "ARM64 KPM Loader: compile with -fno-common\n"); - ret = -ENOEXEC; - } - break; - case SHN_ABS: - break; - case SHN_UNDEF: - // addr = kallsyms_lookup_name(name); - addr = sukisu_compact_find_symbol(name); - if (!addr) { - printk(KERN_ERR "ARM64 KPM Loader: unknown symbol: %s\n", name); - ret = -ENOENT; - break; - } - sym[i].st_value = addr; - break; - default: - secbase = (unsigned long)mod->start + info->sechdrs[sym[i].st_shndx].sh_offset; - sym[i].st_value += secbase; - break; - } - } - return ret; -} - -#ifndef R_AARCH64_GLOB_DAT -#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */ -#endif -#ifndef R_AARCH64_JUMP_SLOT -#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */ -#endif -#ifndef R_ARM_NONE -#define R_ARM_NONE 0 -#endif -#ifndef R_AARCH64_NONE -#define R_AARCH64_NONE 256 -#endif -#ifndef R_AARCH64_GLOB_DAT -#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */ -#endif -#ifndef R_AARCH64_JUMP_SLOT -#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */ -#endif -#ifndef R_ARM_NONE -#define R_ARM_NONE 0 -#endif -#ifndef R_AARCH64_NONE -#define R_AARCH64_NONE 256 -#endif -#ifndef AARCH64_INSN_IMM_MOVNZ -#define AARCH64_INSN_IMM_MOVNZ AARCH64_INSN_IMM_MAX -#endif -#ifndef AARCH64_INSN_IMM_MOVK -#define AARCH64_INSN_IMM_MOVK AARCH64_INSN_IMM_16 -#endif -#ifndef le32_to_cpu -#define le32_to_cpu(x) (x) -#endif -#ifndef cpu_to_le32 -#define cpu_to_le32(x) (x) -#endif - -enum aarch64_reloc_op -{ - RELOC_OP_NONE, - RELOC_OP_ABS, - RELOC_OP_PREL, - RELOC_OP_PAGE, -}; - -static u64 do_reloc(enum aarch64_reloc_op reloc_op, void *place, u64 val) -{ - switch (reloc_op) { - case RELOC_OP_ABS: - return val; - case RELOC_OP_PREL: - return val - (u64)place; - case RELOC_OP_PAGE: - return (val & ~0xfff) - ((u64)place & ~0xfff); - case RELOC_OP_NONE: - return 0; - } - - printk(KERN_ERR "do_reloc: unknown relocation operation %d\n", reloc_op); +int sukisu_kpm_num() { + // This is a KPM module stub. return 0; } -static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len) -{ - u64 imm_mask = (1 << len) - 1; - s64 sval = do_reloc(op, place, val); - - switch (len) { - case 16: - *(s16 *)place = sval; - break; - case 32: - *(s32 *)place = sval; - break; - case 64: - *(s64 *)place = sval; - break; - default: - printk(KERN_ERR "Invalid length (%d) for data relocation\n", len); - return 0; - } - /* - * Extract the upper value bits (including the sign bit) and - * shift them to bit 0. - */ - sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1); - - /* - * Overflow has occurred if the value is not representable in - * len bits (i.e the bottom len bits are not sign-extended and - * the top bits are not all zero). - */ - if ((u64)(sval + 1) > 2) return -ERANGE; - - return 0; +int sukisu_kpm_info(const char* name, void __user* out) { + // This is a KPM module stub. + return -1; } -static int reloc_insn_movw(enum aarch64_reloc_op op, void *place, u64 val, int lsb, enum aarch64_insn_imm_type imm_type) -{ - u64 imm, limit = 0; - s64 sval; - u32 insn = le32_to_cpu(*(u32 *)place); - - sval = do_reloc(op, place, val); - sval >>= lsb; - imm = sval & 0xffff; - - if (imm_type == AARCH64_INSN_IMM_MOVNZ) { - /* - * For signed MOVW relocations, we have to manipulate the - * instruction encoding depending on whether or not the - * immediate is less than zero. - */ - insn &= ~(3 << 29); - if ((s64)imm >= 0) { - /* >=0: Set the instruction to MOVZ (opcode 10b). */ - insn |= 2 << 29; - } else { - /* - * <0: Set the instruction to MOVN (opcode 00b). - * Since we've masked the opcode already, we - * don't need to do anything other than - * inverting the new immediate field. - */ - imm = ~imm; - } - imm_type = AARCH64_INSN_IMM_MOVK; - } - - /* Update the instruction with the new encoding. */ - insn = aarch64_insn_encode_immediate(imm_type, insn, imm); - *(u32 *)place = cpu_to_le32(insn); - - /* Shift out the immediate field. */ - sval >>= 16; - - /* - * For unsigned immediates, the overflow check is straightforward. - * For signed immediates, the sign bit is actually the bit past the - * most significant bit of the field. - * The AARCH64_INSN_IMM_16 immediate type is unsigned. - */ - if (imm_type != AARCH64_INSN_IMM_16) { - sval++; - limit++; - } - - /* Check the upper bits depending on the sign of the immediate. */ - if ((u64)sval > limit) return -ERANGE; - - return 0; +int sukisu_kpm_list(void __user* out, unsigned int bufferSize) { + // This is a KPM module stub. + return -1; } -static int reloc_insn_imm(enum aarch64_reloc_op op, void *place, u64 val, int lsb, int len, - enum aarch64_insn_imm_type imm_type) -{ - u64 imm, imm_mask; - s64 sval; - u32 insn = le32_to_cpu(*(u32 *)place); - - /* Calculate the relocation value. */ - sval = do_reloc(op, place, val); - sval >>= lsb; - /* Extract the value bits and shift them to bit 0. */ - imm_mask = (BIT(lsb + len) - 1) >> lsb; - imm = sval & imm_mask; - /* Update the instruction's immediate field. */ - insn = aarch64_insn_encode_immediate(imm_type, insn, imm); - *(u32 *)place = cpu_to_le32(insn); - /* - * Extract the upper value bits (including the sign bit) and - * shift them to bit 0. - */ - sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1); - /* - * Overflow has occurred if the upper bits are not all equal to - * the sign bit of the value. - */ - if ((u64)(sval + 1) >= 2) return -ERANGE; - - return 0; +void sukisu_kpm_print_list(void) { } -int kpm_apply_relocate(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned int relsec, - struct kpm_module *me) -{ - return 0; -}; - -int kpm_apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned int relsec, - struct kpm_module *me) -{ - unsigned int i; - int ovf; - bool overflow_check; - Elf64_Sym *sym; - void *loc; - u64 val; - Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; - - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* loc corresponds to P in the AArch64 ELF document. */ - loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset; - /* sym is the ELF symbol we're referring to. */ - sym = (Elf64_Sym *)sechdrs[symindex].sh_addr + ELF64_R_SYM(rel[i].r_info); - /* val corresponds to (S + A) in the AArch64 ELF document. */ - val = sym->st_value + rel[i].r_addend; - - overflow_check = true; - - /* Perform the static relocation. */ - switch (ELF64_R_TYPE(rel[i].r_info)) { - /* Null relocations. */ - case R_ARM_NONE: - case R_AARCH64_NONE: - ovf = 0; - break; - /* Data relocations. */ - case R_AARCH64_ABS64: - overflow_check = false; - ovf = reloc_data(RELOC_OP_ABS, loc, val, 64); - break; - case R_AARCH64_ABS32: - ovf = reloc_data(RELOC_OP_ABS, loc, val, 32); - break; - case R_AARCH64_ABS16: - ovf = reloc_data(RELOC_OP_ABS, loc, val, 16); - break; - case R_AARCH64_PREL64: - overflow_check = false; - ovf = reloc_data(RELOC_OP_PREL, loc, val, 64); - break; - case R_AARCH64_PREL32: - ovf = reloc_data(RELOC_OP_PREL, loc, val, 32); - break; - case R_AARCH64_PREL16: - ovf = reloc_data(RELOC_OP_PREL, loc, val, 16); - break; - - /* MOVW instruction relocations. */ - case R_AARCH64_MOVW_UABS_G0_NC: - overflow_check = false; - case R_AARCH64_MOVW_UABS_G0: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0, AARCH64_INSN_IMM_16); - break; - case R_AARCH64_MOVW_UABS_G1_NC: - overflow_check = false; - case R_AARCH64_MOVW_UABS_G1: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16, AARCH64_INSN_IMM_16); - break; - case R_AARCH64_MOVW_UABS_G2_NC: - overflow_check = false; - case R_AARCH64_MOVW_UABS_G2: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32, AARCH64_INSN_IMM_16); - break; - case R_AARCH64_MOVW_UABS_G3: - /* We're using the top bits so we can't overflow. */ - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 48, AARCH64_INSN_IMM_16); - break; - case R_AARCH64_MOVW_SABS_G0: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0, AARCH64_INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_SABS_G1: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16, AARCH64_INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_SABS_G2: - ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32, AARCH64_INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_PREL_G0_NC: - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0, AARCH64_INSN_IMM_MOVK); - break; - case R_AARCH64_MOVW_PREL_G0: - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0, AARCH64_INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_PREL_G1_NC: - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16, AARCH64_INSN_IMM_MOVK); - break; - case R_AARCH64_MOVW_PREL_G1: - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16, AARCH64_INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_PREL_G2_NC: - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32, AARCH64_INSN_IMM_MOVK); - break; - case R_AARCH64_MOVW_PREL_G2: - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32, AARCH64_INSN_IMM_MOVNZ); - break; - case R_AARCH64_MOVW_PREL_G3: - /* We're using the top bits so we can't overflow. */ - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 48, AARCH64_INSN_IMM_MOVNZ); - break; - /* Immediate instruction relocations. */ - case R_AARCH64_LD_PREL_LO19: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19, AARCH64_INSN_IMM_19); - break; - case R_AARCH64_ADR_PREL_LO21: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 0, 21, AARCH64_INSN_IMM_ADR); - break; - case R_AARCH64_ADR_PREL_PG_HI21_NC: - overflow_check = false; - case R_AARCH64_ADR_PREL_PG_HI21: - ovf = reloc_insn_imm(RELOC_OP_PAGE, loc, val, 12, 21, AARCH64_INSN_IMM_ADR); - break; - case R_AARCH64_ADD_ABS_LO12_NC: - case R_AARCH64_LDST8_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 0, 12, AARCH64_INSN_IMM_12); - break; - case R_AARCH64_LDST16_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 1, 11, AARCH64_INSN_IMM_12); - break; - case R_AARCH64_LDST32_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 2, 10, AARCH64_INSN_IMM_12); - break; - case R_AARCH64_LDST64_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 3, 9, AARCH64_INSN_IMM_12); - break; - case R_AARCH64_LDST128_ABS_LO12_NC: - overflow_check = false; - ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 4, 8, AARCH64_INSN_IMM_12); - break; - case R_AARCH64_TSTBR14: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 14, AARCH64_INSN_IMM_14); - break; - case R_AARCH64_CONDBR19: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19, AARCH64_INSN_IMM_19); - break; - case R_AARCH64_JUMP26: - case R_AARCH64_CALL26: - ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 26, AARCH64_INSN_IMM_26); - break; - default: - printk(KERN_ERR "unsupported RELA relocation: %llu\n", ELF64_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - - if (overflow_check && ovf == -ERANGE) goto overflow; - } - return 0; -overflow: - printk(KERN_ERR "overflow in relocation type %d val %llx\n", (int)ELF64_R_TYPE(rel[i].r_info), val); - return -ENOEXEC; -} - - -static int kpm_apply_relocations(struct kpm_module *mod, const struct kpm_load_info *info) -{ - int rc = 0; - int i; - - for (i = 1; i < info->ehdr->e_shnum; i++) { - unsigned int infosec = info->sechdrs[i].sh_info; - if (infosec >= info->ehdr->e_shnum) continue; - if (!(info->sechdrs[infosec].sh_flags & SHF_ALLOC)) continue; - if (info->sechdrs[i].sh_type == SHT_REL) { - rc = kpm_apply_relocate(info->sechdrs, info->strtab, info->index.sym, i, mod); - } else if (info->sechdrs[i].sh_type == SHT_RELA) { - rc = kpm_apply_relocate_add(info->sechdrs, info->strtab, info->index.sym, i, mod); - } - if (rc < 0) break; - } - - return rc; -} - - -/*----------------------------------------------------------- - * 符号表与字符串表布局 - *----------------------------------------------------------*/ -static void kpm_layout_symtab(struct kpm_module *mod, struct kpm_load_info *info) -{ - Elf64_Shdr *symsect = &info->sechdrs[info->index.sym]; - Elf64_Shdr *strsect = &info->sechdrs[info->index.str]; - const Elf64_Sym *src; - unsigned int i, nsrc, ndst; - unsigned int strtab_size = 1; - - /* Put symbol section at end of module. */ - symsect->sh_flags |= SHF_ALLOC; - symsect->sh_entsize = kpm_get_offset2(mod, &mod->size, symsect, info->index.sym); - - src = (void *)info->hdr + symsect->sh_offset; - nsrc = symsect->sh_size / sizeof(*src); - - /* strtab always starts with a nul, so offset 0 is the empty string. */ - strtab_size = 1; - /* Compute total space required for the core symbols' strtab. */ - for (ndst = i = 0; i < nsrc; i++) { - if (i == 0 || kpm_is_core_symbol(src + i, info->sechdrs, info->ehdr->e_shnum)) { - strtab_size += strlen(&info->strtab[src[i].st_name]) + 1; - ndst++; - } - } - - /* Append room for core symbols at end. */ - info->symoffs = ALIGN(mod->size, symsect->sh_addralign ?: 1); - info->stroffs = mod->size = info->symoffs + ndst * sizeof(Elf64_Sym); - mod->size += strtab_size; - - /* Put string table section at end of module. */ - strsect->sh_flags |= SHF_ALLOC; - strsect->sh_entsize = kpm_get_offset2(mod, &mod->size, strsect, info->index.str); -} - -/*----------------------------------------------------------- - * 重写段表头:修正各段的 sh_addr 为在连续内存中的地址 - *----------------------------------------------------------*/ -static int kpm_rewrite_section_headers(struct kpm_load_info *info) -{ - int i; - info->sechdrs[0].sh_addr = 0; - for (i = 1; i < info->ehdr->e_shnum; i++) { - Elf64_Shdr *shdr = &info->sechdrs[i]; - if (shdr->sh_type != SHT_NOBITS && info->len < shdr->sh_offset + shdr->sh_size) - return -ENOEXEC; - shdr->sh_addr = (size_t)info->hdr + shdr->sh_offset; - } - return 0; -} - -/*----------------------------------------------------------- - * 将各段复制到连续内存区域中 - *----------------------------------------------------------*/ -/*----------------------------------------------------------- - * 将各段复制到连续内存区域(修复版) - * 关键修复点: - * 1. 段地址按对齐要求正确计算 - * 2. 显式设置可执行内存权限 - * 3. 刷新指令缓存保证一致性 - *----------------------------------------------------------*/ -static int kpm_move_module(struct kpm_module *mod, struct kpm_load_info *info) -{ - int i; - - /* 分配连续内存(按页对齐) */ - mod->size = ALIGN(mod->size, PAGE_SIZE); - mod->start = kpm_malloc_exec(mod->size); - if (!mod->start) { - printk(KERN_ERR "ARM64 KPM Loader: Failed to allocate module memory\n"); - return -ENOMEM; - } - memset(mod->start, 0, mod->size); - - /* 设置内存可执行权限(关键修复) */ - set_memory_x((unsigned long)mod->start, mod->size >> PAGE_SHIFT); - flush_icache_all(); - - printk(KERN_INFO "ARM64 KPM Loader: Final section addresses (aligned base=0x%px):\n", mod->start); - - for (i = 1; i < info->ehdr->e_shnum; i++) { - void *dest; - const char *sname; - Elf_Shdr *shdr = &info->sechdrs[i]; - if (!(shdr->sh_flags & SHF_ALLOC)) continue; - - dest = mod->start + (shdr->sh_addr - info->ehdr->e_entry); - sname = info->secstrings + shdr->sh_name; - - if (shdr->sh_type != SHT_NOBITS) memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size); - - shdr->sh_addr = (unsigned long)dest; - - if (!mod->init && !strcmp(".kpm.init", sname)) mod->init = (mod_initcall_t *)dest; - - if (!strcmp(".kpm.ctl0", sname)) mod->ctl0 = (mod_ctl0call_t *)dest; - if (!strcmp(".kpm.ctl1", sname)) mod->ctl1 = (mod_ctl1call_t *)dest; - - if (!mod->exit && !strcmp(".kpm.exit", sname)) mod->exit = (mod_exitcall_t *)dest; - - if (!mod->info.base && !strcmp(".kpm.info", sname)) mod->info.base = (const char *)dest; - } - - /* 调整元数据指针(基于新基址) */ - if (info->info.base) { - unsigned long delta = (unsigned long)mod->start - (unsigned long)info->hdr; - mod->info.name = (const char *)((unsigned long)info->info.name + delta); - mod->info.version = (const char *)((unsigned long)info->info.version + delta); - if (info->info.license) - mod->info.license = (const char *)((unsigned long)info->info.license + delta); - if (info->info.author) - mod->info.author = (const char *)((unsigned long)info->info.author + delta); - if (info->info.description) - mod->info.description = (const char *)((unsigned long)info->info.description + delta); - } - - flush_icache_all(); - - return 0; -} - -/*----------------------------------------------------------- - * 初始化 kpm_load_info:解析 ELF 头、modinfo、符号表 - *----------------------------------------------------------*/ -static int kpm_setup_load_info(struct kpm_load_info *info) -{ - int rc = 0; - int i; - const char *name; - const char *version; - - info->sechdrs = (Elf64_Shdr *)((const char *)info->hdr + info->ehdr->e_shoff); - info->secstrings = (const char *)info->hdr + info->sechdrs[info->ehdr->e_shstrndx].sh_offset; - rc = kpm_rewrite_section_headers(info); - if (rc) { - printk(KERN_ERR "ARM64 KPM Loader: rewrite section headers error\n"); - return rc; - } - if (find_sec_num(info, ".kpm.init") == -1 || find_sec_num(info, ".kpm.exit") == -1) { - printk(KERN_ERR "ARM64 KPM Loader: Missing .kpm.init or .kpm.exit section\n"); - return -ENOEXEC; - } - info->index.info = find_sec_num(info, ".kpm.info"); - if (!info->index.info) { - printk(KERN_ERR "ARM64 KPM Loader: Missing .kpm.info section\n"); - return -ENOEXEC; - } - info->info.base = (const char *)info->hdr + info->sechdrs[info->index.info].sh_offset; - info->info.size = info->sechdrs[info->index.info].sh_entsize; - - name = kpm_get_modinfo(info, "name"); - if (!name) { - printk(KERN_ERR "ARM64 KPM Loader: Module name not found\n"); - return -ENOEXEC; - } - info->info.name = name; - printk(KERN_INFO "ARM64 KPM Loader: Module name: %s\n", name); - - version = kpm_get_modinfo(info, "version"); - if (!version) { - printk(KERN_ERR "ARM64 KPM Loader: Module version not found\n"); - return -ENOEXEC; - } - info->info.version = version; - printk(KERN_INFO "ARM64 KPM Loader: Module version: %s\n", version); - - info->info.license = kpm_get_modinfo(info, "license"); - printk(KERN_INFO "ARM64 KPM Loader: Module license: %s\n", info->info.license ? info->info.license : "N/A"); - - info->info.author = kpm_get_modinfo(info, "author"); - printk(KERN_INFO "ARM64 KPM Loader: Module author: %s\n", info->info.author ? info->info.author : "N/A"); - - info->info.description = kpm_get_modinfo(info, "description"); - printk(KERN_INFO "ARM64 KPM Loader: Module description: %s\n", info->info.description ? info->info.description : "N/A"); - - for (i = 1; i < info->ehdr->e_shnum; i++) { - if (info->sechdrs[i].sh_type == SHT_SYMTAB) { - info->index.sym = i; - info->index.str = info->sechdrs[i].sh_link; - info->strtab = (char *)info->hdr + info->sechdrs[info->index.str].sh_offset; - break; - } - } - if (info->index.sym == 0) { - printk(KERN_ERR "ARM64 KPM Loader: Module has no symbols\n"); - return -ENOEXEC; - } - return 0; -} - -// ============================================================================================ - -/*----------------------------------------------------------- - * KPM 模块加载主流程 - *----------------------------------------------------------*/ -/* 注意:接口名称改为 kpm_load_module,避免与内核原有 load_module 冲突 */ -__nocfi -long kpm_load_module(const void *data, int len, const char *args, - const char *event, void *__user reserved) -{ - struct kpm_load_info load_info = { .hdr = data, .len = len }; - long rc = 0; - struct kpm_module *mod; - - /* 检查 ELF 头 */ - rc = kpm_elf_header_check(&load_info); - if (rc) - goto out; - - rc = kpm_setup_load_info(&load_info); - if (rc) - goto out; - - /* 检查必须存在的模块初始化/退出段 */ - if (find_sec_num(&load_info, ".kpm.init") == -1 || - find_sec_num(&load_info, ".kpm.exit") == -1) { - printk(KERN_ERR "ARM64 KPM Loader: Required sections missing\n"); - rc = -ENOEXEC; - goto out; - } - - /* 检查模块是否已经加载 */ - if (find_module(load_info.info.name)) { - printk(KERN_ERR "ARM64 KPM Loader: Module %s already loaded\n", - load_info.info.name); - rc = -EEXIST; - goto out; - } - - mod = vmalloc(sizeof(struct kpm_module)); - if (!mod) { - rc = -ENOMEM; - goto out; - } - memset(mod, 0, sizeof(struct kpm_module)); - - if (args) { - mod->args = vmalloc(strlen(args) + 1); - if (!mod->args) { - rc = -ENOMEM; - goto free_mod; - } - strcpy(mod->args, args); - } - - kpm_layout_sections(mod, &load_info); - kpm_layout_symtab(mod, &load_info); - - rc = kpm_move_module(mod, &load_info); - if (rc) - goto free_mod; - rc = kpm_simplify_symbols(mod, &load_info); - if (rc) - goto free_mod; - rc = kpm_apply_relocations(mod, &load_info); - if (rc) - goto free_mod; - - /* 替换 flush_icache_all() 为 flush_icache_range() */ - flush_icache_range((unsigned long)mod->start, - (unsigned long)mod->start + mod->size); - flush_icache_all(); - - printk(KERN_INFO "ARM64 KPM Loader: Module all load action finish, prepare call init."); - - rc = (*mod->init)(mod->args, event, reserved); - if (!rc) { - printk(KERN_INFO "ARM64 KPM Loader: Module [%s] loaded successfully with args [%s]\n", - mod->info.name, args ? args : ""); - spin_lock(&kpm_module_lock); - list_add_tail(&mod->list, &kpm_module_list); - spin_unlock(&kpm_module_lock); - goto out; - } else { - printk(KERN_ERR "ARM64 KPM Loader: Module [%s] init failed with error %ld\n", - mod->info.name, rc); - (*mod->exit)(reserved); - } -free_mod: - if (mod->args) - vfree(mod->args); - kpm_free_exec(mod->start, mod->size); - vfree(mod); -out: - return rc; -} - -/* 卸载模块接口,改名为 sukisu_kpm_unload_module */ -__nocfi -long sukisu_kpm_unload_module(const char *name, void *__user reserved) -{ - long rc = 0; - struct kpm_module *mod = NULL; - - if (!name) - return -EINVAL; - spin_lock(&kpm_module_lock); - - list_for_each_entry(mod, &kpm_module_list, list) { - if (!strcmp(name, mod->info.name)) - break; - } - if (!mod) { - rc = -ENOENT; - spin_unlock(&kpm_module_lock); - return rc; - } - list_del(&mod->list); - spin_unlock(&kpm_module_lock); - // rc = mod->exit(reserved); - (*mod->exit)(reserved); - if (mod->args) - vfree(mod->args); - if (mod->ctl_args) - vfree(mod->ctl_args); - kpm_free_exec(mod->start, mod->size); - vfree(mod); - printk(KERN_INFO "ARM64 KPM Loader: Module %s unloaded, rc = %ld\n", name, rc); - return rc; -} - -/*----------------------------------------------------------- - * 导出接口:从文件路径加载 KPM 模块(改名为 sukisu_kpm_load_module_path) - *----------------------------------------------------------*/ -long sukisu_kpm_load_module_path(const char *path, const char *args, void *__user reserved) -{ - long rc = 0; - struct file *filp; - loff_t len; - void *data; - loff_t pos = 0; - - printk(KERN_INFO "ARM64 KPM Loader: Loading module from file: %s\n", path); - if (!path) - return -EINVAL; - filp = filp_open(path, O_RDONLY, 0); - if (IS_ERR(filp)) { - printk(KERN_ERR "ARM64 KPM Loader: Failed to open file %s\n", path); - return PTR_ERR(filp); - } - len = vfs_llseek(filp, 0, SEEK_END); - printk(KERN_INFO "ARM64 KPM Loader: Module file size: %llx\n", len); - vfs_llseek(filp, 0, SEEK_SET); - data = vmalloc(len); - if (!data) { - filp_close(filp, NULL); - return -ENOMEM; - } - memset(data, 0, len); - kernel_read(filp, data, len, &pos); - filp_close(filp, 0); - if (pos != len) { - printk(KERN_ERR "ARM64 KPM Loader: Read file error\n"); - rc = -EIO; - goto free_data; - } - rc = kpm_load_module(data, len, args, "load-file", reserved); -free_data: - vfree(data); - return rc; -} - -/*----------------------------------------------------------- - * 模块管理查询接口 - *----------------------------------------------------------*/ -struct kpm_module *sukisu_kpm_find_module(const char *name) -{ - struct kpm_module *pos; - spin_lock(&kpm_module_lock); - list_for_each_entry(pos, &kpm_module_list, list) { - if (!strcmp(name, pos->info.name)) { - spin_unlock(&kpm_module_lock); - return pos; - } - } - spin_unlock(&kpm_module_lock); - return NULL; -} - -// 获取已经加载的KPM数量 -int sukisu_kpm_num(void) { - struct kpm_module *pos; - int num = 0; - - spin_lock(&kpm_module_lock); - list_for_each_entry(pos, &kpm_module_list, list) { - num++; - } - spin_unlock(&kpm_module_lock); - - return num; -} - -// 获取指定名称的KPM信息 -int sukisu_kpm_info(const char* name, char __user* out) { - char buffer[512] = { 0 }; - struct kpm_module *kpm = sukisu_kpm_find_module(name); - int osize; - - if(kpm == NULL) { - return -1; - } - - memset((void*)&buffer, 0, sizeof(buffer)); - osize = snprintf(buffer, 511, - "Name: %s\n" - "Version: %s\n" - "Author: %s\n" - "License: %s\n" - "Description: %s", - kpm->info.name, kpm->info.version, kpm->info.author, kpm->info.license, kpm->info.description); - - osize = copy_to_user((void __user*) out, (const void*)buffer, osize + 1); - return osize; -} - -int sukisu_kpm_list(char __user *out,unsigned int bufferSize) -{ - struct kpm_module *pos; - int outSize = 0; - int len; - char buffer[128]; // 临时缓冲区,避免直接操作用户空间 - - spin_lock(&kpm_module_lock); - list_for_each_entry(pos, &kpm_module_list, list) { - /* 格式化输出,每行一个模块名称 */ - len = snprintf(buffer, sizeof(buffer), "%s\n", pos->info.name); - - /* 检查剩余空间是否足够 */ - if (outSize + len > bufferSize) { - spin_unlock(&kpm_module_lock); - return -ENOSPC; // 空间不足 - } - - /* 复制到用户空间 */ - if (copy_to_user(out + outSize, buffer, len)) { - spin_unlock(&kpm_module_lock); - return -EFAULT; // 复制失败 - } - - outSize += len; - } - spin_unlock(&kpm_module_lock); - - return outSize; -} - -// 打印所有KPM信息 -/* 直接写入进程 stdout(fd = 1) */ -void sukisu_kpm_print_list(void) -{ - struct kpm_module *kpm; - struct file *stdout_file; - loff_t pos = 0; - char *buffer; - int len; - - /* 打开当前进程的 stdout */ - stdout_file = filp_open("/proc/self/fd/1", O_WRONLY, 0); - if (IS_ERR(stdout_file)) { - printk(KERN_ERR "sukisu_kpm_print_list: Failed to open stdout.\n"); - return; - } - - /* 分配内核缓冲区 */ - buffer = kmalloc(256, GFP_KERNEL); - if (!buffer) { - printk(KERN_ERR "sukisu_kpm_print_list: Failed to allocate buffer.\n"); - filp_close(stdout_file, NULL); - return; - } - - spin_lock(&kpm_module_lock); - list_for_each_entry(kpm, &kpm_module_list, list) { - /* 格式化模块信息 */ - len = snprintf(buffer, 256, - "Name: %s\n" - "Version: %s\n" - "Author: %s\n" - "License: %s\n" - "Description: %s\n\n", - kpm->info.name, kpm->info.version, kpm->info.author, - kpm->info.license, kpm->info.description); - - /* 通过 kernel_write() 直接写入 stdout */ - kernel_write(stdout_file, buffer, len, &pos); - } - spin_unlock(&kpm_module_lock); - - /* 释放资源 */ - kfree(buffer); - filp_close(stdout_file, NULL); +void sukisu_kpm_vesion(void) { } EXPORT_SYMBOL(sukisu_kpm_load_module_path); EXPORT_SYMBOL(sukisu_kpm_unload_module); -EXPORT_SYMBOL(sukisu_kpm_find_module); +EXPORT_SYMBOL(sukisu_kpm_num); +EXPORT_SYMBOL(sukisu_kpm_info); +EXPORT_SYMBOL(sukisu_kpm_list); +EXPORT_SYMBOL(sukisu_kpm_print_list); +EXPORT_SYMBOL(sukisu_kpm_version); -// =========================================================================================== - -/*--------------------- 地址过滤逻辑 ---------------------*/ -/** - * 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; -} -// ============================================================================================ int sukisu_handle_kpm(unsigned long arg3, unsigned long arg4, unsigned long arg5) { diff --git a/kernel/kpm/kpm.h b/kernel/kpm/kpm.h index 3d0deae3..0f558683 100644 --- a/kernel/kpm/kpm.h +++ b/kernel/kpm/kpm.h @@ -4,14 +4,9 @@ int sukisu_handle_kpm(unsigned long arg3, unsigned long arg4, unsigned long arg5); int sukisu_is_kpm_control_code(unsigned long arg2); -int kpm_cfi_bypass_init(void); -void kpm_cfi_bypass_exit(void); -int kpm_stack_init(void); -void kpm_stack_exit(void); - // KPM控制代码 #define CMD_KPM_CONTROL 28 -#define CMD_KPM_CONTROL_MAX 34 +#define CMD_KPM_CONTROL_MAX 35 // 控制代码 @@ -46,6 +41,8 @@ void kpm_stack_exit(void); // error will return -1 #define SUKISU_KPM_PRINT 34 +#define SUKISU_KPM_VERSION 35 + /* A64 instructions are always 32 bits. */ #define AARCH64_INSN_SIZE 4