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

View File

@@ -1,6 +1,6 @@
#ifndef ___SUKISU_KPM_COMPACT_H #ifndef __SUKISU_KPM_COMPACT_H
#define ___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 #endif

View File

@@ -8,6 +8,7 @@
* 集成了 ELF 解析、内存布局、符号处理、重定位(支持 ARM64 重定位类型) * 集成了 ELF 解析、内存布局、符号处理、重定位(支持 ARM64 重定位类型)
* 并参照KernelPatch的标准KPM格式实现加载和控制 * 并参照KernelPatch的标准KPM格式实现加载和控制
*/ */
#include <linux/export.h> #include <linux/export.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@@ -23,7 +24,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */ #include <asm/elf.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/string.h> #include <linux/string.h>
@@ -39,7 +40,7 @@
#include <linux/stacktrace.h> #include <linux/stacktrace.h>
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES)
#include <linux/moduleloader.h> // 需要启用 CONFIG_MODULES #include <linux/moduleloader.h>
#endif #endif
#include "kpm.h" #include "kpm.h"
#include "compact.h" #include "compact.h"
@@ -54,131 +55,170 @@
#endif #endif
#endif #endif
// ============================================================================================ noinline NO_OPTIMIZE void sukisu_kpm_load_module_path(const char *path,
const char *args, void *ptr, void __user *result)
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.
int res = -1; 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 printk("KPM: Stub function called (sukisu_kpm_load_module_path). "
NO_OPTIMIZE "path=%s args=%s ptr=%p\n", path, args, ptr);
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.");
}
noinline __asm__ volatile("nop");
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.");
}
noinline if (copy_to_user(result, &res, sizeof(res)) < 1)
NO_OPTIMIZE printk("KPM: Copy to user failed.");
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.");
} }
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); 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); 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); 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); 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_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); EXPORT_SYMBOL(sukisu_kpm_control);
noinline noinline NO_OPTIMIZE void sukisu_kpm_version(void __user *out, unsigned int bufferSize,
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) void __user *result)
{ {
if(arg2 == SUKISU_KPM_LOAD) { 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_load_path[256] = { 0 };
char kernel_args_buffer[256] = { 0 }; char kernel_args_buffer[256] = { 0 };
if(arg3 == 0) { if (arg3 == 0)
return -1; return -1;
}
strncpy_from_user((char*)&kernel_load_path, (const char __user *)arg3, 255); strncpy_from_user((char *)&kernel_load_path, (const char __user *)arg3, 255);
if(arg4 != 0) {
strncpy_from_user((char*)&kernel_args_buffer, (const char __user *)arg4, 255); 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);
} else if(arg2 == SUKISU_KPM_UNLOAD) { 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 }; char kernel_name_buffer[256] = { 0 };
if(arg3 == 0) { if (arg3 == 0)
return -1; return -1;
}
strncpy_from_user((char*)&kernel_name_buffer, (const char __user *)arg3, 255); 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);
} else if(arg2 == SUKISU_KPM_NUM) { sukisu_kpm_unload_module((const char *)&kernel_name_buffer, NULL,
sukisu_kpm_num((void __user*) arg5); (void __user *)arg5);
} else if(arg2 == SUKISU_KPM_INFO) { } else if (arg2 == SUKISU_KPM_NUM) {
sukisu_kpm_num((void __user *)arg5);
} else if (arg2 == SUKISU_KPM_INFO) {
char kernel_name_buffer[256] = { 0 }; char kernel_name_buffer[256] = { 0 };
if(arg3 == 0 || arg4 == 0) { if (arg3 == 0 || arg4 == 0)
return -1; 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);
} else if (arg2 == SUKISU_KPM_LIST) {
sukisu_kpm_list((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);
} }
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);
} 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);
}
return 0; return 0;
} }
EXPORT_SYMBOL(sukisu_handle_kpm);
int sukisu_is_kpm_control_code(unsigned long arg2) { 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 #ifndef __SUKISU_KPM_H
#define ___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_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
int sukisu_is_kpm_control_code(unsigned long arg2); int sukisu_is_kpm_control_code(unsigned long arg2);
int do_kpm(void __user *arg);
// KPM控制代码 #define KSU_IOCTL_KPM _IOC(_IOC_READ|_IOC_WRITE, 'K', 200, 0)
#define CMD_KPM_CONTROL 28
#define CMD_KPM_CONTROL_MAX 35
// 控制代码 /* KPM Control Code */
#define CMD_KPM_CONTROL 1
#define CMD_KPM_CONTROL_MAX 10
// prctl(xxx, 28, "PATH", "ARGS") /* Control Code */
// success return 0, error return -N /*
#define SUKISU_KPM_LOAD 28 * 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 * prctl(xxx, 2, "NAME")
#define SUKISU_KPM_UNLOAD 29 * success return 0, error return -N
*/
#define SUKISU_KPM_UNLOAD 2
// num = prctl(xxx, 30) /*
// error return -N * num = prctl(xxx, 3)
// success return +num or 0 * error return -N
#define SUKISU_KPM_NUM 30 * success return +num or 0
*/
#define SUKISU_KPM_NUM 3
// prctl(xxx, 31, Buffer, BufferSize) /*
// success return +out, error return -N * prctl(xxx, 4, Buffer, BufferSize)
#define SUKISU_KPM_LIST 31 * success return +out, error return -N
*/
#define SUKISU_KPM_LIST 4
// prctl(xxx, 32, "NAME", Buffer[256]) /*
// success return +out, error return -N * prctl(xxx, 5, "NAME", Buffer[256])
#define SUKISU_KPM_INFO 32 * success return +out, error return -N
*/
#define SUKISU_KPM_INFO 5
// prctl(xxx, 33, "NAME", "ARGS") /*
// success return KPM's result value * prctl(xxx, 6, "NAME", "ARGS")
// error return -N * success return KPM's result value
#define SUKISU_KPM_CONTROL 33 * error return -N
*/
#define SUKISU_KPM_CONTROL 6
// prctl(xxx, 34, buffer, bufferSize) /*
// success return KPM's result value * prctl(xxx, 7, buffer, bufferSize)
// error return -N * success return KPM's result value
#define SUKISU_KPM_VERSION 34 * error return -N
*/
#define SUKISU_KPM_VERSION 7
#endif #endif

View File

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

View File

@@ -6,34 +6,10 @@
#include "kpm.h" #include "kpm.h"
#include "compact.h" #include "compact.h"
// return 0 if successful extern int sukisu_super_find_struct(const char *struct_name, size_t *out_size, int *out_members);
// return -1 if struct not defined extern int sukisu_super_access(const char *struct_name, const char *member_name, size_t *out_offset,
int sukisu_super_find_struct( size_t *out_size);
const char* struct_name, extern int sukisu_super_container_of(const char *struct_name, const char *member_name, void *ptr,
size_t* out_size, void **out_ptr);
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
);
#endif #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_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_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}, { .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 { .cmd = 0, .name = NULL, .handler = NULL, .perm_check = NULL} // Sentine
}; };

View File

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