Repo created
This commit is contained in:
parent
0bf9b15769
commit
b7554a5383
363 changed files with 72328 additions and 0 deletions
6
kernel/kpm/Makefile
Normal file
6
kernel/kpm/Makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
obj-y += kpm.o
|
||||
obj-y += compact.o
|
||||
obj-y += super_access.o
|
||||
|
||||
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
|
||||
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function
|
||||
100
kernel/kpm/compact.c
Normal file
100
kernel/kpm/compact.c
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernfs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <asm/elf.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/set_memory.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include "kpm.h"
|
||||
#include "compact.h"
|
||||
#include "../allowlist.h"
|
||||
#include "../manager.h"
|
||||
|
||||
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)
|
||||
{
|
||||
return 0; /* Not supported */
|
||||
}
|
||||
|
||||
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(void)
|
||||
{
|
||||
return is_manager();
|
||||
}
|
||||
|
||||
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 },
|
||||
{ "is_run_in_sukisu_ultra", (void *)1 },
|
||||
{ "is_su_allow_uid", &sukisu_is_su_allow_uid },
|
||||
{ "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 },
|
||||
{ "sukisu_set_manager_uid", &sukisu_set_manager_uid }
|
||||
};
|
||||
|
||||
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)
|
||||
return (unsigned long)symbol->addr;
|
||||
}
|
||||
|
||||
addr = kallsyms_lookup_name(name);
|
||||
if (addr)
|
||||
return addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(sukisu_compact_find_symbol);
|
||||
6
kernel/kpm/compact.h
Normal file
6
kernel/kpm/compact.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __SUKISU_KPM_COMPACT_H
|
||||
#define __SUKISU_KPM_COMPACT_H
|
||||
|
||||
extern unsigned long sukisu_compact_find_symbol(const char *name);
|
||||
|
||||
#endif
|
||||
211
kernel/kpm/kpm.c
Normal file
211
kernel/kpm/kpm.c
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2025 Liankong (xhsw.new@outlook.com). All Rights Reserved.
|
||||
* 本代码由GPL-2授权
|
||||
*
|
||||
* 适配KernelSU的KPM 内核模块加载器兼容实现
|
||||
*
|
||||
* 集成了 ELF 解析、内存布局、符号处理、重定位(支持 ARM64 重定位类型)
|
||||
* 并参照KernelPatch的标准KPM格式实现加载和控制
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernfs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <asm/elf.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/set_memory.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/insn.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/stacktrace.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES)
|
||||
#include <linux/moduleloader.h>
|
||||
#endif
|
||||
#include "kpm.h"
|
||||
#include "compact.h"
|
||||
|
||||
#ifndef NO_OPTIMIZE
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#define NO_OPTIMIZE __attribute__((optimize("O0")))
|
||||
#elif defined(__clang__)
|
||||
#define NO_OPTIMIZE __attribute__((optnone))
|
||||
#else
|
||||
#define NO_OPTIMIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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.");
|
||||
}
|
||||
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);
|
||||
|
||||
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 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)
|
||||
return -1;
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
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);
|
||||
} 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)
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
58
kernel/kpm/kpm.h
Normal file
58
kernel/kpm/kpm.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#ifndef __SUKISU_KPM_H
|
||||
#define __SUKISU_KPM_H
|
||||
|
||||
extern int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4,
|
||||
unsigned long arg5);
|
||||
extern int sukisu_is_kpm_control_code(unsigned long arg2);
|
||||
|
||||
/* KPM Control Code */
|
||||
#define CMD_KPM_CONTROL 28
|
||||
#define CMD_KPM_CONTROL_MAX 35
|
||||
|
||||
/* Control Code */
|
||||
/*
|
||||
* prctl(xxx, 28, "PATH", "ARGS")
|
||||
* success return 0, error return -N
|
||||
*/
|
||||
#define SUKISU_KPM_LOAD 28
|
||||
|
||||
/*
|
||||
* prctl(xxx, 29, "NAME")
|
||||
* success return 0, error return -N
|
||||
*/
|
||||
#define SUKISU_KPM_UNLOAD 29
|
||||
|
||||
/*
|
||||
* num = prctl(xxx, 30)
|
||||
* error return -N
|
||||
* success return +num or 0
|
||||
*/
|
||||
#define SUKISU_KPM_NUM 30
|
||||
|
||||
/*
|
||||
* prctl(xxx, 31, Buffer, BufferSize)
|
||||
* success return +out, error return -N
|
||||
*/
|
||||
#define SUKISU_KPM_LIST 31
|
||||
|
||||
/*
|
||||
* prctl(xxx, 32, "NAME", Buffer[256])
|
||||
* success return +out, error return -N
|
||||
*/
|
||||
#define SUKISU_KPM_INFO 32
|
||||
|
||||
/*
|
||||
* prctl(xxx, 33, "NAME", "ARGS")
|
||||
* success return KPM's result value
|
||||
* error return -N
|
||||
*/
|
||||
#define SUKISU_KPM_CONTROL 33
|
||||
|
||||
/*
|
||||
* prctl(xxx, 34, buffer, bufferSize)
|
||||
* success return KPM's result value
|
||||
* error return -N
|
||||
*/
|
||||
#define SUKISU_KPM_VERSION 34
|
||||
|
||||
#endif
|
||||
278
kernel/kpm/super_access.c
Normal file
278
kernel/kpm/super_access.c
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernfs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <asm/elf.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/set_memory.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.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;
|
||||
size_t total_size;
|
||||
struct DynamicStructMember *members;
|
||||
};
|
||||
|
||||
#define DYNAMIC_STRUCT_BEGIN(struct_name) \
|
||||
static struct DynamicStructMember struct_name##_members[] = {
|
||||
|
||||
#define DEFINE_MEMBER(struct_name, member) \
|
||||
{ \
|
||||
.name = #member, \
|
||||
.size = sizeof(((struct struct_name *)0)->member), \
|
||||
.offset = offsetof(struct struct_name, member) \
|
||||
},
|
||||
|
||||
#define DYNAMIC_STRUCT_END(struct_name) \
|
||||
}; \
|
||||
static struct DynamicStructInfo struct_name##_info = { \
|
||||
.name = #struct_name, \
|
||||
.count = sizeof(struct_name##_members) / sizeof(struct DynamicStructMember), \
|
||||
.total_size = sizeof(struct struct_name), \
|
||||
.members = struct_name##_members \
|
||||
};
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(mount)
|
||||
DEFINE_MEMBER(mount, mnt_parent)
|
||||
DEFINE_MEMBER(mount, mnt)
|
||||
DEFINE_MEMBER(mount, mnt_id)
|
||||
DEFINE_MEMBER(mount, mnt_group_id)
|
||||
DEFINE_MEMBER(mount, mnt_expiry_mark)
|
||||
DEFINE_MEMBER(mount, mnt_master)
|
||||
DEFINE_MEMBER(mount, mnt_devname)
|
||||
DYNAMIC_STRUCT_END(mount)
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(vfsmount)
|
||||
DEFINE_MEMBER(vfsmount, mnt_root)
|
||||
DEFINE_MEMBER(vfsmount, mnt_sb)
|
||||
DEFINE_MEMBER(vfsmount, mnt_flags)
|
||||
DYNAMIC_STRUCT_END(vfsmount)
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(mnt_namespace)
|
||||
DEFINE_MEMBER(mnt_namespace, ns)
|
||||
DEFINE_MEMBER(mnt_namespace, root)
|
||||
DEFINE_MEMBER(mnt_namespace, seq)
|
||||
DEFINE_MEMBER(mnt_namespace, mounts)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
|
||||
DEFINE_MEMBER(mnt_namespace, count)
|
||||
#endif
|
||||
DYNAMIC_STRUCT_END(mnt_namespace)
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
DYNAMIC_STRUCT_BEGIN(kprobe)
|
||||
DEFINE_MEMBER(kprobe, addr)
|
||||
DEFINE_MEMBER(kprobe, symbol_name)
|
||||
DEFINE_MEMBER(kprobe, offset)
|
||||
DEFINE_MEMBER(kprobe, pre_handler)
|
||||
DEFINE_MEMBER(kprobe, post_handler)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
|
||||
DEFINE_MEMBER(kprobe, fault_handler)
|
||||
#endif
|
||||
DEFINE_MEMBER(kprobe, flags)
|
||||
DYNAMIC_STRUCT_END(kprobe)
|
||||
#endif
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(vm_area_struct)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_start)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_end)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_flags)
|
||||
DEFINE_MEMBER(vm_area_struct,anon_vma)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_pgoff)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_file)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_private_data)
|
||||
#ifdef CONFIG_ANON_VMA_NAME
|
||||
DEFINE_MEMBER(vm_area_struct, anon_name)
|
||||
#endif
|
||||
DEFINE_MEMBER(vm_area_struct, vm_ops)
|
||||
DYNAMIC_STRUCT_END(vm_area_struct)
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(vm_operations_struct)
|
||||
DEFINE_MEMBER(vm_operations_struct, open)
|
||||
DEFINE_MEMBER(vm_operations_struct, close)
|
||||
DEFINE_MEMBER(vm_operations_struct, name)
|
||||
DEFINE_MEMBER(vm_operations_struct, access)
|
||||
DYNAMIC_STRUCT_END(vm_operations_struct)
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(netlink_kernel_cfg)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, groups)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, flags)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, input)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, cb_mutex)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, bind)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, unbind)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, compare)
|
||||
#endif
|
||||
DYNAMIC_STRUCT_END(netlink_kernel_cfg)
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(task_struct)
|
||||
DEFINE_MEMBER(task_struct, pid)
|
||||
DEFINE_MEMBER(task_struct, tgid)
|
||||
DEFINE_MEMBER(task_struct, cred)
|
||||
DEFINE_MEMBER(task_struct, real_cred)
|
||||
DEFINE_MEMBER(task_struct, comm)
|
||||
DEFINE_MEMBER(task_struct, parent)
|
||||
DEFINE_MEMBER(task_struct, group_leader)
|
||||
DEFINE_MEMBER(task_struct, mm)
|
||||
DEFINE_MEMBER(task_struct, active_mm)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
DEFINE_MEMBER(task_struct, pids[PIDTYPE_PID].pid)
|
||||
#else
|
||||
DEFINE_MEMBER(task_struct, thread_pid)
|
||||
#endif
|
||||
DEFINE_MEMBER(task_struct, files)
|
||||
DEFINE_MEMBER(task_struct, seccomp)
|
||||
#ifdef CONFIG_THREAD_INFO_IN_TASK
|
||||
DEFINE_MEMBER(task_struct, thread_info)
|
||||
#endif
|
||||
#ifdef CONFIG_CGROUPS
|
||||
DEFINE_MEMBER(task_struct, cgroups)
|
||||
#endif
|
||||
#ifdef CONFIG_SECURITY
|
||||
DEFINE_MEMBER(task_struct, security)
|
||||
#endif
|
||||
DEFINE_MEMBER(task_struct, thread)
|
||||
DYNAMIC_STRUCT_END(task_struct)
|
||||
|
||||
#define STRUCT_INFO(name) &(name##_info)
|
||||
|
||||
static struct DynamicStructInfo *dynamic_struct_infos[] = {
|
||||
STRUCT_INFO(mount),
|
||||
STRUCT_INFO(vfsmount),
|
||||
STRUCT_INFO(mnt_namespace),
|
||||
#ifdef CONFIG_KPROBES
|
||||
STRUCT_INFO(kprobe),
|
||||
#endif
|
||||
STRUCT_INFO(vm_area_struct),
|
||||
STRUCT_INFO(vm_operations_struct),
|
||||
STRUCT_INFO(netlink_kernel_cfg),
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
|
||||
#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)
|
||||
return -3;
|
||||
|
||||
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) {
|
||||
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);
|
||||
15
kernel/kpm/super_access.h
Normal file
15
kernel/kpm/super_access.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef __SUKISU_SUPER_ACCESS_H
|
||||
#define __SUKISU_SUPER_ACCESS_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include "kpm.h"
|
||||
#include "compact.h"
|
||||
|
||||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue