From 277d927fe1ab1934b269c393e51226dfe855105b Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Sat, 29 Mar 2025 21:08:53 +0800 Subject: [PATCH 01/19] Update setup.sh --- kernel/setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/setup.sh b/kernel/setup.sh index c4a3f597..3d042f9e 100755 --- a/kernel/setup.sh +++ b/kernel/setup.sh @@ -39,7 +39,7 @@ perform_cleanup() { # Sets up or update KernelSU environment setup_kernelsu() { echo "[+] Setting up KernelSU..." - test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/ShirkNeko/KernelSU && echo "[+] Repository cloned." + test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/ShirkNeko/SukiSU-Ultra && echo "[+] Repository cloned." cd "$GKI_ROOT/KernelSU" git stash && echo "[-] Stashed current changes." if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then From a79558de699c0e10c5d468506e5a33f974f3581d Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 21:19:55 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/compact.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/kpm/compact.c b/kernel/kpm/compact.c index d6f69705..2c2ac533 100644 --- a/kernel/kpm/compact.c +++ b/kernel/kpm/compact.c @@ -31,7 +31,7 @@ unsigned long sukisu_compact_find_symbol(const char* name); // ====================================================================== -const char* kver = "0.10"; +const char* kpver = "0.10"; struct CompactAddressSymbol { const char* symbol_name; @@ -45,18 +45,18 @@ struct CompactAliasSymbol { struct CompactAddressSymbol address_symbol [] = { { "kallsyms_lookup_name", &kallsyms_lookup_name }, - { "compact_find_symbol", &sukisu_compact_find_symbol }, - { "compact_copy_to_user", ©_to_user }, - { "compact_strncpy_from_user", &strncpy_from_user }, - { "kver", &kver }, + { "compat_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"}, - {"compact_copy_to_user", "__arch_copy_to_user"} + {"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) { From a36916c741062ef0fb61395fba24c5ad3e3f7393 Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 21:25:19 +0800 Subject: [PATCH 03/19] =?UTF-8?q?=E8=BF=81=E7=A7=BBsetup.sh=E5=88=B0SukiSU?= =?UTF-8?q?-Ultra?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/setup.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/setup.sh b/kernel/setup.sh index 3d042f9e..372728f5 100755 --- a/kernel/setup.sh +++ b/kernel/setup.sh @@ -6,9 +6,9 @@ GKI_ROOT=$(pwd) display_usage() { echo "Usage: $0 [--cleanup | ]" echo " --cleanup: Cleans up previous modifications made by the script." - echo " : Sets up or updates the KernelSU to specified tag or commit." + echo " : Sets up or updates the SukiSU-Ultra to specified tag or commit." echo " -h, --help: Displays this usage information." - echo " (no args): Sets up or updates the KernelSU environment to the latest tagged version." + echo " (no args): Sets up or updates the SukiSU-Ultra environment to the latest tagged version." } initialize_variables() { @@ -31,16 +31,16 @@ perform_cleanup() { [ -L "$DRIVER_DIR/kernelsu" ] && rm "$DRIVER_DIR/kernelsu" && echo "[-] Symlink removed." grep -q "kernelsu" "$DRIVER_MAKEFILE" && sed -i '/kernelsu/d' "$DRIVER_MAKEFILE" && echo "[-] Makefile reverted." grep -q "drivers/kernelsu/Kconfig" "$DRIVER_KCONFIG" && sed -i '/drivers\/kernelsu\/Kconfig/d' "$DRIVER_KCONFIG" && echo "[-] Kconfig reverted." - if [ -d "$GKI_ROOT/KernelSU" ]; then - rm -rf "$GKI_ROOT/KernelSU" && echo "[-] KernelSU directory deleted." + if [ -d "$GKI_ROOT/SukiSU-Ultra" ]; then + rm -rf "$GKI_ROOT/SukiSU-Ultra" && echo "[-] SukiSU-Ultra directory deleted." fi } -# Sets up or update KernelSU environment +# Sets up or update SukiSU-Ultra environment setup_kernelsu() { - echo "[+] Setting up KernelSU..." - test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/ShirkNeko/SukiSU-Ultra && echo "[+] Repository cloned." - cd "$GKI_ROOT/KernelSU" + echo "[+] Setting up SukiSU-Ultra..." + test -d "$GKI_ROOT/SukiSU-Ultra" || git clone https://github.com/ShirkNeko/SukiSU-Ultra && echo "[+] Repository cloned." + cd "$GKI_ROOT/SukiSU-Ultra" git stash && echo "[-] Stashed current changes." if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then git checkout main && echo "[-] Switched to main branch." @@ -52,7 +52,7 @@ setup_kernelsu() { git checkout "$1" && echo "[-] Checked out $1." || echo "[-] Checkout default branch" fi cd "$DRIVER_DIR" - ln -sf "$(realpath --relative-to="$DRIVER_DIR" "$GKI_ROOT/KernelSU/kernel")" "kernelsu" && echo "[+] Symlink created." + ln -sf "$(realpath --relative-to="$DRIVER_DIR" "$GKI_ROOT/SukiSU-Ultra/kernel")" "kernelsu" && echo "[+] Symlink created." # Add entries in Makefile and Kconfig if not already existing grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE" && echo "[+] Modified Makefile." From f7c5b511ccd215855a5aacd18948a4582e6223bc Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 21:26:11 +0800 Subject: [PATCH 04/19] =?UTF-8?q?=E4=BF=AE=E6=94=B9setup.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/setup.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/setup.sh b/kernel/setup.sh index 372728f5..172178d5 100755 --- a/kernel/setup.sh +++ b/kernel/setup.sh @@ -6,9 +6,9 @@ GKI_ROOT=$(pwd) display_usage() { echo "Usage: $0 [--cleanup | ]" echo " --cleanup: Cleans up previous modifications made by the script." - echo " : Sets up or updates the SukiSU-Ultra to specified tag or commit." + echo " : Sets up or updates the KernelSU to specified tag or commit." echo " -h, --help: Displays this usage information." - echo " (no args): Sets up or updates the SukiSU-Ultra environment to the latest tagged version." + echo " (no args): Sets up or updates the KernelSU environment to the latest tagged version." } initialize_variables() { @@ -31,16 +31,16 @@ perform_cleanup() { [ -L "$DRIVER_DIR/kernelsu" ] && rm "$DRIVER_DIR/kernelsu" && echo "[-] Symlink removed." grep -q "kernelsu" "$DRIVER_MAKEFILE" && sed -i '/kernelsu/d' "$DRIVER_MAKEFILE" && echo "[-] Makefile reverted." grep -q "drivers/kernelsu/Kconfig" "$DRIVER_KCONFIG" && sed -i '/drivers\/kernelsu\/Kconfig/d' "$DRIVER_KCONFIG" && echo "[-] Kconfig reverted." - if [ -d "$GKI_ROOT/SukiSU-Ultra" ]; then - rm -rf "$GKI_ROOT/SukiSU-Ultra" && echo "[-] SukiSU-Ultra directory deleted." + if [ -d "$GKI_ROOT/KernelSU" ]; then + rm -rf "$GKI_ROOT/KernelSU" && echo "[-] KernelSU directory deleted." fi } -# Sets up or update SukiSU-Ultra environment +# Sets up or update KernelSU environment setup_kernelsu() { - echo "[+] Setting up SukiSU-Ultra..." - test -d "$GKI_ROOT/SukiSU-Ultra" || git clone https://github.com/ShirkNeko/SukiSU-Ultra && echo "[+] Repository cloned." - cd "$GKI_ROOT/SukiSU-Ultra" + echo "[+] Setting up KernelSU..." + test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/ShirkNeko/SukiSU-Ultra -o KernelSU && echo "[+] Repository cloned." + cd "$GKI_ROOT/KernelSU" git stash && echo "[-] Stashed current changes." if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then git checkout main && echo "[-] Switched to main branch." @@ -52,7 +52,7 @@ setup_kernelsu() { git checkout "$1" && echo "[-] Checked out $1." || echo "[-] Checkout default branch" fi cd "$DRIVER_DIR" - ln -sf "$(realpath --relative-to="$DRIVER_DIR" "$GKI_ROOT/SukiSU-Ultra/kernel")" "kernelsu" && echo "[+] Symlink created." + ln -sf "$(realpath --relative-to="$DRIVER_DIR" "$GKI_ROOT/KernelSU/kernel")" "kernelsu" && echo "[+] Symlink created." # Add entries in Makefile and Kconfig if not already existing grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE" && echo "[+] Modified Makefile." From 72b205fa5e1f7de290e562020bf8e4e69ba74b18 Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 21:28:06 +0800 Subject: [PATCH 05/19] =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/setup.sh b/kernel/setup.sh index 172178d5..97086b1f 100755 --- a/kernel/setup.sh +++ b/kernel/setup.sh @@ -39,7 +39,7 @@ perform_cleanup() { # Sets up or update KernelSU environment setup_kernelsu() { echo "[+] Setting up KernelSU..." - test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/ShirkNeko/SukiSU-Ultra -o KernelSU && echo "[+] Repository cloned." + test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/ShirkNeko/SukiSU-Ultra KernelSU && echo "[+] Repository cloned." cd "$GKI_ROOT/KernelSU" git stash && echo "[-] Stashed current changes." if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then From f5cd410954013fc5aa192c87928d26fcd6be491b Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Sat, 29 Mar 2025 21:37:22 +0800 Subject: [PATCH 06/19] =?UTF-8?q?=E6=9B=B4=E6=96=B0setup.sh=E4=BB=A5?= =?UTF-8?q?=E5=85=8B=E9=9A=86=E5=B9=B6=E9=87=8D=E5=91=BD=E5=90=8DSukiSU-Ul?= =?UTF-8?q?tra=E4=B8=BAKernelSU?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/setup.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/setup.sh b/kernel/setup.sh index 97086b1f..973b86be 100755 --- a/kernel/setup.sh +++ b/kernel/setup.sh @@ -39,7 +39,12 @@ perform_cleanup() { # Sets up or update KernelSU environment setup_kernelsu() { echo "[+] Setting up KernelSU..." - test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/ShirkNeko/SukiSU-Ultra KernelSU && echo "[+] Repository cloned." + # Clone the repository and rename it to KernelSU + if [ ! -d "$GKI_ROOT/KernelSU" ]; then + git clone https://github.com/ShirkNeko/SukiSU-Ultra SukiSU-Ultra + mv SukiSU-Ultra KernelSU + echo "[+] Repository cloned and renamed to KernelSU." + fi cd "$GKI_ROOT/KernelSU" git stash && echo "[-] Stashed current changes." if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then @@ -72,4 +77,4 @@ elif [ "$1" = "--cleanup" ]; then else initialize_variables setup_kernelsu "$@" -fi +fi \ No newline at end of file From f11d57d2bd1241a6e7035c4c5ea53b74c2f9cbbc Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 22:32:39 +0800 Subject: [PATCH 07/19] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/compact.c | 18 +++++++++--------- kernel/kpm/kpm.c | 33 ++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/kernel/kpm/compact.c b/kernel/kpm/compact.c index 2c2ac533..d6f69705 100644 --- a/kernel/kpm/compact.c +++ b/kernel/kpm/compact.c @@ -31,7 +31,7 @@ unsigned long sukisu_compact_find_symbol(const char* name); // ====================================================================== -const char* kpver = "0.10"; +const char* kver = "0.10"; struct CompactAddressSymbol { const char* symbol_name; @@ -45,18 +45,18 @@ struct CompactAliasSymbol { struct CompactAddressSymbol address_symbol [] = { { "kallsyms_lookup_name", &kallsyms_lookup_name }, - { "compat_find_symbol", &sukisu_compact_find_symbol }, - { "compat_copy_to_user", ©_to_user }, - { "compat_strncpy_from_user", &strncpy_from_user }, - { "kpver", &kpver }, + { "compact_find_symbol", &sukisu_compact_find_symbol }, + { "compact_copy_to_user", ©_to_user }, + { "compact_strncpy_from_user", &strncpy_from_user }, + { "kver", &kver }, { "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"} + {"kf__strncat", "strncat"}, + {"kf__strlen", "strlen" }, + {"kf__strcpy", "strcpy"}, + {"compact_copy_to_user", "__arch_copy_to_user"} }; unsigned long sukisu_compact_find_symbol(const char* name) { diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index 0f9cc3dd..1b84cbf6 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -598,36 +598,47 @@ static int kpm_setup_load_info(struct kpm_load_info *info) * KPM 模块加载主流程 *----------------------------------------------------------*/ /* 注意:接口名称改为 kpm_load_module,避免与内核原有 load_module 冲突 */ -long kpm_load_module(const void *data, int len, const char *args, const char *event, void *__user reserved) +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) { + + /* 检查必须存在的模块初始化/退出段 */ + 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); + 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) - return -ENOMEM; + if (!mod) { + rc = -ENOMEM; + goto out; + } memset(mod, 0, sizeof(struct kpm_module)); if (args) { - mod->args = (typeof(mod->args)) vmalloc(strlen(args) + 1); + mod->args = vmalloc(strlen(args) + 1); if (!mod->args) { rc = -ENOMEM; goto free_mod; @@ -648,17 +659,21 @@ long kpm_load_module(const void *data, int len, const char *args, const char *ev if (rc) goto free_mod; - flush_icache_all(); + /* 替换 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 : ""); + 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); + printk(KERN_ERR "ARM64 KPM Loader: Module [%s] init failed with error %ld\n", + mod->info.name, rc); mod->exit(reserved); } free_mod: From 7b30b6636cb1fe94fb0cc57aa205c08ea2a58967 Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 22:46:18 +0800 Subject: [PATCH 08/19] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/compact.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/kernel/kpm/compact.c b/kernel/kpm/compact.c index d6f69705..61e99a35 100644 --- a/kernel/kpm/compact.c +++ b/kernel/kpm/compact.c @@ -31,7 +31,7 @@ unsigned long sukisu_compact_find_symbol(const char* name); // ====================================================================== -const char* kver = "0.10"; +const char* kpver = "0.10"; struct CompactAddressSymbol { const char* symbol_name; @@ -46,17 +46,17 @@ struct CompactAliasSymbol { struct CompactAddressSymbol address_symbol [] = { { "kallsyms_lookup_name", &kallsyms_lookup_name }, { "compact_find_symbol", &sukisu_compact_find_symbol }, - { "compact_copy_to_user", ©_to_user }, - { "compact_strncpy_from_user", &strncpy_from_user }, - { "kver", &kver }, + { "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"}, - {"compact_copy_to_user", "__arch_copy_to_user"} + {"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) { From 0ff2aedd653a7cf889245d55caf0c8111701c040 Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 23:09:16 +0800 Subject: [PATCH 09/19] =?UTF-8?q?=E6=8C=89=E7=85=A7AI=E7=BB=99=E5=87=BA?= =?UTF-8?q?=E5=BB=BA=E8=AE=AE=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/kpm.c | 86 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index 1b84cbf6..a790bbd7 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -481,45 +481,81 @@ static int kpm_rewrite_section_headers(struct kpm_load_info *info) /*----------------------------------------------------------- * 将各段复制到连续内存区域中 *----------------------------------------------------------*/ +/*----------------------------------------------------------- + * 将各段复制到连续内存区域(修复版) + * 关键修复点: + * 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; - printk(KERN_INFO "ARM64 KPM Loader: Allocating module memory: size=0x%x\n", mod->size); - mod->start = kpm_malloc_exec(mod->size); - if (!mod->start) + /* 分配连续内存(按页对齐) */ + 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); - printk(KERN_INFO "ARM64 KPM Loader: Final section addresses:\n"); - for (i = 1; i < info->ehdr->e_shnum; i++) { - void *dest; - Elf64_Shdr *shdr = &info->sechdrs[i]; + /* 设置内存可执行权限(关键修复) */ + 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; - dest = mod->start + shdr->sh_entsize; - if (shdr->sh_type != SHT_NOBITS) + + /* 按段对齐要求调整偏移 */ + curr_offset = ALIGN(curr_offset, shdr->sh_addralign); + void *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; - if (!mod->init && !strcmp(".kpm.init", info->secstrings + shdr->sh_name)) + curr_offset += shdr->sh_size; + + /* 定位关键函数指针 */ + const char *secname = info->secstrings + shdr->sh_name; + if (!mod->init && !strcmp(".kpm.init", secname)) { mod->init = (int (*)(const char *, const char *, void *__user))dest; - if (!strcmp(".kpm.exit", info->secstrings + shdr->sh_name)) + printk(KERN_DEBUG "Found .kpm.init at 0x%px\n", dest); + } else if (!strcmp(".kpm.exit", secname)) { mod->exit = (void (*)(void *__user))dest; - if (!strcmp(".kpm.ctl0", info->secstrings + shdr->sh_name)) - mod->ctl0 = (int (*)(const char *, char *__user, int))dest; - if (!strcmp(".kpm.ctl1", info->secstrings + shdr->sh_name)) - mod->ctl1 = (int (*)(void *, void *, void *))dest; - if (!mod->info.base && !strcmp(".kpm.info", info->secstrings + shdr->sh_name)) - mod->info.base = (const char *)dest; + } } - mod->info.name = info->info.name - info->info.base + mod->info.base; - mod->info.version = info->info.version - info->info.base + mod->info.base; - if (info->info.license) - mod->info.license = info->info.license - info->info.base + mod->info.base; - if (info->info.author) - mod->info.author = info->info.author - info->info.base + mod->info.base; - if (info->info.description) - mod->info.description = info->info.description - info->info.base + mod->info.base; + + /* 调整元数据指针(基于新基址) */ + 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; } From 032bc68154182e4ce9cb257b07170e8e22d67fd6 Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 23:20:48 +0800 Subject: [PATCH 10/19] 1 --- kernel/kpm/kpm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index a790bbd7..5af62d2e 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -493,6 +493,7 @@ 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; /* 分配连续内存(按页对齐) */ mod->size = ALIGN(mod->size, PAGE_SIZE); @@ -516,7 +517,7 @@ static int kpm_move_module(struct kpm_module *mod, struct kpm_load_info *info) /* 按段对齐要求调整偏移 */ curr_offset = ALIGN(curr_offset, shdr->sh_addralign); - void *dest = mod->start + curr_offset; + dest = mod->start + curr_offset; /* 复制段内容(NOBITS 段不复制) */ if (shdr->sh_type != SHT_NOBITS) { From 17a2efb135f8c60764393860b78694ad71c07399 Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 23:28:27 +0800 Subject: [PATCH 11/19] 2 --- kernel/kpm/kpm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index 5af62d2e..172b4646 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -494,6 +494,7 @@ static int kpm_move_module(struct kpm_module *mod, struct kpm_load_info *info) unsigned long curr_offset = 0; Elf64_Shdr *shdr; void *dest; + const char *secname; /* 分配连续内存(按页对齐) */ mod->size = ALIGN(mod->size, PAGE_SIZE); @@ -535,7 +536,7 @@ static int kpm_move_module(struct kpm_module *mod, struct kpm_load_info *info) curr_offset += shdr->sh_size; /* 定位关键函数指针 */ - const char *secname = info->secstrings + shdr->sh_name; + 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); From bd8f051c73c568a3d47ee14931c332cc497424fb Mon Sep 17 00:00:00 2001 From: liankong Date: Sat, 29 Mar 2025 23:51:49 +0800 Subject: [PATCH 12/19] 2 --- kernel/kpm/kpm.c | 131 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 109 insertions(+), 22 deletions(-) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index 172b4646..f4a0403f 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -478,6 +478,87 @@ static int kpm_rewrite_section_headers(struct kpm_load_info *info) return 0; } +/*----------------------------------------------------------- + * 增强版重定位处理(ARM64) + *----------------------------------------------------------*/ +static int kpm_apply_relocations(struct kpm_module *mod, struct kpm_load_info *info) +{ + int i; + for (i = 0; i < info->ehdr->e_shnum; i++) { + Elf64_Shdr *shdr = &info->sechdrs[i]; + size_t j, num; + Elf64_Rela *relas; + if (shdr->sh_type != SHT_RELA) + continue; + + relas = (Elf64_Rela *)((char *)info->hdr + shdr->sh_offset); + num = shdr->sh_size / sizeof(Elf64_Rela); + + + for (j = 0; j < num; j++) { + Elf64_Rela *rela = &relas[j]; + uint32_t type = ELF64_R_TYPE(rela->r_info); + uint32_t sym_idx = ELF64_R_SYM(rela->r_info); + unsigned long *target = (unsigned long *)(mod->start + rela->r_offset); + + /* 解析符号地址 */ + Elf64_Sym *sym = &info->syms[sym_idx]; + unsigned long sym_addr = 0; + if (ELF64_ST_BIND(sym->st_info) == STB_GLOBAL) { + const char *name = info->strtab + sym->st_name; + sym_addr = kallsyms_lookup_name_fn(name); // 使用动态解析的符号查找函数 + if (!sym_addr) { + printk(KERN_ERR "Symbol %s not found!\n", name); + return -ENOENT; + } + } else { + sym_addr = (unsigned long)mod->start + sym->st_value; + } + + /* 处理重定位类型 */ + switch (type) { + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: { + int64_t offset = sym_addr - (unsigned long)target - 4; + uint32_t insn; + offset >>= 2; // 指令偏移单位为4字节 + + /* 校验偏移范围(±128MB) */ + if (offset < -0x2000000 || offset > 0x1FFFFFF) { + printk(KERN_ERR "Reloc offset 0x%llx out of range!\n", offset); + return -ERANGE; + } + + insn = le32_to_cpu(*(uint32_t*)target); + insn = (insn & ~0x03FFFFFF) | (offset & 0x03FFFFFF); + *(uint32_t*)target = cpu_to_le32(insn); + break; + } + case R_AARCH64_ADR_PREL_PG_HI21: { + /* 页对齐计算 */ + unsigned long base_page = (sym_addr >> 12) << 12; + unsigned long target_page = ((unsigned long)target >> 12) << 12; + int64_t page_offset = (base_page - target_page) >> 12; + + /* 编码到指令高21位 */ + uint32_t insn = le32_to_cpu(*(uint32_t*)target); + insn &= ~0x1FFFFF; + insn |= (page_offset & 0x1FFFFF) << 3; + *(uint32_t*)target = cpu_to_le32(insn); + break; + } + case R_AARCH64_ABS64: + *target = sym_addr + rela->r_addend; + break; + default: + printk(KERN_ERR "Unsupported relocation type: 0x%x\n", type); + return -EINVAL; + } + } + } + return 0; +} + /*----------------------------------------------------------- * 将各段复制到连续内存区域中 *----------------------------------------------------------*/ @@ -493,38 +574,44 @@ 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 接口 + /* 步骤1:计算总内存需求(按最大对齐) */ + size_t total_size = 0; + for (i = 0; i < info->ehdr->e_shnum; i++) { + shdr = &info->sechdrs[i]; + if (!(shdr->sh_flags & SHF_ALLOC)) continue; + + total_size = ALIGN(total_size, shdr->sh_addralign); + total_size += shdr->sh_size; + } + mod->size = ALIGN(total_size, PAGE_SIZE); + + /* 步骤2:分配对齐内存并设置权限 */ + mod->start = module_alloc(mod->size); if (!mod->start) { - printk(KERN_ERR "ARM64 KPM Loader: Failed to allocate module memory\n"); + printk(KERN_ERR "ARM64 KPM Loader: Failed to allocate 0x%zx bytes\n", mod->size); 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); - - /* 遍历所有段并按对齐要求布局 */ + /* 步骤3:复制段数据并处理对齐 */ for (i = 0; i < info->ehdr->e_shnum; i++) { - shdr = &info->sechdrs[i]; - if (!(shdr->sh_flags & SHF_ALLOC)) - continue; + void *dest; + const char *secname; - /* 按段对齐要求调整偏移 */ + 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); @@ -535,17 +622,17 @@ static int kpm_move_module(struct kpm_module *mod, struct kpm_load_info *info) shdr->sh_addr = (unsigned long)dest; curr_offset += shdr->sh_size; - /* 定位关键函数指针 */ + /* 定位关键函数(init/exit) */ secname = info->secstrings + shdr->sh_name; - if (!mod->init && !strcmp(".kpm.init", secname)) { + if (!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); + printk(KERN_DEBUG "Located .kpm.init at 0x%px\n", dest); } else if (!strcmp(".kpm.exit", secname)) { mod->exit = (void (*)(void *__user))dest; } } - /* 调整元数据指针(基于新基址) */ + /* 步骤4:调整元数据指针 */ 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); @@ -553,7 +640,7 @@ static int kpm_move_module(struct kpm_module *mod, struct kpm_load_info *info) 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); + 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); } From 97c19b07ae80e5bb037d093c597914f6b8d02de2 Mon Sep 17 00:00:00 2001 From: liankong Date: Sun, 30 Mar 2025 00:36:12 +0800 Subject: [PATCH 13/19] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/kpm.c | 182 ++++++++++++++++------------------------------- 1 file changed, 61 insertions(+), 121 deletions(-) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index f4a0403f..e5b78dff 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -361,19 +361,21 @@ static int kpm_simplify_symbols(struct kpm_module *mod, const struct kpm_load_in return ret; } -/* ARM64 重定位处理:支持 R_AARCH64_RELATIVE 与 R_AARCH64_ABS64 */ +/* 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_Rela *rel = (Elf64_Rela *)((char *)mod->start + relsec->sh_entsize); + 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 + rel[i].r_addend; + *addr = (unsigned long)mod->start + *(unsigned long *)addr; break; default: printk(KERN_ERR "ARM64 KPM Loader: Unsupported REL relocation type %lu\n", type); @@ -387,12 +389,14 @@ static int kpm_apply_relocate_add_arm64(Elf64_Shdr *sechdrs, const char *strtab, { Elf64_Shdr *relasec = &sechdrs[rela_idx]; int num = relasec->sh_size / sizeof(Elf64_Rela); - Elf64_Rela *rela = (Elf64_Rela *)((char *)mod->start + relasec->sh_entsize); + Elf64_Rela *rela = (Elf64_Rela *)((char *)mod->start + relasec->sh_offset); // 修正为 sh_offset int i; + 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); unsigned long *addr = (unsigned long *)(mod->start + rela[i].r_offset); + switch (type) { case R_AARCH64_RELATIVE: *addr = (unsigned long)mod->start + rela[i].r_addend; @@ -400,12 +404,22 @@ static int kpm_apply_relocate_add_arm64(Elf64_Shdr *sechdrs, const char *strtab, case R_AARCH64_ABS64: if (sym_index) { Elf64_Sym *sym = (Elf64_Sym *)((char *)mod->start + sechdrs[sym_idx].sh_offset) + sym_index; - *addr = sym->st_value + rela[i].r_addend; + *addr = (unsigned long)mod->start + sym->st_value + rela[i].r_addend; // 修正:确保 st_value 是绝对地址 } 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) { + Elf64_Sym *sym = (Elf64_Sym *)((char *)mod->start + sechdrs[sym_idx].sh_offset) + sym_index; + *addr = (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; default: printk(KERN_ERR "ARM64 KPM Loader: Unsupported RELA relocation type %lu\n", type); return -EINVAL; @@ -418,22 +432,36 @@ static int kpm_apply_relocations(struct kpm_module *mod, const struct kpm_load_i { 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) + + 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[target].sh_flags & SHF_ALLOC)) - continue; - if (info->sechdrs[i].sh_type == SHT_REL) + } + + 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) + } 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) + } + + if (rc < 0) { + printk(KERN_ERR "ARM64 KPM Loader: Relocation failed at section %d, error %d\n", i, rc); break; + } } + return rc; } + /*----------------------------------------------------------- * 符号表与字符串表布局 *----------------------------------------------------------*/ @@ -478,87 +506,6 @@ static int kpm_rewrite_section_headers(struct kpm_load_info *info) return 0; } -/*----------------------------------------------------------- - * 增强版重定位处理(ARM64) - *----------------------------------------------------------*/ -static int kpm_apply_relocations(struct kpm_module *mod, struct kpm_load_info *info) -{ - int i; - for (i = 0; i < info->ehdr->e_shnum; i++) { - Elf64_Shdr *shdr = &info->sechdrs[i]; - size_t j, num; - Elf64_Rela *relas; - if (shdr->sh_type != SHT_RELA) - continue; - - relas = (Elf64_Rela *)((char *)info->hdr + shdr->sh_offset); - num = shdr->sh_size / sizeof(Elf64_Rela); - - - for (j = 0; j < num; j++) { - Elf64_Rela *rela = &relas[j]; - uint32_t type = ELF64_R_TYPE(rela->r_info); - uint32_t sym_idx = ELF64_R_SYM(rela->r_info); - unsigned long *target = (unsigned long *)(mod->start + rela->r_offset); - - /* 解析符号地址 */ - Elf64_Sym *sym = &info->syms[sym_idx]; - unsigned long sym_addr = 0; - if (ELF64_ST_BIND(sym->st_info) == STB_GLOBAL) { - const char *name = info->strtab + sym->st_name; - sym_addr = kallsyms_lookup_name_fn(name); // 使用动态解析的符号查找函数 - if (!sym_addr) { - printk(KERN_ERR "Symbol %s not found!\n", name); - return -ENOENT; - } - } else { - sym_addr = (unsigned long)mod->start + sym->st_value; - } - - /* 处理重定位类型 */ - switch (type) { - case R_AARCH64_CALL26: - case R_AARCH64_JUMP26: { - int64_t offset = sym_addr - (unsigned long)target - 4; - uint32_t insn; - offset >>= 2; // 指令偏移单位为4字节 - - /* 校验偏移范围(±128MB) */ - if (offset < -0x2000000 || offset > 0x1FFFFFF) { - printk(KERN_ERR "Reloc offset 0x%llx out of range!\n", offset); - return -ERANGE; - } - - insn = le32_to_cpu(*(uint32_t*)target); - insn = (insn & ~0x03FFFFFF) | (offset & 0x03FFFFFF); - *(uint32_t*)target = cpu_to_le32(insn); - break; - } - case R_AARCH64_ADR_PREL_PG_HI21: { - /* 页对齐计算 */ - unsigned long base_page = (sym_addr >> 12) << 12; - unsigned long target_page = ((unsigned long)target >> 12) << 12; - int64_t page_offset = (base_page - target_page) >> 12; - - /* 编码到指令高21位 */ - uint32_t insn = le32_to_cpu(*(uint32_t*)target); - insn &= ~0x1FFFFF; - insn |= (page_offset & 0x1FFFFF) << 3; - *(uint32_t*)target = cpu_to_le32(insn); - break; - } - case R_AARCH64_ABS64: - *target = sym_addr + rela->r_addend; - break; - default: - printk(KERN_ERR "Unsupported relocation type: 0x%x\n", type); - return -EINVAL; - } - } - } - return 0; -} - /*----------------------------------------------------------- * 将各段复制到连续内存区域中 *----------------------------------------------------------*/ @@ -574,44 +521,38 @@ 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; - /* 步骤1:计算总内存需求(按最大对齐) */ - size_t total_size = 0; - for (i = 0; i < info->ehdr->e_shnum; i++) { - shdr = &info->sechdrs[i]; - if (!(shdr->sh_flags & SHF_ALLOC)) continue; - - total_size = ALIGN(total_size, shdr->sh_addralign); - total_size += shdr->sh_size; - } - mod->size = ALIGN(total_size, PAGE_SIZE); - - /* 步骤2:分配对齐内存并设置权限 */ - mod->start = module_alloc(mod->size); + /* 分配连续内存(按页对齐) */ + 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 0x%zx bytes\n", mod->size); + 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); - /* 步骤3:复制段数据并处理对齐 */ + 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++) { - void *dest; - const char *secname; - shdr = &info->sechdrs[i]; - if (!(shdr->sh_flags & SHF_ALLOC)) continue; + 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); @@ -622,17 +563,17 @@ static int kpm_move_module(struct kpm_module *mod, struct kpm_load_info *info) shdr->sh_addr = (unsigned long)dest; curr_offset += shdr->sh_size; - /* 定位关键函数(init/exit) */ + /* 定位关键函数指针 */ secname = info->secstrings + shdr->sh_name; - if (!strcmp(".kpm.init", secname)) { + if (!mod->init && !strcmp(".kpm.init", secname)) { mod->init = (int (*)(const char *, const char *, void *__user))dest; - printk(KERN_DEBUG "Located .kpm.init at 0x%px\n", dest); + printk(KERN_DEBUG "Found .kpm.init at 0x%px\n", dest); } else if (!strcmp(".kpm.exit", secname)) { mod->exit = (void (*)(void *__user))dest; } } - /* 步骤4:调整元数据指针 */ + /* 调整元数据指针(基于新基址) */ 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); @@ -640,7 +581,7 @@ static int kpm_move_module(struct kpm_module *mod, struct kpm_load_info *info) 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; + 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); } @@ -1069,5 +1010,4 @@ int sukisu_is_kpm_control_code(unsigned long arg2) { return (arg2 >= CMD_KPM_CONTROL && arg2 <= CMD_KPM_CONTROL_MAX) ? 1 : 0; } -EXPORT_SYMBOL(sukisu_handle_kpm); - +EXPORT_SYMBOL(sukisu_handle_kpm); \ No newline at end of file From 634c9b3c04b47be1cc1cd797e1aacf4b489f438c Mon Sep 17 00:00:00 2001 From: liankong Date: Sun, 30 Mar 2025 00:51:13 +0800 Subject: [PATCH 14/19] 1 --- kernel/kpm/kpm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index e5b78dff..c34bfc93 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -385,6 +385,13 @@ static int kpm_apply_relocate_arm64(Elf64_Shdr *sechdrs, const char *strtab, int 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 + 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]; From 3bbf8c0d5a55735d1248e4ecb7b93c3ca7935f35 Mon Sep 17 00:00:00 2001 From: liankong Date: Sun, 30 Mar 2025 01:03:55 +0800 Subject: [PATCH 15/19] =?UTF-8?q?=E4=BF=AE=E5=A4=8DR=5FAARCH64=5FNONE?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/kpm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index c34bfc93..dd30cc97 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -391,6 +391,9 @@ static int kpm_apply_relocate_arm64(Elf64_Shdr *sechdrs, const char *strtab, int #ifndef R_AARCH64_JUMP_SLOT #define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */ #endif +#ifndef R_AARCH64_NONE +#define R_AARCH64_NONE 0 +#endif static int kpm_apply_relocate_add_arm64(Elf64_Shdr *sechdrs, const char *strtab, int sym_idx, int rela_idx, struct kpm_module *mod) { @@ -404,6 +407,10 @@ static int kpm_apply_relocate_add_arm64(Elf64_Shdr *sechdrs, const char *strtab, unsigned long sym_index = ELF64_R_SYM(rela[i].r_info); unsigned long *addr = (unsigned long *)(mod->start + rela[i].r_offset); + if(type == R_AARCH64_NONE) { + continue; + } + switch (type) { case R_AARCH64_RELATIVE: *addr = (unsigned long)mod->start + rela[i].r_addend; From a1aee70467b7f676fdea9e51ed636da8c95a7387 Mon Sep 17 00:00:00 2001 From: liankong Date: Sun, 30 Mar 2025 01:29:50 +0800 Subject: [PATCH 16/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=87=8D=E5=AE=9A?= =?UTF-8?q?=E4=BD=8D=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/kpm.c | 228 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 203 insertions(+), 25 deletions(-) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index dd30cc97..e4359886 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -391,54 +391,232 @@ static int kpm_apply_relocate_arm64(Elf64_Shdr *sechdrs, const char *strtab, int #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 0 +#define R_AARCH64_NONE 256 #endif -static int kpm_apply_relocate_add_arm64(Elf64_Shdr *sechdrs, const char *strtab, int sym_idx, int rela_idx, struct kpm_module *mod) +/* 重定位操作类型 */ +typedef enum { + RELOC_OP_ABS, + RELOC_OP_PREL, + RELOC_OP_PAGE +} reloc_op_t; + +/* 指令编码辅助函数 */ +static int reloc_data(reloc_op_t op, void *loc, u64 val, int len) +{ + u64 imm = val; + int shift = 0; + + switch (op) { + case RELOC_OP_ABS: + break; + case RELOC_OP_PREL: + imm -= (u64)loc; + break; + case RELOC_OP_PAGE: + imm = (imm >> 12) - ((u64)loc >> 12); + shift = 12; + break; + default: + return -EINVAL; + } + + switch (len) { + case 16: + *(u16 *)loc = cpu_to_le16(imm >> shift); + break; + case 32: + *(u32 *)loc = cpu_to_le32(imm >> shift); + break; + case 64: + *(u64 *)loc = cpu_to_le64(imm >> shift); + break; + default: + return -EINVAL; + } + + /* 检查溢出 */ + if (imm > (BIT_ULL(len) - 1) << shift) + return -ERANGE; + return 0; +} + +/* MOVW 指令重定位 */ +static int reloc_insn_movw(reloc_op_t op, void *loc, u64 val, int shift, aarch64_insn_imm_type imm_type) +{ + u64 imm = val; + s64 sval; + + switch (op) { + case RELOC_OP_ABS: + break; + case RELOC_OP_PREL: + imm -= (u64)loc; + break; + default: + return -EINVAL; + } + + sval = (s64)imm; + return aarch64_insn_patch_imm(loc, imm_type, sval >> shift); +} + +/* 立即数指令重定位 */ +static int reloc_insn_imm(reloc_op_t op, void *loc, u64 val, int shift, int len, aarch64_insn_imm_type imm_type) +{ + u64 imm = val; + s64 sval; + + switch (op) { + case RELOC_OP_ABS: + break; + case RELOC_OP_PREL: + imm -= (u64)loc; + break; + case RELOC_OP_PAGE: + imm = (imm >> 12) - ((u64)loc >> 12); + shift = 0; + break; + default: + return -EINVAL; + } + + sval = (s64)imm; + return aarch64_insn_patch_imm(loc, imm_type, sval >> shift); +} + +/* 完整的 ARM64 重定位适配 */ +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); - Elf64_Rela *rela = (Elf64_Rela *)((char *)mod->start + relasec->sh_offset); // 修正为 sh_offset - int i; + Elf64_Rela *rela = (Elf64_Rela *)((char *)mod->start + relasec->sh_offset); + int i, ovf; + bool overflow_check; 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); - unsigned long *addr = (unsigned long *)(mod->start + rela[i].r_offset); + void *loc = (void *)(mod->start + rela[i].r_offset); + u64 val; + Elf64_Sym *sym; - if(type == R_AARCH64_NONE) { + /* 处理特殊重定位类型 */ + if (type == R_AARCH64_NONE || type == R_ARM_NONE) continue; + + /* 解析符号值 */ + if (sym_index) { + sym = (Elf64_Sym *)((char *)mod->start + sechdrs[sym_idx].sh_offset) + sym_index; + val = sym->st_value + rela[i].r_addend; + + /* 全局符号需通过内核解析 */ + if (ELF64_ST_BIND(sym->st_info) == STB_GLOBAL) { + const char *name = strtab + sym->st_name; + unsigned long addr = kallsyms_lookup_name(name); + if (!addr) { + printk(KERN_ERR "KPM: Symbol %s not found!\n", name); + return -ENOENT; + } + val = addr + rela[i].r_addend; + } else { + val += (u64)mod->start; // 转换为模块内绝对地址 + } + } else { + val = rela[i].r_addend; } + overflow_check = true; + + /* 处理所有重定位类型 */ switch (type) { - case R_AARCH64_RELATIVE: - *addr = (unsigned long)mod->start + rela[i].r_addend; - break; + /* 数据重定位 */ case R_AARCH64_ABS64: - if (sym_index) { - Elf64_Sym *sym = (Elf64_Sym *)((char *)mod->start + sechdrs[sym_idx].sh_offset) + sym_index; - *addr = (unsigned long)mod->start + sym->st_value + rela[i].r_addend; // 修正:确保 st_value 是绝对地址 - } else { - printk(KERN_ERR "ARM64 KPM Loader: R_AARCH64_ABS64 with zero symbol\n"); - return -EINVAL; - } + 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 指令 */ + 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_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: + ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 0, 12, AARCH64_INSN_IMM_12); + 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; + + /* GOT 相关 */ case R_AARCH64_GLOB_DAT: case R_AARCH64_JUMP_SLOT: - if (sym_index) { - Elf64_Sym *sym = (Elf64_Sym *)((char *)mod->start + sechdrs[sym_idx].sh_offset) + sym_index; - *addr = (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; - } + *((u64 *)loc) = val; + ovf = 0; break; + default: - printk(KERN_ERR "ARM64 KPM Loader: Unsupported RELA relocation type %lu\n", type); - return -EINVAL; + printk(KERN_ERR "KPM: Unsupported relocation type %lu\n", type); + return -ENOEXEC; + } + + if (overflow_check && ovf == -ERANGE) { + printk(KERN_ERR "KPM: Relocation overflow (type %lu val 0x%llx)\n", type, val); + return -ENOEXEC; + } else if (ovf) { + return ovf; } } + return 0; } From 31852bc2b84a588bbf2cdf22e2ce8f3e46dd2ce5 Mon Sep 17 00:00:00 2001 From: liankong Date: Sun, 30 Mar 2025 01:35:03 +0800 Subject: [PATCH 17/19] =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/kpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index e4359886..b4b8fb11 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "kpm.h" #include "compact.h" From 269aea7cfc0ab4210c96589e91982ce23b999c49 Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Sun, 30 Mar 2025 01:54:27 +0800 Subject: [PATCH 18/19] Add KPM module support, update related strings and view models --- .../sukisu/ui/screen/BottomBarDestination.kt | 2 + .../shirkneko/zako/sukisu/ui/screen/kpm.kt | 297 ++++++++++++++++++ .../shirkneko/zako/sukisu/ui/util/KsuCli.kt | 54 ++++ .../zako/sukisu/ui/viewmodel/KpmViewModel.kt | 98 ++++++ manager/app/src/main/res/values/strings.xml | 2 + 5 files changed, 453 insertions(+) create mode 100644 manager/app/src/main/java/shirkneko/zako/sukisu/ui/screen/kpm.kt create mode 100644 manager/app/src/main/java/shirkneko/zako/sukisu/ui/viewmodel/KpmViewModel.kt diff --git a/manager/app/src/main/java/shirkneko/zako/sukisu/ui/screen/BottomBarDestination.kt b/manager/app/src/main/java/shirkneko/zako/sukisu/ui/screen/BottomBarDestination.kt index 129411b2..285acbd9 100644 --- a/manager/app/src/main/java/shirkneko/zako/sukisu/ui/screen/BottomBarDestination.kt +++ b/manager/app/src/main/java/shirkneko/zako/sukisu/ui/screen/BottomBarDestination.kt @@ -9,6 +9,7 @@ import com.ramcosta.composedestinations.generated.destinations.HomeScreenDestina import com.ramcosta.composedestinations.generated.destinations.ModuleScreenDestination import com.ramcosta.composedestinations.generated.destinations.SuperUserScreenDestination import com.ramcosta.composedestinations.generated.destinations.SettingScreenDestination +import com.ramcosta.composedestinations.generated.destinations.KpmScreenDestination import com.ramcosta.composedestinations.spec.DirectionDestinationSpec import shirkneko.zako.sukisu.R @@ -22,5 +23,6 @@ enum class BottomBarDestination( Home(HomeScreenDestination, R.string.home, Icons.Filled.Home, Icons.Outlined.Home, false), SuperUser(SuperUserScreenDestination, R.string.superuser, Icons.Filled.Security, Icons.Outlined.Security, true), Module(ModuleScreenDestination, R.string.module, Icons.Filled.Apps, Icons.Outlined.Apps, true), + Kpm(KpmScreenDestination, R.string.kpm_title, Icons.Filled.Build, Icons.Outlined.Build, true), Settings(SettingScreenDestination, R.string.settings, Icons.Filled.Settings, Icons.Outlined.Settings, false), } diff --git a/manager/app/src/main/java/shirkneko/zako/sukisu/ui/screen/kpm.kt b/manager/app/src/main/java/shirkneko/zako/sukisu/ui/screen/kpm.kt new file mode 100644 index 00000000..ecbc59a6 --- /dev/null +++ b/manager/app/src/main/java/shirkneko/zako/sukisu/ui/screen/kpm.kt @@ -0,0 +1,297 @@ +package shirkneko.zako.sukisu.ui.screen + +import android.app.Activity.RESULT_OK +import android.content.Intent +import android.util.Log +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.* +import androidx.compose.material3.* +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.navigation.DestinationsNavigator +import kotlinx.coroutines.launch +import shirkneko.zako.sukisu.R +import shirkneko.zako.sukisu.ui.component.ConfirmResult +import shirkneko.zako.sukisu.ui.component.SearchAppBar +import shirkneko.zako.sukisu.ui.component.rememberConfirmDialog +import shirkneko.zako.sukisu.ui.component.rememberLoadingDialog +import shirkneko.zako.sukisu.ui.theme.getCardColors +import shirkneko.zako.sukisu.ui.theme.getCardElevation +import shirkneko.zako.sukisu.ui.viewmodel.KpmViewModel +import shirkneko.zako.sukisu.ui.util.loadKpmModule +import shirkneko.zako.sukisu.ui.util.unloadKpmModule +import java.io.File + +@OptIn(ExperimentalMaterial3Api::class) +@Destination +@Composable +fun KpmScreen( + navigator: DestinationsNavigator, + viewModel: KpmViewModel = viewModel() +) { + val context = LocalContext.current + val scope = rememberCoroutineScope() + val snackBarHost = remember { SnackbarHostState() } + val confirmDialog = rememberConfirmDialog() + val loadingDialog = rememberLoadingDialog() + + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) + + val kpmInstall = stringResource(R.string.kpm_install) + val kpmInstallConfirm = stringResource(R.string.kpm_install_confirm) + val kpmInstallSuccess = stringResource(R.string.kpm_install_success) + val kpmInstallFailed = stringResource(R.string.kpm_install_failed) + val install = stringResource(R.string.install) + val cancel = stringResource(R.string.cancel) + val kpmUninstall = stringResource(R.string.kpm_uninstall) + val kpmUninstallConfirmTemplate = stringResource(R.string.kpm_uninstall_confirm) + val uninstall = stringResource(R.string.uninstall) + val kpmUninstallSuccess = stringResource(R.string.kpm_uninstall_success) + val kpmUninstallFailed = stringResource(R.string.kpm_uninstall_failed) + + val selectPatchLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult() + ) { result -> + if (result.resultCode != RESULT_OK) return@rememberLauncherForActivityResult + + val uri = result.data?.data ?: return@rememberLauncherForActivityResult + + scope.launch { + // 复制文件到临时目录 + val tempFile = File(context.cacheDir, "temp_patch.kpm") + context.contentResolver.openInputStream(uri)?.use { input -> + tempFile.outputStream().use { output -> + input.copyTo(output) + } + } + + val confirmResult = confirmDialog.awaitConfirm( + title = kpmInstall, + content = kpmInstallConfirm, + confirm = install, + dismiss = cancel + ) + + if (confirmResult == ConfirmResult.Confirmed) { + val success = loadingDialog.withLoading { + loadKpmModule(tempFile.absolutePath) + } + + Log.d("KsuCli", "loadKpmModule result: $success") + + if (success == "success") { + viewModel.fetchModuleList() + snackBarHost.showSnackbar( + message = kpmInstallSuccess, + duration = SnackbarDuration.Long + ) + } else { + // 修正为显示安装失败的消息 + snackBarHost.showSnackbar( + message = kpmInstallFailed, + duration = SnackbarDuration.Long + ) + } + } + tempFile.delete() + } + } + + LaunchedEffect(Unit) { + if (viewModel.moduleList.isEmpty()) { + viewModel.fetchModuleList() + } + } + + Scaffold( + topBar = { + SearchAppBar( + title = { Text(stringResource(R.string.kpm_title)) }, + searchText = viewModel.search, + onSearchTextChange = { viewModel.search = it }, + onClearClick = { viewModel.search = "" }, + scrollBehavior = scrollBehavior, + dropdownContent = { + IconButton(onClick = { viewModel.fetchModuleList() }) { + Icon( + imageVector = Icons.Outlined.Refresh, + contentDescription = stringResource(R.string.refresh) + ) + } + } + ) + }, + floatingActionButton = { + ExtendedFloatingActionButton( + onClick = { + selectPatchLauncher.launch( + Intent(Intent.ACTION_GET_CONTENT).apply { + type = "application/*" + } + ) + }, + icon = { + Icon( + imageVector = Icons.Outlined.Add, + contentDescription = stringResource(R.string.kpm_install) + ) + }, + text = { Text(stringResource(R.string.kpm_install)) }, + containerColor = MaterialTheme.colorScheme.secondaryContainer, + contentColor = MaterialTheme.colorScheme.onSecondaryContainer + ) + }, + snackbarHost = { SnackbarHost(snackBarHost) } + ) { padding -> + PullToRefreshBox( + onRefresh = { viewModel.fetchModuleList() }, + isRefreshing = viewModel.isRefreshing, + modifier = Modifier.padding(padding) + ) { + if (viewModel.moduleList.isEmpty()) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + stringResource(R.string.kpm_empty), + textAlign = TextAlign.Center + ) + } + } else { + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + items(viewModel.moduleList) { module -> + val kpmUninstallConfirm = String.format(kpmUninstallConfirmTemplate, module.name) + KpmModuleItem( + module = module, + onUninstall = { + scope.launch { + val confirmResult = confirmDialog.awaitConfirm( + title = kpmUninstall, + content = kpmUninstallConfirm, + confirm = uninstall, + dismiss = cancel + ) + if (confirmResult == ConfirmResult.Confirmed) { + val success = loadingDialog.withLoading { + unloadKpmModule(module.id) + } + Log.d("KsuCli", "unloadKpmModule result: $success") + if (success == "success") { + viewModel.fetchModuleList() + snackBarHost.showSnackbar( + message = kpmUninstallSuccess, + duration = SnackbarDuration.Long + ) + } else { + snackBarHost.showSnackbar( + message = kpmUninstallFailed, + duration = SnackbarDuration.Long + ) + } + } + } + }, + onControl = { + viewModel.loadModuleDetail(module.id) + } + ) + } + } + } + } + } +} + +@Composable +private fun KpmModuleItem( + module: KpmViewModel.ModuleInfo, + onUninstall: () -> Unit, + onControl: () -> Unit +) { + ElevatedCard( + colors = getCardColors(MaterialTheme.colorScheme.secondaryContainer), + elevation = CardDefaults.cardElevation(defaultElevation = getCardElevation()) + ) { + Column( + modifier = Modifier.padding(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = module.name, + style = MaterialTheme.typography.titleMedium + ) + Text( + text = "${stringResource(R.string.kpm_version)}: ${module.version}", + style = MaterialTheme.typography.bodyMedium + ) + Text( + text = "${stringResource(R.string.kpm_author)}: ${module.author}", + style = MaterialTheme.typography.bodyMedium + ) + Text( + text = "${stringResource(R.string.kpm_args)}: ${module.args}", + style = MaterialTheme.typography.bodyMedium + ) + } + } + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = module.description, + style = MaterialTheme.typography.bodyMedium + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + FilledTonalButton( + onClick = onControl + ) { + Icon( + imageVector = Icons.Outlined.Settings, + contentDescription = null + ) + Text(stringResource(R.string.kpm_control)) + } + + FilledTonalButton( + onClick = onUninstall + ) { + Icon( + imageVector = Icons.Outlined.Delete, + contentDescription = null + ) + Text(stringResource(R.string.kpm_uninstall)) + } + } + } + } +} \ No newline at end of file diff --git a/manager/app/src/main/java/shirkneko/zako/sukisu/ui/util/KsuCli.kt b/manager/app/src/main/java/shirkneko/zako/sukisu/ui/util/KsuCli.kt index 00321f60..fe873201 100644 --- a/manager/app/src/main/java/shirkneko/zako/sukisu/ui/util/KsuCli.kt +++ b/manager/app/src/main/java/shirkneko/zako/sukisu/ui/util/KsuCli.kt @@ -480,3 +480,57 @@ fun susfsSUS_SU_Mode(): String { val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} sus_su mode") return result } + +private fun getKpmmgrPath(): String { + return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libkpmmgr.so" +} + + +fun loadKpmModule(path: String, args: String? = null): String { + val shell = getRootShell() + val cmd = "${getKpmmgrPath()} load $path ${args ?: ""}" + val result = ShellUtils.fastCmd(shell, cmd) + return result +} + +fun unloadKpmModule(name: String): String { + val shell = getRootShell() + val cmd = "${getKpmmgrPath()} unload $name" + val result = ShellUtils.fastCmd(shell, cmd) + return result +} + +fun getKpmModuleCount(): String { + val shell = getRootShell() + val cmd = "${getKpmmgrPath()} num" + val result = ShellUtils.fastCmd(shell, cmd) + return result +} + +fun listKpmModules(): String { + val shell = getRootShell() + val cmd = "${getKpmmgrPath()} list" + val result = ShellUtils.fastCmd(shell, cmd) + return result +} + +fun getKpmModuleInfo(name: String): String { + val shell = getRootShell() + val cmd = "${getKpmmgrPath()} info $name" + val result = ShellUtils.fastCmd(shell, cmd) + return result +} + +fun controlKpmModule(name: String, args: String? = null): String { + val shell = getRootShell() + val cmd = "${getKpmmgrPath()} control $name ${args ?: ""}" + val result = ShellUtils.fastCmd(shell, cmd) + return result +} + +fun printKpmModules(): String { + val shell = getRootShell() + val cmd = "${getKpmmgrPath()} print" + val result = ShellUtils.fastCmd(shell, cmd) + return result +} diff --git a/manager/app/src/main/java/shirkneko/zako/sukisu/ui/viewmodel/KpmViewModel.kt b/manager/app/src/main/java/shirkneko/zako/sukisu/ui/viewmodel/KpmViewModel.kt new file mode 100644 index 00000000..9f430cfd --- /dev/null +++ b/manager/app/src/main/java/shirkneko/zako/sukisu/ui/viewmodel/KpmViewModel.kt @@ -0,0 +1,98 @@ +package shirkneko.zako.sukisu.ui.viewmodel + +import android.util.Log +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import shirkneko.zako.sukisu.ui.util.* + +class KpmViewModel : ViewModel() { + var moduleList by mutableStateOf(emptyList()) + private set + + + var search by mutableStateOf("") + internal set + + var isRefreshing by mutableStateOf(false) + private set + + var currentModuleDetail by mutableStateOf("") + private set + + fun loadModuleDetail(moduleId: String) { + viewModelScope.launch { + currentModuleDetail = withContext(Dispatchers.IO) { + try { + getKpmModuleInfo(moduleId) + } catch (e: Exception) { + "无法获取模块详细信息: ${e.message}" + } + } + Log.d("KsuCli", "Module detail: $currentModuleDetail") + } + } + + fun fetchModuleList() { + viewModelScope.launch { + isRefreshing = true + try { + val moduleCount = getKpmModuleCount() + Log.d("KsuCli", "Module count: $moduleCount") + + val moduleInfo = listKpmModules() + Log.d("KsuCli", "Module info: $moduleInfo") + + val modules = parseModuleList(moduleInfo) + moduleList = modules + } finally { + isRefreshing = false + } + } + } + + private fun getInstalledKernelPatches(): List { + return try { + val output = printKpmModules() + parseModuleList(output) + } catch (e: Exception) { + emptyList() + } + } + + private fun parseModuleList(output: String): List { + return output.split("\n").mapNotNull { line -> + if (line.isBlank()) return@mapNotNull null + val parts = line.split("|") + if (parts.size < 7) return@mapNotNull null + + ModuleInfo( + id = parts[0].trim(), + name = parts[1].trim(), + version = parts[2].trim(), + author = parts[3].trim(), + description = parts[4].trim(), + args = parts[6].trim(), + enabled = true, + hasAction = controlKpmModule(parts[0].trim()).isNotBlank() + ) + } + } + + + data class ModuleInfo( + val id: String, + val name: String, + val version: String, + val author: String, + val description: String, + val args: String, + val enabled: Boolean, + val hasAction: Boolean + ) +} \ No newline at end of file diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml index 86b37418..0a1c37db 100644 --- a/manager/app/src/main/res/values/strings.xml +++ b/manager/app/src/main/res/values/strings.xml @@ -236,4 +236,6 @@ Confirm installation? Installation of kpm module successful Installation of kpm module failed + kpm 参数 + kpm 控制 From 2ca346340fd460c6e49691ef053260c9bfeb4e47 Mon Sep 17 00:00:00 2001 From: liankong Date: Sun, 30 Mar 2025 01:55:29 +0800 Subject: [PATCH 19/19] =?UTF-8?q?=E6=8C=89=E7=85=A7AI=E7=BB=99=E5=87=BA?= =?UTF-8?q?=E7=9A=84=E5=BB=BA=E8=AE=AE=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/kpm/kpm.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/kernel/kpm/kpm.c b/kernel/kpm/kpm.c index b4b8fb11..997a290d 100644 --- a/kernel/kpm/kpm.c +++ b/kernel/kpm/kpm.c @@ -406,6 +406,33 @@ typedef enum { RELOC_OP_PAGE } reloc_op_t; +// 移植自内核 arch/arm64/kernel/insn.c +int aarch64_insn_patch_imm(void *addr, 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 的 16-bit 立即数 + new_insn = aarch64_insn_encode_immediate(type, insn, imm); + break; + case AARCH64_INSN_IMM_26: // B/BL 的 26-bit 偏移 + new_insn = aarch64_insn_encode_offset(insn, imm, 26); + break; + case AARCH64_INSN_IMM_ADR: // ADR 的 21-bit 页偏移 + new_insn = aarch64_insn_encode_offset(insn, imm, 21); + break; + case AARCH64_INSN_IMM_19: // 条件跳转的 19-bit 偏移 + new_insn = aarch64_insn_encode_offset(insn, imm, 19); + break; + default: + return -EINVAL; + } + + *(u32 *)addr = cpu_to_le32(new_insn); + return 0; +} + /* 指令编码辅助函数 */ static int reloc_data(reloc_op_t op, void *loc, u64 val, int len) { @@ -447,7 +474,7 @@ static int reloc_data(reloc_op_t op, void *loc, u64 val, int len) } /* MOVW 指令重定位 */ -static int reloc_insn_movw(reloc_op_t op, void *loc, u64 val, int shift, aarch64_insn_imm_type imm_type) +static int reloc_insn_movw(reloc_op_t op, void *loc, u64 val, int shift, enum aarch64_insn_imm_type imm_type) { u64 imm = val; s64 sval; @@ -467,7 +494,7 @@ static int reloc_insn_movw(reloc_op_t op, void *loc, u64 val, int shift, aarch64 } /* 立即数指令重定位 */ -static int reloc_insn_imm(reloc_op_t op, void *loc, u64 val, int shift, int len, aarch64_insn_imm_type imm_type) +static int reloc_insn_imm(reloc_op_t op, void *loc, u64 val, int shift, int len, enum aarch64_insn_imm_type imm_type) { u64 imm = val; s64 sval;