diff --git a/re_kernel/Makefile b/re_kernel/Makefile index 25cecc9..17070b9 100644 --- a/re_kernel/Makefile +++ b/re_kernel/Makefile @@ -1,4 +1,4 @@ -RK_VERSION := 1.4.0.3 +RK_VERSION := 1.4.0.4 ifndef KP_DIR KP_DIR = ../KernelPatch diff --git a/re_kernel/README.md b/re_kernel/README.md index 1eebc2e..00573af 100644 --- a/re_kernel/README.md +++ b/re_kernel/README.md @@ -3,6 +3,8 @@ 配合墓碑模块,当应用收到 `binder` 同步信息时,临时解冻被冻结的应用 ## 更新记录 +### 1.4.0.4 +函数版本判断条件由内核版本判断改为分析函数参数 ### 1.4.0.3 解决应用长时间冻结后, 唤醒重载的问题 ### 1.4.0.2 @@ -14,10 +16,10 @@ ### 1.3.6.5 CGRP_FREEZE 支持改为可选项,因为 4.14 及以下内核不支持此功能 ### 1.3.6.4 -修复对 5.4 的支持 +修复对 5.4 的支持
模块依然支持 4.4,但加载时会判断是否支持 `freeze`,如果内核不支持此功能则无法加载 ### 1.3.6.3 -将线程休眠判断逻辑从 `hans` 改为 `millet` +将线程休眠判断逻辑从 `hans` 改为 `millet`
增加 `quiet` 版,大幅减少唤醒次数 ### 1.3.6.2 修复 `f_p` 重启失效 diff --git a/re_kernel/re_kernel.c b/re_kernel/re_kernel.c index 8c3e301..c2039df 100644 --- a/re_kernel/re_kernel.c +++ b/re_kernel/re_kernel.c @@ -89,6 +89,10 @@ void kfunc_def(kfree)(const void* objp); static struct binder_stats kvar_def(binder_stats); // hook do_send_sig_info static int (*do_send_sig_info)(int sig, struct siginfo* info, struct task_struct* p, enum pid_type type); + +// _raw_spin_lock && _raw_spin_unlock +void kfunc_def(_raw_spin_lock)(raw_spinlock_t* lock); +void kfunc_def(_raw_spin_unlock)(raw_spinlock_t* lock); // trace int kfunc_def(tracepoint_probe_register)(struct tracepoint* tp, void* probe, void* data); int kfunc_def(tracepoint_probe_unregister)(struct tracepoint* tp, void* probe, void* data); @@ -98,12 +102,14 @@ struct tracepoint kvar_def(__tracepoint_binder_transaction); int kfunc_def(get_cmdline)(struct task_struct* task, char* buffer, int buflen); #endif /* DEBUG */ +// 最好初始化一个大于 0xffffffff 的值, 否则编译器优化后, 全局变量可能出错 static uint64_t task_struct_flags_offset = UZERO, task_struct_jobctl_offset = UZERO, task_struct_pid_offset = UZERO, task_struct_group_leader_offset = UZERO, task_struct_frozen_offset = UZERO, task_struct_css_set_offset = UZERO, -binder_proc_alloc_offset = UZERO, +binder_proc_alloc_offset = UZERO, binder_proc_context_offset = UZERO, binder_proc_inner_lock_offset = UZERO, binder_proc_outer_lock_offset = UZERO, binder_alloc_pid_offset = UZERO, binder_alloc_buffer_size_offset = UZERO, binder_alloc_free_async_space_offset = UZERO, binder_alloc_vma_offset = UZERO, css_set_dfl_cgrp_offset = UZERO, cgroup_flags_offset = UZERO, -task_struct_frozen_bit = UZERO; +task_struct_frozen_bit = UZERO, +binder_transaction_buffer_release_ver = UZERO; static struct sock* rekernel_netlink; static unsigned long rekernel_netlink_unit = UZERO, trace = UZERO; @@ -119,6 +125,24 @@ static inline pid_t task_tgid(struct task_struct* task) { pid_t tgid = *(pid_t*)((uintptr_t)task + task_struct_pid_offset + 0x4); return tgid; } +// binder_node_lock +static inline void binder_node_lock(struct binder_node* node) { + spin_lock(&node->lock); +} +// binder_node_unlock +static inline void binder_node_unlock(struct binder_node* node) { + spin_unlock(&node->lock); +} +// binder_inner_proc_lock +static inline void binder_inner_proc_lock(struct binder_proc* proc) { + spinlock_t* inner_lock = (spinlock_t*)((uintptr_t)proc + binder_proc_inner_lock_offset); + spin_lock(inner_lock); +} +// binder_inner_proc_unlock +static inline void binder_inner_proc_unlock(struct binder_proc* proc) { + spinlock_t* inner_lock = (spinlock_t*)((uintptr_t)proc + binder_proc_inner_lock_offset); + spin_unlock(inner_lock); +} // 判断线程是否进入 frozen 状态 static inline bool cgroup_task_frozen(struct task_struct* task) { if (task_struct_frozen_offset == UZERO) { @@ -326,7 +350,6 @@ static bool binder_can_update_transaction(struct binder_transaction* t1, struct return false; } -// TODO: binder_inner_proc_lock(proc); static struct binder_transaction* binder_find_outdated_transaction_ilocked(struct binder_transaction* t, struct list_head* target_list) { struct binder_work* w; @@ -343,7 +366,7 @@ static struct binder_transaction* binder_find_outdated_transaction_ilocked(struc } static inline void binder_release_entire_buffer(struct binder_proc* proc, struct binder_thread* thread, struct binder_buffer* buffer, bool is_failure) { - if (kver > VERSION(5, 0, 0)) { + if (binder_transaction_buffer_release_ver == IZERO) { binder_size_t off_end_offset = ALIGN(buffer->data_size, sizeof(void*)); off_end_offset += buffer->offsets_size; @@ -360,6 +383,7 @@ static inline void binder_stats_deleted(enum binder_stat_types type) { static void binder_proc_transaction_before(hook_fargs3_t* args, void* udata) { struct binder_transaction* t = (struct binder_transaction*)args->arg0; + struct binder_proc* proc = (struct binder_proc*)args->arg1; // 兼容不支持 trace 的内核 if (trace == UZERO) { rekernel_binder_transaction(NULL, false, t, NULL); @@ -370,10 +394,23 @@ static void binder_proc_transaction_before(hook_fargs3_t* args, void* udata) { && t->to_proc->tsk && frozen_task_group(t->to_proc->tsk)) { struct binder_node* node = t->buffer->target_node; + if (!node) + return; + struct binder_alloc* target_alloc = (struct binder_alloc*)((uintptr_t)t->to_proc + binder_proc_alloc_offset); + binder_node_lock(node); + binder_inner_proc_lock(proc); + struct binder_transaction* t_outdated = binder_find_outdated_transaction_ilocked(t, &node->async_todo); if (t_outdated) { + list_del_init(&t_outdated->work.entry); + } + + binder_inner_proc_unlock(proc); + binder_node_unlock(node); + + if (t_outdated) { #ifdef DEBUG printk("re_kernel: free_outdated pid=%d,uid=%d,data_size=%d\n", t->to_proc->pid, task_uid(t->to_proc->tsk).val, t_outdated->buffer->data_size); #endif /* DEBUG */ @@ -469,6 +506,41 @@ static long calculate_offsets() { task_struct_jobctl_offset = sign64_extend((imm12), 16u) - 0x2; } } + // 获取 binder_transaction_buffer_release 版本, 以参数数量做判断 + uint32_t* binder_transaction_buffer_release_src = (uint32_t*)binder_transaction_buffer_release; + for (u32 i = 0; i < 0x20; i++) { +#ifdef DEBUG + printk("re_kernel: binder_transaction_buffer_release %x %llx\n", i, binder_transaction_buffer_release_src[i]); +#endif /* DEBUG */ + if (binder_transaction_buffer_release_src[i] == ARM64_RET) { + break; + } else if ((binder_transaction_buffer_release_src[i] & MASK_STR_Rn_SP_Rt_4) == INST_STR_Rn_SP_Rt_4) { + binder_transaction_buffer_release_ver = IZERO; + break; + } else if ((binder_transaction_buffer_release_src[i] & MASK_MOV_Rm_4_WZR) == INST_MOV_Rm_4_WZR) { + binder_transaction_buffer_release_ver = IZERO; + break; + } + } + // 获取 binder_proc->context, binder_proc->inner_lock, binder_proc->outer_lock + void (*binder_transaction)(struct binder_proc* proc, struct binder_thread* thread, struct binder_transaction_data* tr, int reply, binder_size_t extra_buffers_size); + lookup_name(binder_transaction); + + uint32_t* binder_transaction_src = (uint32_t*)binder_transaction; + for (u32 i = 0; i < 0x20; i++) { + if (binder_transaction_src[i] == ARM64_RET) { + break; + } else if ((binder_transaction_src[i] & MASK_LDR_64_X0) == INST_LDR_64_X0) { + uint64_t imm12 = bits32(binder_transaction_src[i], 21, 10); + binder_proc_context_offset = sign64_extend((imm12 << 0b11u), 16u); + binder_proc_inner_lock_offset = binder_proc_context_offset + 0x8; + binder_proc_outer_lock_offset = binder_proc_context_offset + 0xC; + break; + } + } + if (binder_proc_context_offset == UZERO || binder_proc_inner_lock_offset == UZERO || binder_proc_outer_lock_offset == UZERO) { + return -11; + } // 获取 binder_proc->alloc void (*binder_free_proc)(struct binder_proc* proc); binder_free_proc = (typeof(binder_free_proc))kallsyms_lookup_name("binder_free_proc"); @@ -572,6 +644,8 @@ static long inline_hook_init(const char* args, const char* event, void* __user r kfunc_lookup_name(tracepoint_probe_register); kfunc_lookup_name(tracepoint_probe_unregister); + kfunc_lookup_name(_raw_spin_lock); + kfunc_lookup_name(_raw_spin_unlock); kvar_lookup_name(__tracepoint_binder_transaction); lookup_name(binder_transaction_buffer_release); diff --git a/re_kernel/re_kernel.h b/re_kernel/re_kernel.h index 571702d..672bb57 100644 --- a/re_kernel/re_kernel.h +++ b/re_kernel/re_kernel.h @@ -9,6 +9,7 @@ // android/binder.c struct binder_alloc; +struct binder_transaction_data; enum transaction_flags { TF_ONE_WAY = 0x01, diff --git a/re_kernel/re_utils.h b/re_kernel/re_utils.h index 9526713..29aafb4 100644 --- a/re_kernel/re_utils.h +++ b/re_kernel/re_utils.h @@ -35,6 +35,8 @@ typedef uint32_t inst_mask_t; #define INST_LDRH 0x79400000u #define INST_LDRSH 0x79800000u #define INST_LDRSH_64_ 0x79800000u +#define INST_MOV_Rm_4_WZR 0x2A0403E0u +#define INST_STR_Rn_SP_Rt_4 0xB90003E4u #define INST_STR_32_x0 0xB9000000u #define INST_CBZ 0x34000000 #define INST_CBNZ 0x35000000 @@ -57,6 +59,8 @@ typedef uint32_t inst_mask_t; #define MASK_LDRH 0xFFC00000u #define MASK_LDRSH 0xFF800000u #define MASK_LDRSH_64_ 0xFFC00000u +#define MASK_MOV_Rm_4_WZR 0x7FFFFFE0u +#define MASK_STR_Rn_SP_Rt_4 0xBFC003E4u #define MASK_STR_32_x0 0xFFC003E0u #define MASK_CBZ 0x7F000000u #define MASK_CBNZ 0x7F000000u