Merge branch 'dev' of https://github.com/ShirkNeko/SukiSU-Ultra into dev
This commit is contained in:
@@ -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) {
|
||||
|
||||
362
kernel/kpm/kpm.c
362
kernel/kpm/kpm.c
@@ -34,6 +34,7 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/insn.h>
|
||||
#include "kpm.h"
|
||||
#include "compact.h"
|
||||
|
||||
@@ -361,19 +362,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);
|
||||
@@ -383,34 +386,238 @@ static int kpm_apply_relocate_arm64(Elf64_Shdr *sechdrs, const char *strtab, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kpm_apply_relocate_add_arm64(Elf64_Shdr *sechdrs, const char *strtab, int sym_idx, int rela_idx, struct kpm_module *mod)
|
||||
#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 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_entsize);
|
||||
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);
|
||||
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 = sym->st_value + rela[i].r_addend;
|
||||
void *loc = (void *)(mod->start + rela[i].r_offset);
|
||||
u64 val;
|
||||
Elf64_Sym *sym;
|
||||
|
||||
/* 处理特殊重定位类型 */
|
||||
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 {
|
||||
printk(KERN_ERR "ARM64 KPM Loader: R_AARCH64_ABS64 with zero symbol\n");
|
||||
return -EINVAL;
|
||||
val += (u64)mod->start; // 转换为模块内绝对地址
|
||||
}
|
||||
} else {
|
||||
val = rela[i].r_addend;
|
||||
}
|
||||
|
||||
overflow_check = true;
|
||||
|
||||
/* 处理所有重定位类型 */
|
||||
switch (type) {
|
||||
/* 数据重定位 */
|
||||
case R_AARCH64_ABS64:
|
||||
overflow_check = false;
|
||||
ovf = reloc_data(RELOC_OP_ABS, loc, val, 64);
|
||||
break;
|
||||
case R_AARCH64_ABS32:
|
||||
ovf = reloc_data(RELOC_OP_ABS, loc, val, 32);
|
||||
break;
|
||||
case R_AARCH64_ABS16:
|
||||
ovf = reloc_data(RELOC_OP_ABS, loc, val, 16);
|
||||
break;
|
||||
case R_AARCH64_PREL64:
|
||||
overflow_check = false;
|
||||
ovf = reloc_data(RELOC_OP_PREL, loc, val, 64);
|
||||
break;
|
||||
case R_AARCH64_PREL32:
|
||||
ovf = reloc_data(RELOC_OP_PREL, loc, val, 32);
|
||||
break;
|
||||
case R_AARCH64_PREL16:
|
||||
ovf = reloc_data(RELOC_OP_PREL, loc, val, 16);
|
||||
break;
|
||||
|
||||
/* MOVW 指令 */
|
||||
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:
|
||||
*((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;
|
||||
}
|
||||
|
||||
@@ -418,22 +625,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;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* 符号表与字符串表布局
|
||||
*----------------------------------------------------------*/
|
||||
@@ -481,45 +702,83 @@ 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;
|
||||
void *dest;
|
||||
const char *secname;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
/* 定位关键函数指针 */
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -944,5 +1203,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);
|
||||
Reference in New Issue
Block a user