diff --git a/kernel/kpm/kpm_loader.c b/kernel/kpm/kpm_loader.c new file mode 100644 index 00000000..1386e3b2 --- /dev/null +++ b/kernel/kpm/kpm_loader.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kpm.h" +#include "kpm_compact.h" + +#define KPM_MODULE_DIR "/data/adb/kpm" + +struct dir_context_impl { + struct dir_context ctx; + void *dirent; + int result; +}; + +static int dir_emit_impl(struct dir_context *ctx, const char *name, int namlen, + loff_t offset, u64 ino, unsigned int d_type) +{ + struct dir_context_impl *impl = container_of(ctx, struct dir_context_impl, ctx); + struct linux_dirent64 *dirent = impl->dirent; + + // 填充目录项信息 + strncpy(dirent->d_name, name, namlen); + dirent->d_name[namlen] = 0; + dirent->d_ino = ino; + dirent->d_type = d_type; + + impl->result = 1; + return 0; +} + +static void load_kpm_modules(void) +{ + struct path root_path; + struct file *fp; + struct dir_context_impl ctx = { + .ctx.actor = dir_emit_impl, + .ctx.pos = 0, + }; + int ret; + + // 打开KPM模块目录 + ret = kern_path(KPM_MODULE_DIR, LOOKUP_FOLLOW, &root_path); + if (ret) { + pr_err("Failed to open KPM directory: %d\n", ret); + return; + } + + // 打开目录进行遍历 + fp = dentry_open(&root_path, O_RDONLY | O_DIRECTORY, current_cred()); + if (IS_ERR(fp)) { + pr_err("Failed to open KPM directory file: %ld\n", PTR_ERR(fp)); + path_put(&root_path); + return; + } + + // 遍历目录中的所有.kpm文件 + while (true) { + struct linux_dirent64 *dirent; + int result = 0; + + dirent = kzalloc(sizeof(*dirent), GFP_KERNEL); + if (!dirent) + break; + + ctx.dirent = dirent; + ctx.result = 0; + + ret = iterate_dir(fp, &ctx.ctx); + if (ret < 0 || !ctx.result) { + kfree(dirent); + break; + } + + // 检查是否是.kpm文件 + if (strstr(dirent->d_name, ".kpm")) { + char module_path[256]; + snprintf(module_path, sizeof(module_path), "%s/%s", KPM_MODULE_DIR, dirent->d_name); + + // 使用 prctl 系统调用加载模块 + ret = syscall(__NR_prctl, 0x4B534C4B /* KERNEL_SU_OPTION */, SUKISU_KPM_LOAD, module_path, NULL, &result); + if (ret == 0) { + pr_info("Loaded KPM module: %s, result: %d\n", module_path, result); + } else { + pr_err("Failed to load KPM module: %s, ret: %d\n", module_path, ret); + } + } + + kfree(dirent); + ctx.ctx.pos++; + } + + filp_close(fp, NULL); + path_put(&root_path); +} + +// 在内核启动时调用 +static int __init kpm_loader_init(void) +{ + pr_info("KPM loader initialized\n"); + load_kpm_modules(); + return 0; +} + +module_init(kpm_loader_init); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ShirkNeko"); +MODULE_DESCRIPTION("KernelSU KPM Module Loader"); \ No newline at end of file