297 lines
8.8 KiB
C
297 lines
8.8 KiB
C
#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> /* 包含 ARM64 重定位类型定义 */
|
|
#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 <linux/types.h>
|
|
#include <linux/stddef.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;
|
|
};
|
|
|
|
// 定义结构体元数据的宏(直接使用 struct 名称)
|
|
#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 \
|
|
};
|
|
|
|
// ==================================================================================
|
|
|
|
#include <linux/version.h>
|
|
|
|
#define KERNEL_VERSION_6_1 KERNEL_VERSION(6, 1, 0)
|
|
#define KERNEL_VERSION_5_15 KERNEL_VERSION(5, 15, 0)
|
|
|
|
#include <../fs/mount.h>
|
|
#include <linux/mount.h>
|
|
|
|
// 定义元数据
|
|
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
|
|
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)
|
|
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
|
|
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)
|
|
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)
|
|
|
|
#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)
|
|
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
|
|
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)
|
|
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
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
|
DEFINE_MEMBER(task_struct, security)
|
|
#else
|
|
DEFINE_MEMBER(task_struct, cred)
|
|
#endif
|
|
#endif
|
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
|
DEFINE_MEMBER(task_struct, thread)
|
|
#else
|
|
DEFINE_MEMBER(task_struct, thread_info)
|
|
#endif
|
|
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);
|
|
|
|
// 动态 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) {
|
|
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); |