From cdf5e7b869e98fd9bf1df461de6f07c30661d645 Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Mon, 31 Mar 2025 19:36:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20KPM=20=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=AF=B9=20compact.o=20=E7=9A=84?= =?UTF-8?q?=E6=94=AF=E6=8C=81=EF=BC=8C=E5=B9=B6=E8=B0=83=E6=95=B4=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E4=BB=A3=E7=A0=81=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/Makefile | 4 +- kernel/kpm/compact.c | 42 +- kernel/kpm/kpm.c | 1304 +++--------------------------------------- kernel/kpm/kpm.h | 22 +- 4 files changed, 91 insertions(+), 1281 deletions(-) diff --git a/kernel/kpm/Makefile b/kernel/kpm/Makefile index 10cf7d44..e0a8ce1a 100644 --- a/kernel/kpm/Makefile +++ b/kernel/kpm/Makefile @@ -1,2 +1,4 @@ obj-y += kpm.o -obj-y += compact.o \ No newline at end of file +obj-y += compact.o + +ccflags-y += -flto=thin \ No newline at end of file diff --git a/kernel/kpm/compact.c b/kernel/kpm/compact.c index 61e99a35..e25a7a53 100644 --- a/kernel/kpm/compact.c +++ b/kernel/kpm/compact.c @@ -31,34 +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 CompactAddressSymbol address_symbol [] = { +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 } }; -struct CompactAliasSymbol alias_symbol[] = { - {"kf_strncat", "strncat"}, - {"kf_strlen", "strlen" }, - {"kf_strcpy", "strcpy"}, - {"compat_copy_to_user", "__arch_copy_to_user"} -}; - unsigned long sukisu_compact_find_symbol(const char* name) { int i; unsigned long addr; @@ -71,30 +54,13 @@ unsigned long sukisu_compact_find_symbol(const char* name) { } } - /* 如果符号名以 "kf__" 开头,尝试解析去掉前缀的部分 */ - if (strncmp(name, "kf__", 4) == 0) { - const char *real_name = name + 4; // 去掉 "kf__" - addr = (unsigned long)kallsyms_lookup_name(real_name); - if (addr) { - 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; - } - } - 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 9b160530..87ec9bec 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -35,1263 +35,102 @@ #include #include #include -#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"); -} - +#include +#include +#include #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES) #include // 需要启用 CONFIG_MODULES #endif +#include "kpm.h" +#include "compact.h" -/** - * 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; - } +#ifndef NO_OPTIMIZE +#if defined(__GNUC__) && !defined(__clang__) + #define NO_OPTIMIZE __attribute__((optimize("O0"))) +#elif defined(__clang__) + #define NO_OPTIMIZE __attribute__((optnone)) #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); + #define NO_OPTIMIZE #endif #endif - 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 - -/* 加载信息结构体,避免与内核已有 load_info 冲突 */ -struct kpm_load_info { - const void *hdr; /* ELF 数据 */ - Elf64_Ehdr *ehdr; /* ELF 头 */ - Elf64_Shdr *sechdrs; /* 段表 */ - const char *secstrings; /* 段名字符串表 */ - size_t len; /* 文件长度 */ - struct { - const char *base; - const char *name; - const char *version; - const char *license; - const char *author; - const char *description; - size_t 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; - int (*init)(const char *args, const char *event, void *__user reserved); - void (*exit)(void *__user reserved); - int (*ctl0)(const char *ctl_args, char *__user out_msg, int outlen); - int (*ctl1)(void *a1, void *a2, void *a3); - 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; - } - - 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; -} - -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 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); -} - -/*----------------------------------------------------------- - * 符号处理与重定位(针对 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 = info->sechdrs[sym[i].st_shndx].sh_addr; - sym[i].st_value += secbase; - break; - } - } - return ret; -} - -/* ARM64 重定位处理:支持 R_AARCH64_RELATIVE、R_AARCH64_ABS64、R_AARCH64_GLOB_DAT、R_AARCH64_JUMP_SLOT */ -static int kpm_apply_relocate_arm64(Elf64_Shdr *sechdrs, const char *strtab, int sym_idx, int rel_idx, struct kpm_module *mod) -{ - Elf64_Shdr *relsec = &sechdrs[rel_idx]; - int num = relsec->sh_size / sizeof(Elf64_Rel); - Elf64_Rel *rel = (Elf64_Rel *)((char *)mod->start + relsec->sh_offset); // 修正为 sh_offset - int i; - - for (i = 0; i < num; i++) { - unsigned long type = ELF64_R_TYPE(rel[i].r_info); - unsigned long *addr = (unsigned long *)(mod->start + rel[i].r_offset); - - switch (type) { - case R_AARCH64_RELATIVE: - *addr = (unsigned long)mod->start + *(unsigned long *)addr; - break; - default: - printk(KERN_ERR "ARM64 KPM Loader: Unsupported REL relocation type %lu\n", type); - return -EINVAL; - } - } - return 0; -} - -#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 - -/* 重定位操作类型 */ -typedef enum { - RELOC_OP_ABS, - RELOC_OP_PREL, - RELOC_OP_PAGE -} reloc_op_t; - -/* 编码立即数到指令 */ -static u32 K_aarch64_insn_encode_immediate(u32 insn, s64 imm, int shift, int bits) -{ - u32 mask = (BIT(bits) - 1) << shift; - return (insn & ~mask) | ((imm & (BIT(bits) - 1)) << shift); -} - -/* 修补指令中的立即数字段 */ -int aarch64_insn_patch_imm(void *addr, enum aarch64_insn_imm_type type, s64 imm) -{ - u32 insn = le32_to_cpu(*(u32 *)addr); - u32 new_insn; - - switch (type) { - case AARCH64_INSN_IMM_16: - /* MOVZ/MOVK: imm[15:0] → shift=5, bits=16 */ - new_insn = K_aarch64_insn_encode_immediate(insn, imm, 5, 16); - break; - case AARCH64_INSN_IMM_26: - /* B/BL: offset[25:0] → shift=0, bits=26 */ - new_insn = K_aarch64_insn_encode_immediate(insn, imm, 0, 26); - break; - case AARCH64_INSN_IMM_ADR: - /* ADR/ADRP: imm[20:0] → shift=5, bits=21 */ - new_insn = K_aarch64_insn_encode_immediate(insn, imm, 5, 21); - break; - case AARCH64_INSN_IMM_19: - /* 条件跳转: offset[18:0] → shift=5, bits=19 */ - new_insn = K_aarch64_insn_encode_immediate(insn, imm, 5, 19); - break; - default: - return -EINVAL; - } - - /* 写入新指令并刷新缓存 */ - *(u32 *)addr = cpu_to_le32(new_insn); - flush_icache_range((unsigned long)addr, (unsigned long)addr + 4); - return 0; -} - -/* - * reloc_data - 将数值 val 写入目标地址 loc, - * 并检查 val 是否能在指定的 bits 位内表示。 - * op 参数目前未使用,bits 可为16、32或64。 - */ -int reloc_data(int op, void *loc, u64 val, int bits) -{ - u64 max_val = (1ULL << bits) - 1; - - if (val > max_val) - return -ERANGE; - - switch (bits) { - case 16: - *(u16 *)loc = (u16)val; - break; - case 32: - *(u32 *)loc = (u32)val; - break; - case 64: - *(u64 *)loc = val; - break; - default: - return -EINVAL; - } - return 0; -} - -/* - * reloc_insn_movw - 针对 MOVW 类指令的重定位处理 - * - * 参数说明: - * op: 重定位操作类型(例如 RELOC_OP_ABS 或 RELOC_OP_PREL,目前未作区分) - * loc: 指向要修改的 32 位指令的地址 - * val: 需要嵌入指令的立即数值(在左移 shift 位后写入) - * shift: 表示立即数在 val 中应左移多少位后再写入指令 - * imm_width: 立即数字段宽度,通常为16 - * - * 本示例假定 MOVW 指令的立即数字段位于指令的 bit[5:20]。 - */ -int reloc_insn_movw(int op, void *loc, u64 val, int shift, int imm_width) -{ - u32 *insn = (u32 *)loc; - u32 imm; - - /* 检查 val >> shift 是否能在16位内表示 */ - if (((val >> shift) >> 16) != 0) - return -ERANGE; - - imm = (val >> shift) & 0xffff; - - /* 清除原有立即数字段(假定占用 bit[5:20]) */ - *insn &= ~(0xffff << 5); - /* 写入新的立即数 */ - *insn |= (imm << 5); - - return 0; -} - -/* - * reloc_insn_imm - 针对其他立即数重定位处理 - * - * 参数说明: - * op: 重定位操作类型(例如 RELOC_OP_ABS 或 RELOC_OP_PREL,目前未作区分) - * loc: 指向 32 位指令的地址 - * val: 重定位后需要写入的立即数值 - * shift: 表示 val 中立即数需要右移多少位后写入指令 - * bits: 立即数字段宽度(例如12、19、26等) - * insn_mask: 指令中立即数字段的掩码(本示例中未使用,可根据实际编码调整) - * - * 本示例假定立即数字段位于指令的 bit[5] 开始,占用 bits 位。 - */ -int reloc_insn_imm(int op, void *loc, u64 val, int shift, int bits, int insn_mask) -{ - u32 *insn = (u32 *)loc; - u64 max_val = (1ULL << bits) - 1; - u32 imm; - - if ((val >> shift) > max_val) - return -ERANGE; - - imm = (u32)(val >> shift) & max_val; - - /* 清除原立即数字段,这里假定立即数字段位于 bit[5] */ - *insn &= ~(max_val << 5); - /* 写入新的立即数 */ - *insn |= (imm << 5); - - return 0; -} - -#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 - -/* - * 完善后的 ARM64 RELA 重定位处理函数 - * 支持的重定位类型: - * - R_AARCH64_NONE / R_ARM_NONE: 不做处理 - * - R_AARCH64_RELATIVE: 目标地址 = module_base + r_addend - * - R_AARCH64_ABS64: 目标地址 = module_base + (S + r_addend) - * - R_AARCH64_GLOB_DAT / R_AARCH64_JUMP_SLOT: 目标地址 = module_base + S - * - 其他类型调用 reloc_insn_movw 或 reloc_insn_imm 等函数处理 - * - * 参数说明: - * - sechdrs: ELF 段表数组 - * - strtab: 符号字符串表(未在本函数中直接使用) - * - sym_idx: 符号表所在段的索引 - * - rela_idx: 当前重定位段的索引 - * - mod: 当前模块数据结构,mod->start 为模块加载基地址 - */ -static int kpm_apply_relocate_add_arm64(Elf64_Shdr *sechdrs, const char *strtab, - int sym_idx, int rela_idx, struct kpm_module *mod) -{ - Elf64_Shdr *relasec = &sechdrs[rela_idx]; - int num = relasec->sh_size / sizeof(Elf64_Rela); - /* 使用 sh_offset 而非 sh_entsize,确保 Rela 表起始地址正确 */ - Elf64_Rela *rela = (Elf64_Rela *)((char *)mod->start + relasec->sh_offset); - int i; - int ovf; - bool overflow_check; - Elf64_Sym *sym; - void *loc; - u64 val; - - for (i = 0; i < num; i++) { - unsigned long type = ELF64_R_TYPE(rela[i].r_info); - unsigned long sym_index = ELF64_R_SYM(rela[i].r_info); - - /* 获取目标段索引,即 Rela 段的 sh_info 字段 */ - unsigned int target = sechdrs[rela_idx].sh_info; - if (target >= sechdrs[0].sh_size) { - /* 这里不太可能用 sh_size 来判断,正确做法是检查 e_shnum */ - /* 假设我们可以通过全局信息获得 e_shnum,这里用 target 比较 */ - printk(KERN_ERR "ARM64 KPM Loader: Invalid target section index %u\n", target); - return -EINVAL; - } - /* 根据 ELF 规范,目标地址 loc = (target section's address) + r_offset */ - loc = (void *)sechdrs[target].sh_addr + rela[i].r_offset; - - /* 获取符号 S 值 */ - sym = (Elf64_Sym *)sechdrs[sym_idx].sh_addr + sym_index; - val = sym->st_value + rela[i].r_addend; - overflow_check = true; - - switch (type) { - case R_ARM_NONE: - case R_AARCH64_NONE: - ovf = 0; - break; - case R_AARCH64_RELATIVE: - * (unsigned long *)loc = (unsigned long)mod->start + rela[i].r_addend; - break; - case R_AARCH64_ABS64: - if (sym_index) { - /* 注意:这里假设符号 st_value 是相对地址,需要加上模块基地址 */ - * (unsigned long *)loc = (unsigned long)mod->start + sym->st_value + rela[i].r_addend; - } else { - printk(KERN_ERR "ARM64 KPM Loader: R_AARCH64_ABS64 with zero symbol\n"); - return -EINVAL; - } - break; - case R_AARCH64_GLOB_DAT: - case R_AARCH64_JUMP_SLOT: - if (sym_index) { - * (unsigned long *)loc = (unsigned long)mod->start + sym->st_value; - } else { - printk(KERN_ERR "ARM64 KPM Loader: R_AARCH64_GLOB_DAT/JUMP_SLOT with zero symbol\n"); - return -EINVAL; - } - 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: - 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 重定位处理 */ - 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: - 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: - overflow_check = false; - ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 48, AARCH64_INSN_IMM_MOVNZ); - break; - /* Immediate 指令重定位 */ - 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: - pr_err("ARM64 KPM Loader: Unsupported RELA relocation: %llu\n", - ELF64_R_TYPE(rela[i].r_info)); - return -ENOEXEC; - } - - if (overflow_check && ovf == -ERANGE) - goto overflow; - } - return 0; -overflow: - pr_err("ARM64 KPM Loader: Overflow in relocation type %d, val %llx\n", - (int)ELF64_R_TYPE(rela[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 target = info->sechdrs[i].sh_info; - - if (target >= info->ehdr->e_shnum) { - printk(KERN_ERR "ARM64 KPM Loader: Invalid target section index %u\n", target); - return -EINVAL; - } - - if (!(info->sechdrs[target].sh_flags & SHF_ALLOC)) { - printk(KERN_INFO "ARM64 KPM Loader: Skipping non-allocated section %d\n", i); - continue; - } - - if (info->sechdrs[i].sh_type == SHT_REL) { - rc = kpm_apply_relocate_arm64(info->sechdrs, info->strtab, info->index.sym, i, mod); - } else if (info->sechdrs[i].sh_type == SHT_RELA) { - rc = kpm_apply_relocate_add_arm64(info->sechdrs, info->strtab, info->index.sym, i, mod); - } - - if (rc < 0) { - printk(KERN_ERR "ARM64 KPM Loader: Relocation failed at section %d, error %d\n", i, rc); - 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; - - symsect->sh_flags |= SHF_ALLOC; - symsect->sh_entsize = kpm_get_offset(mod, &mod->size, symsect); - src = (Elf64_Sym *)((char *)info->hdr + symsect->sh_offset); - nsrc = symsect->sh_size / sizeof(Elf64_Sym); - 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++; - } - } - info->symoffs = ALIGN(mod->size, symsect->sh_addralign ? symsect->sh_addralign : 1); - info->stroffs = mod->size = info->symoffs + ndst * sizeof(Elf64_Sym); - mod->size += strtab_size; - strsect->sh_flags |= SHF_ALLOC; - strsect->sh_entsize = kpm_get_offset(mod, &mod->size, strsect); -} - -/*----------------------------------------------------------- - * 重写段表头:修正各段的 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; - unsigned long curr_offset = 0; - Elf64_Shdr *shdr; - void *dest; - const char *secname; - - /* 分配连续内存(按页对齐) */ - mod->size = ALIGN(mod->size, PAGE_SIZE); - mod->start = module_alloc(mod->size); // 使用内核的 module_alloc 接口 - 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); - - printk(KERN_INFO "ARM64 KPM Loader: Final section addresses (aligned base=0x%px):\n", mod->start); - - /* 遍历所有段并按对齐要求布局 */ - for (i = 0; i < info->ehdr->e_shnum; i++) { - shdr = &info->sechdrs[i]; - if (!(shdr->sh_flags & SHF_ALLOC)) - continue; - - /* 按段对齐要求调整偏移 */ - curr_offset = ALIGN(curr_offset, shdr->sh_addralign); - dest = mod->start + curr_offset; - - /* 复制段内容(NOBITS 段不复制) */ - if (shdr->sh_type != SHT_NOBITS) { - memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size); - - /* 刷新指令缓存(针对可执行段) */ - if (shdr->sh_flags & SHF_EXECINSTR) { - flush_icache_range((unsigned long)dest, - (unsigned long)dest + shdr->sh_size); - } - } - - /* 更新段头中的虚拟地址 */ - shdr->sh_addr = (unsigned long)dest; - curr_offset += shdr->sh_size; - - /* 定位关键函数指针 */ - secname = info->secstrings + shdr->sh_name; - if (!mod->init && !strcmp(".kpm.init", secname)) { - mod->init = (int (*)(const char *, const char *, void *__user))dest; - printk(KERN_DEBUG "Found .kpm.init at 0x%px\n", dest); - } else if (!strcmp(".kpm.exit", secname)) { - mod->exit = (void (*)(void *__user))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); - } - - 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 冲突 */ -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); - - 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; +noinline +NO_OPTIMIZE +int sukisu_kpm_load_module_path(const char* path, const char* args, void* ptr) { + // This is a KPM module stub. + printk("KPM: Stub function called (sukisu_kpm_load_module_path). path=%s args=%s ptr=%p\n", path, args, ptr); + __asm__ volatile("nop"); // 精确控制循环不被优化 + return -1; } -/* 卸载模块接口,改名为 sukisu_kpm_unload_module */ -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; +noinline +NO_OPTIMIZE +int sukisu_kpm_unload_module(const char* name, void* ptr) { + // This is a KPM module stub. + printk("KPM: Stub function called (sukisu_kpm_unload_module). name=%s ptr=%p\n", name, ptr); + __asm__ volatile("nop"); // 精确控制循环不被优化 + return -1; } -/*----------------------------------------------------------- - * 导出接口:从文件路径加载 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数量 +noinline +NO_OPTIMIZE 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; + // This is a KPM module stub. + printk("KPM: Stub function called (sukisu_kpm_num).\n"); + __asm__ volatile("nop"); // 精确控制循环不被优化 + return 0; } -// 获取指定名称的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; +noinline +NO_OPTIMIZE +int sukisu_kpm_info(const char* name, void __user* out) { + // This is a KPM module stub. + printk("KPM: Stub function called (sukisu_kpm_info). name=%s buffer=%p\n", name, out); + __asm__ volatile("nop"); // 精确控制循环不被优化 + return -1; } -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; +noinline +NO_OPTIMIZE +int sukisu_kpm_list(void __user* out, unsigned int bufferSize) { + // This is a KPM module stub. + printk("KPM: Stub function called (sukisu_kpm_list). buffer=%p size=%d\n", out, bufferSize); + return -1; } -// 打印所有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; +noinline +NO_OPTIMIZE +int sukisu_kpm_control(void __user* name, void __user* args) { + // This is a KPM module stub. + printk("KPM: Stub function called (sukisu_kpm_control). name=%p args=%p\n", name, args); + __asm__ volatile("nop"); // 精确控制循环不被优化 + return -1; +} - /* 打开当前进程的 stdout */ - stdout_file = filp_open("/proc/self/fd/1", O_WRONLY, 0); - if (IS_ERR(stdout_file)) { - pr_err("sukisu_kpm_print_list: Failed to open stdout.\n"); - return; - } - - /* 分配内核缓冲区 */ - buffer = kmalloc(256, GFP_KERNEL); - if (!buffer) { - pr_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); +noinline +NO_OPTIMIZE +int sukisu_kpm_version(void __user* out, unsigned int bufferSize) { + // This is a KPM module stub. + printk("KPM: Stub function called (sukisu_kpm_version). buffer=%p size=%d\n", out, bufferSize); + __asm__ volatile("nop"); // 精确控制循环不被优化 + return -1; } 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_version); +EXPORT_SYMBOL(sukisu_kpm_control); +noinline +NO_OPTIMIZE int sukisu_handle_kpm(unsigned long arg3, unsigned long arg4, unsigned long arg5) { + __asm__ volatile("nop"); // 精确控制循环不被优化 if(arg3 == SUKISU_KPM_LOAD) { char kernel_load_path[256] = { 0 }; char kernel_args_buffer[256] = { 0 }; @@ -1302,7 +141,7 @@ int sukisu_handle_kpm(unsigned long arg3, unsigned long arg4, unsigned long arg5 strncpy_from_user((char*)&kernel_load_path, (const char __user *)arg4, 255); if(arg5 != 0) { - strncpy_from_user((char*)&kernel_args_buffer, (const char __user *)arg4, 255); + strncpy_from_user((char*)&kernel_args_buffer, (const char __user *)arg5, 255); } return sukisu_kpm_load_module_path((const char*)&kernel_load_path, (const char*) &kernel_args_buffer, NULL); } else if(arg3 == SUKISU_KPM_UNLOAD) { @@ -1327,9 +166,12 @@ int sukisu_handle_kpm(unsigned long arg3, unsigned long arg4, unsigned long arg5 return sukisu_kpm_info((const char*) &kernel_name_buffer, (char __user*) arg5); } else if(arg3 == SUKISU_KPM_LIST) { return sukisu_kpm_list((char __user*) arg4, (unsigned int) arg5); - } else if(arg3 == SUKISU_KPM_PRINT) { - sukisu_kpm_print_list(); + } else if(arg3 == SUKISU_KPM_VERSION) { + return sukisu_kpm_version((char __user*) arg4, (unsigned int) arg5); + } else if(arg3 == SUKISU_KPM_CONTROL) { + return sukisu_kpm_control((char __user*) arg4, (char __user*) arg5); } + __asm__ volatile("nop"); // 精确控制循环不被优化 return 0; } diff --git a/kernel/kpm/kpm.h b/kernel/kpm/kpm.h index 734a0611..83145f97 100644 --- a/kernel/kpm/kpm.h +++ b/kernel/kpm/kpm.h @@ -6,39 +6,39 @@ int sukisu_is_kpm_control_code(unsigned long arg2); // KPM控制代码 #define CMD_KPM_CONTROL 28 -#define CMD_KPM_CONTROL_MAX 34 +#define CMD_KPM_CONTROL_MAX 35 // 控制代码 -// prctl(xxx, xxx, 1, "PATH", "ARGS") +// prctl(xxx, 28, "PATH", "ARGS") // success return 0, error return -N #define SUKISU_KPM_LOAD 28 -// prctl(xxx, xxx, 2, "NAME") +// prctl(xxx, 29, "NAME") // success return 0, error return -N #define SUKISU_KPM_UNLOAD 29 -// num = prctl(xxx, xxx, 3) +// num = prctl(xxx, 30) // error return -N // success return +num or 0 #define SUKISU_KPM_NUM 30 -// prctl(xxx, xxx, 4, Buffer, BufferSize) +// prctl(xxx, 31, Buffer, BufferSize) // success return +out, error return -N #define SUKISU_KPM_LIST 31 -// prctl(xxx, xxx, 5, "NAME", Buffer[256]) +// prctl(xxx, 32, "NAME", Buffer[256]) // success return +out, error return -N #define SUKISU_KPM_INFO 32 -// prctl(xxx, xxx, 6, "NAME", "ARGS") +// prctl(xxx, 33, "NAME", "ARGS") // success return KPM's result value // error return -N #define SUKISU_KPM_CONTROL 33 -// prctl(xxx, xxx, 7) -// success will printf to stdout and return 0 -// error will return -1 -#define SUKISU_KPM_PRINT 34 +// prctl(xxx, 34, buffer, bufferSize) +// success return KPM's result value +// error return -N +#define SUKISU_KPM_VERSION 34 #endif \ No newline at end of file