kernel: Migrating KPM to ioctl

This commit is contained in:
ShirkNeko
2025-11-04 00:54:38 +08:00
parent 1e122b2469
commit 2075d2867e
9 changed files with 321 additions and 297 deletions

View File

@@ -13,7 +13,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
#include <asm/elf.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/string.h>
@@ -29,44 +29,44 @@
#include "../allowlist.h"
#include "../manager.h"
unsigned long sukisu_compact_find_symbol(const char* name);
// ======================================================================
// 兼容函数 for KPM
static
int sukisu_is_su_allow_uid(uid_t uid) {
static int sukisu_is_su_allow_uid(uid_t uid)
{
return ksu_is_allow_uid(uid) ? 1 : 0;
}
static
int sukisu_get_ap_mod_exclude(uid_t uid) {
// Not supported
return 0;
static int sukisu_get_ap_mod_exclude(uid_t uid)
{
return 0; /* Not supported */
}
static
int sukisu_is_uid_should_umount(uid_t uid) {
static int sukisu_is_uid_should_umount(uid_t uid)
{
return ksu_uid_should_umount(uid) ? 1 : 0;
}
static
int sukisu_is_current_uid_manager() {
static int sukisu_is_current_uid_manager(void)
{
return is_manager();
}
static
uid_t sukisu_get_manager_uid() {
static uid_t sukisu_get_manager_uid(void)
{
return ksu_manager_uid;
}
// ======================================================================
static void sukisu_set_manager_uid(uid_t uid, int force)
{
if (force || ksu_manager_uid == -1)
ksu_manager_uid = uid;
}
struct CompactAddressSymbol {
const char *symbol_name;
void *addr;
};
unsigned long sukisu_compact_find_symbol(const char *name);
static struct CompactAddressSymbol address_symbol[] = {
{ "kallsyms_lookup_name", &kallsyms_lookup_name },
{ "compact_find_symbol", &sukisu_compact_find_symbol },
@@ -75,28 +75,26 @@ static struct CompactAddressSymbol address_symbol [] = {
{ "get_ap_mod_exclude", &sukisu_get_ap_mod_exclude },
{ "is_uid_should_umount", &sukisu_is_uid_should_umount },
{ "is_current_uid_manager", &sukisu_is_current_uid_manager },
{ "get_manager_uid", &sukisu_get_manager_uid }
{ "get_manager_uid", &sukisu_get_manager_uid },
{ "sukisu_set_manager_uid", &sukisu_set_manager_uid }
};
unsigned long sukisu_compact_find_symbol(const char* name) {
unsigned long sukisu_compact_find_symbol(const char* name)
{
int i;
unsigned long addr;
// 先自己在地址表部分查出来
for (i = 0; i < (sizeof(address_symbol) / sizeof(struct CompactAddressSymbol)); i++) {
struct CompactAddressSymbol *symbol = &address_symbol[i];
if(strcmp(name, symbol->symbol_name) == 0) {
if (strcmp(name, symbol->symbol_name) == 0)
return (unsigned long)symbol->addr;
}
}
// 通过内核来查
addr = kallsyms_lookup_name(name);
if(addr) {
if (addr)
return addr;
}
return 0;
}
EXPORT_SYMBOL(sukisu_compact_find_symbol);

View File

@@ -1,6 +1,6 @@
#ifndef ___SUKISU_KPM_COMPACT_H
#define ___SUKISU_KPM_COMPACT_H
#ifndef __SUKISU_KPM_COMPACT_H
#define __SUKISU_KPM_COMPACT_H
unsigned long sukisu_compact_find_symbol(const char* name);
extern unsigned long sukisu_compact_find_symbol(const char *name);
#endif

View File

@@ -8,6 +8,7 @@
* 集成了 ELF 解析、内存布局、符号处理、重定位(支持 ARM64 重定位类型)
* 并参照KernelPatch的标准KPM格式实现加载和控制
*/
#include <linux/export.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -23,7 +24,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
#include <asm/elf.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/string.h>
@@ -39,7 +40,7 @@
#include <linux/stacktrace.h>
#include <linux/kallsyms.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES)
#include <linux/moduleloader.h> // 需要启用 CONFIG_MODULES
#include <linux/moduleloader.h>
#endif
#include "kpm.h"
#include "compact.h"
@@ -54,131 +55,170 @@
#endif
#endif
// ============================================================================================
noinline
NO_OPTIMIZE
void sukisu_kpm_load_module_path(const char* path, const char* args, void* ptr, void __user* result) {
// This is a KPM module stub.
noinline NO_OPTIMIZE void sukisu_kpm_load_module_path(const char *path,
const char *args, void *ptr, void __user *result)
{
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_load_module_path). path=%s args=%s ptr=%p\n", path, args, ptr);
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
}
noinline
NO_OPTIMIZE
void sukisu_kpm_unload_module(const char* name, void* ptr, void __user* result) {
// This is a KPM module stub.
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_unload_module). name=%s ptr=%p\n", name, ptr);
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
}
printk("KPM: Stub function called (sukisu_kpm_load_module_path). "
"path=%s args=%s ptr=%p\n", path, args, ptr);
noinline
NO_OPTIMIZE
void sukisu_kpm_num(void __user* result) {
// This is a KPM module stub.
int res = 0;
printk("KPM: Stub function called (sukisu_kpm_num).\n");
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
}
__asm__ volatile("nop");
noinline
NO_OPTIMIZE
void sukisu_kpm_info(const char* name, void __user* out, void __user* result) {
// This is a KPM module stub.
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_info). name=%s buffer=%p\n", name, out);
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
if (copy_to_user(result, &res, sizeof(res)) < 1)
printk("KPM: Copy to user failed.");
}
noinline
NO_OPTIMIZE
void sukisu_kpm_list(void __user* out, unsigned int bufferSize, void __user* result) {
// This is a KPM module stub.
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_list). buffer=%p size=%d\n", out, bufferSize);
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
}
noinline
NO_OPTIMIZE
void sukisu_kpm_control(void __user* name, void __user* args, void __user* result) {
// This is a KPM module stub.
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_control). name=%p args=%p\n", name, args);
__asm__ volatile("nop"); // 精确控制循环不被优化
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
}
noinline
NO_OPTIMIZE
void sukisu_kpm_version(void __user* out, unsigned int bufferSize, void __user* result) {
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_version). buffer=%p size=%d\n", out, bufferSize);
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user failed.");
}
EXPORT_SYMBOL(sukisu_kpm_load_module_path);
noinline NO_OPTIMIZE void sukisu_kpm_unload_module(const char *name,
void *ptr, void __user *result)
{
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_unload_module). "
"name=%s ptr=%p\n", name, ptr);
__asm__ volatile("nop");
if (copy_to_user(result, &res, sizeof(res)) < 1)
printk("KPM: Copy to user failed.");
}
EXPORT_SYMBOL(sukisu_kpm_unload_module);
noinline NO_OPTIMIZE void sukisu_kpm_num(void __user *result)
{
int res = 0;
printk("KPM: Stub function called (sukisu_kpm_num).\n");
__asm__ volatile("nop");
if (copy_to_user(result, &res, sizeof(res)) < 1)
printk("KPM: Copy to user failed.");
}
EXPORT_SYMBOL(sukisu_kpm_num);
noinline NO_OPTIMIZE void sukisu_kpm_info(const char *name, void __user *out,
void __user *result)
{
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_info). "
"name=%s buffer=%p\n", name, out);
__asm__ volatile("nop");
if (copy_to_user(result, &res, sizeof(res)) < 1)
printk("KPM: Copy to user failed.");
}
EXPORT_SYMBOL(sukisu_kpm_info);
noinline NO_OPTIMIZE void sukisu_kpm_list(void __user *out, unsigned int bufferSize,
void __user *result)
{
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_list). "
"buffer=%p size=%d\n", out, bufferSize);
if (copy_to_user(result, &res, sizeof(res)) < 1)
printk("KPM: Copy to user failed.");
}
EXPORT_SYMBOL(sukisu_kpm_list);
EXPORT_SYMBOL(sukisu_kpm_version);
noinline NO_OPTIMIZE void sukisu_kpm_control(void __user *name, void __user *args,
void __user *result)
{
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_control). "
"name=%p args=%p\n", name, args);
__asm__ volatile("nop");
if (copy_to_user(result, &res, sizeof(res)) < 1)
printk("KPM: Copy to user failed.");
}
EXPORT_SYMBOL(sukisu_kpm_control);
noinline
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
noinline NO_OPTIMIZE void sukisu_kpm_version(void __user *out, unsigned int bufferSize,
void __user *result)
{
int res = -1;
printk("KPM: Stub function called (sukisu_kpm_version). "
"buffer=%p size=%d\n", out, bufferSize);
if (copy_to_user(result, &res, sizeof(res)) < 1)
printk("KPM: Copy to user failed.");
}
EXPORT_SYMBOL(sukisu_kpm_version);
noinline int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4,
unsigned long arg5)
{
if (arg2 == SUKISU_KPM_LOAD) {
char kernel_load_path[256] = { 0 };
char kernel_args_buffer[256] = { 0 };
if(arg3 == 0) {
if (arg3 == 0)
return -1;
}
strncpy_from_user((char *)&kernel_load_path, (const char __user *)arg3, 255);
if(arg4 != 0) {
if (arg4 != 0)
strncpy_from_user((char *)&kernel_args_buffer, (const char __user *)arg4, 255);
}
sukisu_kpm_load_module_path((const char*)&kernel_load_path, (const char*) &kernel_args_buffer, NULL, (void __user*) arg5);
sukisu_kpm_load_module_path((const char *)&kernel_load_path,
(const char *)&kernel_args_buffer, NULL, (void __user *)arg5);
} else if (arg2 == SUKISU_KPM_UNLOAD) {
char kernel_name_buffer[256] = { 0 };
if(arg3 == 0) {
if (arg3 == 0)
return -1;
}
strncpy_from_user((char *)&kernel_name_buffer, (const char __user *)arg3, 255);
sukisu_kpm_unload_module((const char*) &kernel_name_buffer, NULL, (void __user*) arg5);
sukisu_kpm_unload_module((const char *)&kernel_name_buffer, NULL,
(void __user *)arg5);
} else if (arg2 == SUKISU_KPM_NUM) {
sukisu_kpm_num((void __user *)arg5);
} else if (arg2 == SUKISU_KPM_INFO) {
char kernel_name_buffer[256] = { 0 };
if(arg3 == 0 || arg4 == 0) {
if (arg3 == 0 || arg4 == 0)
return -1;
}
strncpy_from_user((char *)&kernel_name_buffer, (const char __user *)arg3, 255);
sukisu_kpm_info((const char*) &kernel_name_buffer, (char __user*) arg4, (void __user*) arg5);
sukisu_kpm_info((const char *)&kernel_name_buffer, (char __user *)arg4,
(void __user *)arg5);
} else if (arg2 == SUKISU_KPM_LIST) {
sukisu_kpm_list((char __user *)arg3, (unsigned int)arg4, (void __user *)arg5);
} else if(arg2 == SUKISU_KPM_VERSION) {
sukisu_kpm_version((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5);
} else if (arg2 == SUKISU_KPM_CONTROL) {
sukisu_kpm_control((char __user *)arg3, (char __user *)arg4, (void __user *)arg5);
} else if (arg2 == SUKISU_KPM_VERSION) {
sukisu_kpm_version((char __user *)arg3, (unsigned int)arg4, (void __user *)arg5);
}
return 0;
}
EXPORT_SYMBOL(sukisu_handle_kpm);
int sukisu_is_kpm_control_code(unsigned long arg2) {
return (arg2 >= CMD_KPM_CONTROL && arg2 <= CMD_KPM_CONTROL_MAX) ? 1 : 0;
return (arg2 >= CMD_KPM_CONTROL &&
arg2 <= CMD_KPM_CONTROL_MAX) ? 1 : 0;
}
int do_kpm(void __user *arg)
{
struct ksu_kpm_cmd cmd;
if (copy_from_user(&cmd, arg, sizeof(cmd))) {
pr_err("kpm: copy_from_user failed\n");
return -EFAULT;
}
return sukisu_handle_kpm(cmd.arg2, cmd.arg3, cmd.arg4, cmd.arg5);
}
EXPORT_SYMBOL(sukisu_handle_kpm);

View File

@@ -1,44 +1,70 @@
#ifndef ___SUKISU_KPM_H
#define ___SUKISU_KPM_H
#ifndef __SUKISU_KPM_H
#define __SUKISU_KPM_H
#include <linux/types.h>
#include <linux/ioctl.h>
struct ksu_kpm_cmd {
__aligned_u64 arg2;
__aligned_u64 arg3;
__aligned_u64 arg4;
__aligned_u64 arg5;
};
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
int sukisu_is_kpm_control_code(unsigned long arg2);
int do_kpm(void __user *arg);
// KPM控制代码
#define CMD_KPM_CONTROL 28
#define CMD_KPM_CONTROL_MAX 35
#define KSU_IOCTL_KPM _IOC(_IOC_READ|_IOC_WRITE, 'K', 200, 0)
// 控制代码
/* KPM Control Code */
#define CMD_KPM_CONTROL 1
#define CMD_KPM_CONTROL_MAX 10
// prctl(xxx, 28, "PATH", "ARGS")
// success return 0, error return -N
#define SUKISU_KPM_LOAD 28
/* Control Code */
/*
* prctl(xxx, 1, "PATH", "ARGS")
* success return 0, error return -N
*/
#define SUKISU_KPM_LOAD 1
// prctl(xxx, 29, "NAME")
// success return 0, error return -N
#define SUKISU_KPM_UNLOAD 29
/*
* prctl(xxx, 2, "NAME")
* success return 0, error return -N
*/
#define SUKISU_KPM_UNLOAD 2
// num = prctl(xxx, 30)
// error return -N
// success return +num or 0
#define SUKISU_KPM_NUM 30
/*
* num = prctl(xxx, 3)
* error return -N
* success return +num or 0
*/
#define SUKISU_KPM_NUM 3
// prctl(xxx, 31, Buffer, BufferSize)
// success return +out, error return -N
#define SUKISU_KPM_LIST 31
/*
* prctl(xxx, 4, Buffer, BufferSize)
* success return +out, error return -N
*/
#define SUKISU_KPM_LIST 4
// prctl(xxx, 32, "NAME", Buffer[256])
// success return +out, error return -N
#define SUKISU_KPM_INFO 32
/*
* prctl(xxx, 5, "NAME", Buffer[256])
* success return +out, error return -N
*/
#define SUKISU_KPM_INFO 5
// prctl(xxx, 33, "NAME", "ARGS")
// success return KPM's result value
// error return -N
#define SUKISU_KPM_CONTROL 33
/*
* prctl(xxx, 6, "NAME", "ARGS")
* success return KPM's result value
* error return -N
*/
#define SUKISU_KPM_CONTROL 6
// prctl(xxx, 34, buffer, bufferSize)
// success return KPM's result value
// error return -N
#define SUKISU_KPM_VERSION 34
/*
* prctl(xxx, 7, buffer, bufferSize)
* success return KPM's result value
* error return -N
*/
#define SUKISU_KPM_VERSION 7
#endif

View File

@@ -13,7 +13,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
#include <asm/elf.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/string.h>
@@ -24,19 +24,23 @@
#include <linux/version.h>
#include <linux/export.h>
#include <linux/slab.h>
#include "kpm.h"
#include "compact.h"
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/mount.h>
#include <linux/kprobes.h>
#include <linux/mm_types.h>
#include <linux/netlink.h>
#include <linux/sched.h>
#include <../fs/mount.h>
#include "kpm.h"
#include "compact.h"
// 结构体成员元数据
struct DynamicStructMember {
const char *name;
size_t size;
size_t offset;
};
// 结构体元数据(包含总大小)
struct DynamicStructInfo {
const char *name;
size_t count;
@@ -44,7 +48,6 @@ struct DynamicStructInfo {
struct DynamicStructMember *members;
};
// 定义结构体元数据的宏(直接使用 struct 名称)
#define DYNAMIC_STRUCT_BEGIN(struct_name) \
static struct DynamicStructMember struct_name##_members[] = {
@@ -64,19 +67,6 @@ struct DynamicStructInfo {
.members = struct_name##_members \
};
// ==================================================================================
#include <linux/version.h>
#define KERNEL_VERSION_6_1 KERNEL_VERSION(6, 1, 0)
#define KERNEL_VERSION_5_15 KERNEL_VERSION(5, 15, 0)
#define KERNEL_VERSION_6_12 KERNEL_VERSION(6, 12, 0)
#define KERNEL_VERSION_4_10 KERNEL_VERSION(4, 10, 0)
#include <../fs/mount.h>
#include <linux/mount.h>
// 定义元数据
DYNAMIC_STRUCT_BEGIN(mount)
DEFINE_MEMBER(mount, mnt_parent)
DEFINE_MEMBER(mount, mnt)
@@ -98,13 +88,11 @@ DYNAMIC_STRUCT_BEGIN(mnt_namespace)
DEFINE_MEMBER(mnt_namespace, root)
DEFINE_MEMBER(mnt_namespace, seq)
DEFINE_MEMBER(mnt_namespace, mounts)
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
DEFINE_MEMBER(mnt_namespace, count)
#endif
DYNAMIC_STRUCT_END(mnt_namespace)
#include <linux/kprobes.h>
#ifdef CONFIG_KPROBES
DYNAMIC_STRUCT_BEGIN(kprobe)
DEFINE_MEMBER(kprobe, addr)
@@ -112,16 +100,13 @@ DYNAMIC_STRUCT_BEGIN(kprobe)
DEFINE_MEMBER(kprobe, offset)
DEFINE_MEMBER(kprobe, pre_handler)
DEFINE_MEMBER(kprobe, post_handler)
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
DEFINE_MEMBER(kprobe, fault_handler)
#endif
DEFINE_MEMBER(kprobe, flags)
DYNAMIC_STRUCT_END(kprobe)
#endif
#include <linux/mm.h>
#include <linux/mm_types.h>
DYNAMIC_STRUCT_BEGIN(vm_area_struct)
DEFINE_MEMBER(vm_area_struct,vm_start)
DEFINE_MEMBER(vm_area_struct,vm_end)
@@ -143,24 +128,18 @@ DYNAMIC_STRUCT_BEGIN(vm_operations_struct)
DEFINE_MEMBER(vm_operations_struct, access)
DYNAMIC_STRUCT_END(vm_operations_struct)
#include <linux/netlink.h>
DYNAMIC_STRUCT_BEGIN(netlink_kernel_cfg)
DEFINE_MEMBER(netlink_kernel_cfg, groups)
DEFINE_MEMBER(netlink_kernel_cfg, flags)
DEFINE_MEMBER(netlink_kernel_cfg, input)
#if LINUX_VERSION_CODE < KERNEL_VERSION_6_12
DEFINE_MEMBER(netlink_kernel_cfg, cb_mutex)
#endif
DEFINE_MEMBER(netlink_kernel_cfg, bind)
DEFINE_MEMBER(netlink_kernel_cfg, unbind)
#if LINUX_VERSION_CODE < KERNEL_VERSION_6_1
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)
DEFINE_MEMBER(netlink_kernel_cfg, compare)
#endif
DYNAMIC_STRUCT_END(netlink_kernel_cfg)
#include <linux/sched.h>
DYNAMIC_STRUCT_BEGIN(task_struct)
DEFINE_MEMBER(task_struct, pid)
DEFINE_MEMBER(task_struct, tgid)
@@ -184,20 +163,15 @@ DYNAMIC_STRUCT_BEGIN(task_struct)
#ifdef CONFIG_CGROUPS
DEFINE_MEMBER(task_struct, cgroups)
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION_4_10
#ifdef CONFIG_SECURITY
DEFINE_MEMBER(task_struct, security)
#endif
#endif
DEFINE_MEMBER(task_struct, thread)
DYNAMIC_STRUCT_END(task_struct)
// =====================================================================================================================
#define STRUCT_INFO(name) &(name##_info)
static
struct DynamicStructInfo* dynamic_struct_infos[] = {
static struct DynamicStructInfo *dynamic_struct_infos[] = {
STRUCT_INFO(mount),
STRUCT_INFO(vfsmount),
STRUCT_INFO(mnt_namespace),
@@ -210,92 +184,95 @@ struct DynamicStructInfo* dynamic_struct_infos[] = {
STRUCT_INFO(task_struct)
};
// return 0 if successful
// return -1 if struct not defined
int sukisu_super_find_struct(
const char* struct_name,
size_t* out_size,
int* out_members
) {
size_t i;
for(i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
/*
* return 0 if successful
* return -1 if struct not defined
*/
int sukisu_super_find_struct(const char *struct_name, size_t *out_size, int *out_members)
{
for (size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
struct DynamicStructInfo *info = dynamic_struct_infos[i];
if (strcmp(struct_name, info->name) == 0) {
if (out_size)
*out_size = info->total_size;
if (out_members)
*out_members = info->count;
return 0;
}
}
return -1;
}
EXPORT_SYMBOL(sukisu_super_find_struct);
// Dynamic access struct
// return 0 if successful
// return -1 if struct not defined
// return -2 if member not defined
int sukisu_super_access (
const char* struct_name,
const char* member_name,
size_t* out_offset,
size_t* out_size
) {
size_t i;
for(i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
/*
* Dynamic access struct
* return 0 if successful
* return -1 if struct not defined
* return -2 if member not defined
*/
int sukisu_super_access(const char *struct_name, const char *member_name, size_t *out_offset,
size_t *out_size)
{
for (size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
struct DynamicStructInfo *info = dynamic_struct_infos[i];
if (strcmp(struct_name, info->name) == 0) {
size_t i1;
for (i1 = 0; i1 < info->count; i1++) {
for (size_t i1 = 0; i1 < info->count; i1++) {
if (strcmp(info->members[i1].name, member_name) == 0) {
if (out_offset)
*out_offset = info->members[i].offset;
if (out_size)
*out_size = info->members[i].size;
return 0;
}
}
return -2;
}
}
return -1;
}
EXPORT_SYMBOL(sukisu_super_access);
// 动态 container_of 宏
#define DYNAMIC_CONTAINER_OF(offset, member_ptr) ({ \
(offset != (size_t)-1) ? (void*)((char*)(member_ptr) - offset) : NULL; \
})
// Dynamic container_of
// return 0 if success
// return -1 if current struct not defined
// return -2 if target member not defined
int sukisu_super_container_of(
const char* struct_name,
const char* member_name,
void* ptr,
void** out_ptr
) {
if(ptr == NULL) {
/*
* Dynamic container_of
* return 0 if success
* return -1 if current struct not defined
* return -2 if target member not defined
*/
int sukisu_super_container_of(const char *struct_name, const char *member_name, void *ptr,
void **out_ptr)
{
if (ptr == NULL)
return -3;
}
size_t i;
for(i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
for (size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
struct DynamicStructInfo *info = dynamic_struct_infos[i];
if (strcmp(struct_name, info->name) == 0) {
size_t i1;
for (i1 = 0; i1 < info->count; i1++) {
for (size_t i1 = 0; i1 < info->count; i1++) {
if (strcmp(info->members[i1].name, member_name) == 0) {
*out_ptr = (void *)DYNAMIC_CONTAINER_OF(info->members[i1].offset, ptr);
return 0;
}
}
return -2;
}
}
return -1;
}
EXPORT_SYMBOL(sukisu_super_container_of);

View File

@@ -6,34 +6,10 @@
#include "kpm.h"
#include "compact.h"
// return 0 if successful
// return -1 if struct not defined
int sukisu_super_find_struct(
const char* struct_name,
size_t* out_size,
int* out_members
);
// Dynamic access struct
// return 0 if successful
// return -1 if struct not defined
// return -2 if member not defined
int sukisu_super_access (
const char* struct_name,
const char* member_name,
size_t* out_offset,
size_t* out_size
);
// Dynamic container_of
// return 0 if success
// return -1 if current struct not defined
// return -2 if target member not defined
int sukisu_super_container_of(
const char* struct_name,
const char* member_name,
void* ptr,
void** out_ptr
);
extern int sukisu_super_find_struct(const char *struct_name, size_t *out_size, int *out_members);
extern int sukisu_super_access(const char *struct_name, const char *member_name, size_t *out_offset,
size_t *out_size);
extern int sukisu_super_container_of(const char *struct_name, const char *member_name, void *ptr,
void **out_ptr);
#endif

View File

@@ -542,6 +542,9 @@ static const struct ksu_ioctl_cmd_map ksu_ioctl_handlers[] = {
{ .cmd = KSU_IOCTL_DYNAMIC_MANAGER, .name = "SET_DYNAMIC_MANAGER", .handler = do_dynamic_manager, .perm_check = manager_or_root},
{ .cmd = KSU_IOCTL_GET_MANAGERS, .name = "GET_MANAGERS", .handler = do_get_managers, .perm_check = manager_or_root},
{ .cmd = KSU_IOCTL_ENABLE_UID_SCANNER, .name = "SET_ENABLE_UID_SCANNER", .handler = do_enable_uid_scanner, .perm_check = manager_or_root},
#ifdef CONFIG_KPM
{ .cmd = KSU_IOCTL_KPM, .name = "KPM_OPERATION", .handler = do_kpm, .perm_check = manager_or_root},
#endif
{ .cmd = 0, .name = NULL, .handler = NULL, .perm_check = NULL} // Sentine
};

View File

@@ -5,6 +5,10 @@
#include <linux/ioctl.h>
#include "ksu.h"
#ifdef CONFIG_KPM
#include "kpm/kpm.h"
#endif
// Magic numbers for reboot hook to install fd
#define KSU_INSTALL_MAGIC1 0xDEADBEEF
#define KSU_INSTALL_MAGIC2 0xCAFEBABE