Skip to content

Commit

Permalink
[re_kernel] 支持 6.1
Browse files Browse the repository at this point in the history
  • Loading branch information
lzghzr committed Jul 7, 2024
1 parent c511f1c commit ace72eb
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 71 deletions.
2 changes: 1 addition & 1 deletion re_kernel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
### pre
由于 4.x 和 5.x 版本差异过大, 去除 /proc/rekernel/ 的读写权限<br />
更加小心的清理过时消息<br />
修复一个函数调用错误
支持 6.1
### 6.0.7
为了兼容5.4内核, 不再增加 TF_UPDATE_TXN
### 6.0.6
Expand Down
128 changes: 91 additions & 37 deletions re_kernel/re_kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ KPM_NAME("re_kernel");
KPM_VERSION(MYKPM_VERSION);
KPM_LICENSE("GPL v3");
KPM_AUTHOR("Nep-Timeline, lzghzr");
KPM_DESCRIPTION("Re:Kernel, support 4.4, 4.9, 4.14, 4.19, 5.4, 5.10, 5.15");
KPM_DESCRIPTION("Re:Kernel, support 4.4, 4.9, 4.14, 4.19, 5.4, 5.10, 5.15, 6.1");

#define NETLINK_REKERNEL_MAX 26
#define NETLINK_REKERNEL_MIN 22
Expand Down Expand Up @@ -81,6 +81,7 @@ void kfunc_def(proc_remove)(struct proc_dir_entry* de);
static int (*binder_proc_transaction)(struct binder_transaction* t, struct binder_proc* proc, struct binder_thread* thread);
// free the outdated transaction and buffer
static void (*binder_transaction_buffer_release)(struct binder_proc* proc, struct binder_thread* thread, struct binder_buffer* buffer, binder_size_t off_end_offset, bool is_failure);
static void (*binder_transaction_buffer_release_v6)(struct binder_proc* proc, struct binder_thread* thread, struct binder_buffer* buffer, binder_size_t failed_at, bool is_failure);
static void (*binder_transaction_buffer_release_v4)(struct binder_proc* proc, struct binder_buffer* buffer, binder_size_t failed_at, bool is_failure);
static void (*binder_transaction_buffer_release_v3)(struct binder_proc* proc, struct binder_buffer* buffer, binder_size_t* failed_at);
static void (*binder_alloc_free_buf)(struct binder_alloc* alloc, struct binder_buffer* buffer);
Expand Down Expand Up @@ -111,11 +112,12 @@ int kfunc_def(get_cmdline)(struct task_struct* task, char* buffer, int buflen);

// 最好初始化一个大于 0xFFFFFFFF 的值, 否则编译器优化后, 全局变量可能出错
static uint64_t task_struct_jobctl_offset = UZERO, task_struct_pid_offset = UZERO, task_struct_group_leader_offset = UZERO,
binder_transaction_to_proc_offset = UZERO, binder_transaction_buffer_offset = UZERO, binder_transaction_code_offset = UZERO, binder_transaction_flags_offset = UZERO,
binder_proc_outstanding_txns_offset = UZERO, binder_proc_is_frozen_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,
// 实际上会被编译器优化为 bool
binder_transaction_buffer_release_ver5 = UZERO, binder_transaction_buffer_release_ver4 = UZERO;
binder_transaction_buffer_release_ver6 = UZERO, binder_transaction_buffer_release_ver5 = UZERO, binder_transaction_buffer_release_ver4 = UZERO;

static struct sock* rekernel_netlink;
static unsigned long rekernel_netlink_unit = UZERO, trace = UZERO;
Expand Down Expand Up @@ -150,6 +152,26 @@ 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);
}
// binder_transaction_to_proc
static inline struct binder_proc* binder_transaction_to_proc(struct binder_transaction* t) {
struct binder_proc* to_proc = *(struct binder_proc**)((uintptr_t)t + binder_transaction_to_proc_offset);
return to_proc;
}
// binder_transaction_buffer
static inline struct binder_buffer* binder_transaction_buffer(struct binder_transaction* t) {
struct binder_buffer* buffer = *(struct binder_buffer**)((uintptr_t)t + binder_transaction_buffer_offset);
return buffer;
}
// binder_transaction_code
static inline unsigned int binder_transaction_code(struct binder_transaction* t) {
unsigned int code = *(unsigned int*)((uintptr_t)t + binder_transaction_code_offset);
return code;
}
// binder_transaction_flags
static inline unsigned int binder_transaction_flags(struct binder_transaction* t) {
unsigned int flags = *(unsigned int*)((uintptr_t)t + binder_transaction_flags_offset);
return flags;
}

// binder_is_frozen
static inline bool binder_is_frozen(struct binder_proc* proc) {
Expand Down Expand Up @@ -306,36 +328,47 @@ static void binder_overflow_handler(pid_t src_pid, struct task_struct* src, pid_
}

static void rekernel_binder_transaction(void* data, bool reply, struct binder_transaction* t, struct binder_node* target_node) {
if (!t->to_proc)
struct binder_proc* to_proc = binder_transaction_to_proc(t);
if (!to_proc)
return;

if (reply) {
binder_reply_handler(task_pid(current), current, t->to_proc->pid, t->to_proc->tsk, false);
binder_reply_handler(task_pid(current), current, to_proc->pid, to_proc->tsk, false);
} else if (t->from) {
if (t->from->proc) {
binder_trans_handler(t->from->proc->pid, t->from->proc->tsk, t->to_proc->pid, t->to_proc->tsk, false);
binder_trans_handler(t->from->proc->pid, t->from->proc->tsk, to_proc->pid, to_proc->tsk, false);
}
} else { // oneway=1
// binder_trans_handler(task_pid(current), current, t->to_proc->pid, t->to_proc->tsk, true);
// binder_trans_handler(task_pid(current), current, to_proc->pid, to_proc->tsk, true);

struct binder_alloc* target_alloc = (struct binder_alloc*)((uintptr_t)t->to_proc + binder_proc_alloc_offset);
struct binder_alloc* target_alloc = (struct binder_alloc*)((uintptr_t)to_proc + binder_proc_alloc_offset);
size_t free_async_space = *(size_t*)((uintptr_t)target_alloc + binder_alloc_free_async_space_offset);
size_t buffer_size = *(size_t*)((uintptr_t)target_alloc + binder_alloc_buffer_size_offset);
if (free_async_space < (buffer_size / 10 + 0x300)) {
binder_overflow_handler(task_pid(current), current, t->to_proc->pid, t->to_proc->tsk, true);
binder_overflow_handler(task_pid(current), current, to_proc->pid, to_proc->tsk, true);
}
}
}

static bool binder_can_update_transaction(struct binder_transaction* t1, struct binder_transaction* t2) {
if ((t1->flags & t2->flags & TF_ONE_WAY) != TF_ONE_WAY || !t1->to_proc || !t2->to_proc)
struct binder_proc* t1_to_proc = binder_transaction_to_proc(t1);
struct binder_buffer* t1_buffer = binder_transaction_buffer(t1);
unsigned int t1_code = binder_transaction_code(t1);
unsigned int t1_flags = binder_transaction_flags(t1);

struct binder_proc* t2_to_proc = binder_transaction_to_proc(t2);
struct binder_buffer* t2_buffer = binder_transaction_buffer(t2);
unsigned int t2_code = binder_transaction_code(t2);
unsigned int t2_flags = binder_transaction_flags(t2);

if ((t1_flags & t2_flags & TF_ONE_WAY) != TF_ONE_WAY || !t1_to_proc || !t2_to_proc)
return false;
if (t1->to_proc->tsk == t2->to_proc->tsk
&& t1->code == t2->code
&& t1->flags == t2->flags
&& binder_proc_is_frozen_offset == UZERO ? true : t1->buffer->pid == t2->buffer->pid // 4.19 以下无此数据
&& t1->buffer->target_node->ptr == t2->buffer->target_node->ptr
&& t1->buffer->target_node->cookie == t2->buffer->target_node->cookie)
if (t1_to_proc->tsk == t2_to_proc->tsk
&& t1_code == t2_code
&& t1_flags == t2_flags
&& (binder_proc_is_frozen_offset == UZERO ? true : t1_buffer->pid == t2_buffer->pid) // 4.19 以下无此数据
&& t1_buffer->target_node->ptr == t2_buffer->target_node->ptr
&& t1_buffer->target_node->cookie == t2_buffer->target_node->cookie)
return true;
return false;
}
Expand All @@ -344,11 +377,9 @@ static struct binder_transaction* binder_find_outdated_transaction_ilocked(struc
struct binder_work* w;

list_for_each_entry(w, target_list, entry) {
struct binder_transaction* t_queued;

if (w->type != BINDER_WORK_TRANSACTION)
continue;
t_queued = container_of(w, struct binder_transaction, work);
struct binder_transaction* t_queued = container_of(w, struct binder_transaction, work);
if (binder_can_update_transaction(t_queued, t))
return t_queued;
}
Expand All @@ -363,7 +394,9 @@ static inline void outstanding_txns_dec(struct binder_proc* proc) {
}

static inline void binder_release_entire_buffer(struct binder_proc* proc, struct binder_thread* thread, struct binder_buffer* buffer, bool is_failure) {
if (binder_transaction_buffer_release_ver5 == IZERO) {
if (binder_transaction_buffer_release_ver6 == IZERO && binder_transaction_buffer_release_ver5 == IZERO) {
binder_transaction_buffer_release_v6(proc, thread, buffer, 0, is_failure);
} else if (binder_transaction_buffer_release_ver5 == IZERO) {
binder_size_t off_end_offset = ALIGN(buffer->data_size, sizeof(void*));
off_end_offset += buffer->offsets_size;

Expand All @@ -382,13 +415,16 @@ 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;
struct binder_node* node = t->buffer->target_node;

struct binder_buffer* buffer = binder_transaction_buffer(t);
struct binder_node* node = buffer->target_node;
args->local.data0 = NULL;
// 兼容不支持 trace 的内核
if (trace == UZERO) {
rekernel_binder_transaction(NULL, false, t, NULL);
}
if (!node || !(t->flags & TF_ONE_WAY))
unsigned int flags = binder_transaction_flags(t);
if (!node || !(flags & TF_ONE_WAY))
return;

// binder 冻结时不再清理过时消息
Expand Down Expand Up @@ -419,12 +455,12 @@ static void binder_proc_transaction_after(hook_fargs3_t* args, void* udata) {
if (t_outdated) {
struct binder_proc* proc = (struct binder_proc*)args->arg1;
struct binder_alloc* target_alloc = (struct binder_alloc*)((uintptr_t)proc + binder_proc_alloc_offset);
struct binder_buffer* buffer = t_outdated->buffer;
struct binder_buffer* buffer = binder_transaction_buffer(t_outdated);
#ifdef CONFIG_DEBUG
logkm("free_outdated pid=%d,uid=%d,data_size=%d\n", proc->pid, task_uid(proc->tsk).val, buffer->data_size);
#endif /* CONFIG_DEBUG */

t_outdated->buffer = NULL;
* (struct binder_buffer**)((uintptr_t)t_outdated + binder_transaction_buffer_offset) = NULL;
buffer->transaction = NULL;
binder_release_entire_buffer(proc, NULL, buffer, false);
binder_alloc_free_buf(target_alloc, buffer);
Expand Down Expand Up @@ -464,11 +500,17 @@ static void tcp_rcv_before(hook_fargs1_t* args, void* udata) {
static long calculate_offsets() {
// 获取 binder_transaction_buffer_release 版本, 以参数数量做判断
uint32_t* binder_transaction_buffer_release_src = (uint32_t*)binder_transaction_buffer_release;
for (u32 i = 0; i < 0x10; i++) {
for (u32 i = 0; i < 0x100; i++) {
#ifdef CONFIG_DEBUG
logkm("binder_transaction_buffer_release %x %llx\n", i, binder_transaction_buffer_release_src[i]);
#endif /* CONFIG_DEBUG */
if (binder_transaction_buffer_release_src[i] == ARM64_RET) {
if ((binder_transaction_buffer_release_src[i] & MASK_AND_64_imm_0XFFFFFFFFFFFFFFF8) == INST_AND_64_imm_0XFFFFFFFFFFFFFFF8) {
for (u32 j = 1; j < 0x3; j++) {
if ((binder_transaction_buffer_release_src[i + j] & MASK_CBZ) == INST_CBZ
|| (binder_transaction_buffer_release_src[i + j] & MASK_TBNZ) == INST_TBNZ) {
binder_transaction_buffer_release_ver6 = IZERO;
}
}
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_ver5 = IZERO;
Expand All @@ -481,6 +523,7 @@ static long calculate_offsets() {
}
}
#ifdef CONFIG_DEBUG
logkm("binder_transaction_buffer_release_ver6=0x%llx\n", binder_transaction_buffer_release_ver6);
logkm("binder_transaction_buffer_release_ver5=0x%llx\n", binder_transaction_buffer_release_ver5);
logkm("binder_transaction_buffer_release_ver4=0x%llx\n", binder_transaction_buffer_release_ver4);
#endif /* CONFIG_DEBUG */
Expand All @@ -492,6 +535,12 @@ static long calculate_offsets() {
#endif /* CONFIG_DEBUG */
if (binder_proc_transaction_src[i] == ARM64_RET) {
break;
} else if (binder_transaction_buffer_offset == UZERO && (binder_proc_transaction_src[i] & MASK_LDR_64_Rn_X0) == INST_LDR_64_Rn_X0) {
uint64_t imm12 = bits32(binder_proc_transaction_src[i], 21, 10);
binder_transaction_buffer_offset = sign64_extend((imm12 << 0b11u), 16u); // 0x50
binder_transaction_to_proc_offset = binder_transaction_buffer_offset - 0x20; // 0x30
binder_transaction_code_offset = binder_transaction_buffer_offset + 0x8; // 0x58
binder_transaction_flags_offset = binder_transaction_buffer_offset + 0xC; // 0x5C
} else if ((binder_proc_transaction_src[i] & MASK_MOVZ_imm16_0x7212) == INST_MOVZ_imm16_0x7212) {
for (u32 j = 0; j < 0x5; j++) {
if ((binder_proc_transaction_src[i - j] & MASK_LDRB) == INST_LDRB) {
Expand All @@ -505,6 +554,10 @@ static long calculate_offsets() {
}
}
#ifdef CONFIG_DEBUG
logkm("binder_transaction_to_proc_offset=0x%llx\n", binder_transaction_to_proc_offset);
logkm("binder_transaction_buffer_offset=0x%llx\n", binder_transaction_buffer_offset);
logkm("binder_transaction_code_offset=0x%llx\n", binder_transaction_code_offset);
logkm("binder_transaction_flags_offset=0x%llx\n", binder_transaction_flags_offset);
logkm("binder_proc_outstanding_txns_offset=0x%llx\n", binder_proc_outstanding_txns_offset);
logkm("binder_proc_is_frozen_offset=0x%llx\n", binder_proc_is_frozen_offset);
#endif /* CONFIG_DEBUG */
Expand All @@ -521,7 +574,7 @@ static long calculate_offsets() {
break;
} else if ((task_clear_jobctl_trapping_src[i] & MASK_LDR_64_Rn_X0) == INST_LDR_64_Rn_X0) {
uint64_t imm12 = bits32(task_clear_jobctl_trapping_src[i], 21, 10);
task_struct_jobctl_offset = sign64_extend((imm12 << 0b11u), 16u);
task_struct_jobctl_offset = sign64_extend((imm12 << 0b11u), 16u); // 0x580
break;
}
}
Expand All @@ -548,9 +601,9 @@ static long calculate_offsets() {
} else if (((binder_transaction_src[i] & MASK_LDR_64_Rn_X0) == INST_LDR_64_Rn_X0 && (binder_transaction_src[i] & MASK_LDR_64_Rn_X0_Rt_X0) != INST_LDR_64_Rn_X0_Rt_X0)
|| (mov_x22_x0 && (binder_transaction_src[i] & MASK_LDR_64_X22) == INST_LDR_64_X22)) {
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;
binder_proc_context_offset = sign64_extend((imm12 << 0b11u), 16u); // 0x240
binder_proc_inner_lock_offset = binder_proc_context_offset + 0x8; // 0x248
binder_proc_outer_lock_offset = binder_proc_context_offset + 0xC; // 0x24C
break;
}
}
Expand Down Expand Up @@ -580,9 +633,9 @@ static long calculate_offsets() {
uint32_t sh = bit(binder_free_proc_src[i], 22);
uint64_t imm12 = imm12 = bits32(binder_free_proc_src[i], 21, 10);
if (sh) {
binder_proc_alloc_offset = sign64_extend((imm12 << 12u), 16u);
binder_proc_alloc_offset = sign64_extend((imm12 << 12u), 16u); // 0x1A8
} else {
binder_proc_alloc_offset = sign64_extend((imm12), 16u);
binder_proc_alloc_offset = sign64_extend((imm12), 16u); // 0x1A8
}
break;
}
Expand All @@ -606,17 +659,17 @@ static long calculate_offsets() {
break;
} else if ((binder_alloc_init_src[i] & MASK_STR_32_x0) == INST_STR_32_x0) {
uint64_t imm12 = bits32(binder_alloc_init_src[i], 21, 10);
binder_alloc_pid_offset = sign64_extend((imm12 << 0b10u), 16u); // 0x74
binder_alloc_buffer_size_offset = binder_alloc_pid_offset - 0xC; // 0x68
binder_alloc_free_async_space_offset = binder_alloc_pid_offset - 0x1C; // 0x58
binder_alloc_vma_offset = binder_alloc_pid_offset - 0x54; // 0x20
binder_alloc_pid_offset = sign64_extend((imm12 << 0b10u), 16u); // 0x84
binder_alloc_buffer_size_offset = binder_alloc_pid_offset - 0xC; // 0x78
binder_alloc_free_async_space_offset = binder_alloc_pid_offset - 0x1C; // 0x68
binder_alloc_vma_offset = binder_alloc_pid_offset - 0x54; // 0x30
break;
} else if ((binder_alloc_init_src[i] & MASK_LDR_32_) == INST_LDR_32_) {
uint64_t imm12 = bits32(binder_alloc_init_src[i], 21, 10);
task_struct_pid_offset = sign64_extend((imm12 << 0b10u), 16u);
task_struct_pid_offset = sign64_extend((imm12 << 0b10u), 16u); // 0x5D8
} else if ((binder_alloc_init_src[i] & MASK_LDR_64_) == INST_LDR_64_) {
uint64_t imm12 = bits32(binder_alloc_init_src[i], 21, 10);
task_struct_group_leader_offset = sign64_extend((imm12 << 0b11u), 16u);
task_struct_group_leader_offset = sign64_extend((imm12 << 0b11u), 16u); // 0x618
}
}
#ifdef CONFIG_DEBUG
Expand Down Expand Up @@ -658,6 +711,7 @@ static long inline_hook_init(const char* args, const char* event, void* __user r
kvar_lookup_name(__tracepoint_binder_transaction);

lookup_name(binder_transaction_buffer_release);
binder_transaction_buffer_release_v6 = (typeof(binder_transaction_buffer_release_v6))binder_transaction_buffer_release;
binder_transaction_buffer_release_v4 = (typeof(binder_transaction_buffer_release_v4))binder_transaction_buffer_release;
binder_transaction_buffer_release_v3 = (typeof(binder_transaction_buffer_release_v3))binder_transaction_buffer_release;
lookup_name(binder_alloc_free_buf);
Expand Down
55 changes: 22 additions & 33 deletions re_kernel/re_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct binder_work {
enum binder_work_type {
BINDER_WORK_TRANSACTION = 1,
BINDER_WORK_TRANSACTION_COMPLETE,
BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT, // 6.1
BINDER_WORK_RETURN_ERROR,
BINDER_WORK_NODE,
BINDER_WORK_DEAD_BINDER,
Expand Down Expand Up @@ -111,9 +112,12 @@ struct binder_buffer {
struct list_head entry;
struct rb_node rb_node;
unsigned free : 1;
unsigned clear_on_free : 1; // 6.1
unsigned allow_user_free : 1;
unsigned async_transaction : 1;
unsigned debug_id : 29;
unsigned oneway_spam_suspect : 1; // 6.1
// unsigned debug_id : 29;
unsigned debug_id : 27; // 6.1
struct binder_transaction* transaction;
struct binder_node* target_node;
size_t data_size;
Expand All @@ -131,24 +135,22 @@ struct binder_transaction {
int debug_id;
struct binder_work work;
struct binder_thread* from;
struct binder_transaction* from_parent;
struct binder_proc* to_proc;
struct binder_thread* to_thread;
struct binder_transaction* to_parent;
unsigned need_reply : 1;
struct binder_buffer* buffer;
unsigned int code;
unsigned int flags;
struct binder_priority priority;
struct binder_priority saved_priority;
bool set_priority_called;
// unknow
// pid_t from_pid; // 6.1
// pid_t from_tid; // 6.1
// struct binder_transaction* from_parent;
// struct binder_proc* to_proc;
// struct binder_thread* to_thread;
// struct binder_transaction* to_parent;
// unsigned need_reply : 1;
// struct binder_buffer* buffer;
// unsigned int code;
// unsigned int flags;
// struct binder_priority priority;
// struct binder_priority saved_priority;
// bool set_priority_called;
};

struct binder_error {
struct binder_work work;
uint32_t cmd;
};
struct wait_queue_head {
spinlock_t lock;
struct list_head head;
Expand All @@ -165,28 +167,15 @@ enum binder_stat_types {
BINDER_STAT_COUNT
};
struct binder_stats {
atomic_t br[(((29201u) >> 0) & ((1 << 8) - 1)) + 1];
atomic_t bc[(((1078485778) >> 0) & ((1 << 8) - 1)) + 1];
atomic_t br[18];
// atomic_t br[20]; // 6.1
atomic_t bc[19];
atomic_t obj_created[BINDER_STAT_COUNT];
atomic_t obj_deleted[BINDER_STAT_COUNT];
};

struct binder_thread {
struct binder_proc* proc;
struct rb_node rb_node;
struct list_head waiting_thread_node;
int pid;
int looper;
bool looper_need_return;
struct binder_transaction* transaction_stack;
struct list_head todo;
bool process_todo;
struct binder_error return_error;
struct binder_error reply_error;
wait_queue_head_t wait;
struct binder_stats stats;
atomic_t tmp_ref;
bool is_dead;
struct task_struct* task;
// unknow
};

Expand Down
Loading

0 comments on commit ace72eb

Please sign in to comment.