From 01dacec0d895b91e5b10c8895fa7a562bc2622a5 Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Sun, 18 Jan 2026 13:25:18 +0800 Subject: [PATCH 01/35] Delete code/api_proxy.h --- code/api_proxy.h | 54 ------------------------------------------------ 1 file changed, 54 deletions(-) delete mode 100644 code/api_proxy.h diff --git a/code/api_proxy.h b/code/api_proxy.h deleted file mode 100644 index 083a53d6..00000000 --- a/code/api_proxy.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef API_PROXY_H_ -#define API_PROXY_H_ -#include "ver_control.h" -#include "linux_kernel_api.h" -#include -#include -#include -#include - -//声明 -////////////////////////////////////////////////////////////////////////// -static inline int x_atoi(const char arr[]); -static inline bool x_isdigit(char c); -static inline struct task_struct* x_get_current(void); -static inline void * x_kmalloc(size_t size, gfp_t flags); -static inline unsigned long x_copy_from_user(void *to, const void __user *from, unsigned long n); -static inline unsigned long x_copy_to_user(void __user *to, const void *from, unsigned long n); - -//实现 -////////////////////////////////////////////////////////////////////////// -static inline bool x_isdigit(char c) { return (unsigned)(c - '0') < 10; } -static inline int x_atoi(const char arr[]) { - int index = 0; - int flag = 1; - int num = 0; - - if (arr == NULL) { return -1; } - while (isspace(arr[index])) { index++; } - if (arr[index] == '-') { flag = -1; } - if (arr[index] == '-' || arr[index] == '+') { index++; } - while (arr[index] >= '0' && arr[index] <= '9') { num = num * 10 + arr[index] - '0'; index++; } - return flag * num; -} - -static struct task_struct *x_get_current(void) { - unsigned long sp_el0; - asm ("mrs %0, sp_el0" : "=r" (sp_el0)); - return (struct task_struct *)sp_el0; -} - -static void * x_kmalloc(size_t size, gfp_t flags) { - return __kmalloc(size, flags); -} - -static unsigned long x_copy_from_user(void *to, const void __user *from, unsigned long n) { - return __arch_copy_from_user(to, from, n); -} - -static unsigned long x_copy_to_user(void __user *to, const void *from, unsigned long n) { - return __arch_copy_to_user(to, from, n); -} -#endif /* API_PROXY_H_ */ - - From 29afe3e8e9dc3416081fbeaef6875db317b25e42 Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Sun, 18 Jan 2026 13:25:39 +0800 Subject: [PATCH 02/35] Delete code directory --- code/Makefile | 1 - code/hide_procfs_dir.h | 82 -- code/linux_kernel_api.h | 78 - code/phy_mem.h | 292 ---- code/phy_mem_auto_offset.h | 144 -- code/proc_cmdline.h | 81 - code/proc_cmdline_auto_offset.h | 83 -- code/proc_list.h | 62 - code/proc_list_auto_offset.h | 92 -- code/proc_maps.h | 2445 ------------------------------- code/proc_maps_auto_offset.h | 364 ----- code/proc_root.h | 63 - code/proc_root_auto_offset.h | 59 - code/proc_rss.h | 32 - code/rwProcMem_module.c | 397 ----- code/rwProcMem_module.h | 62 - code/test.h | 168 --- code/ver_control.h | 47 - 18 files changed, 4552 deletions(-) delete mode 100644 code/Makefile delete mode 100644 code/hide_procfs_dir.h delete mode 100644 code/linux_kernel_api.h delete mode 100644 code/phy_mem.h delete mode 100644 code/phy_mem_auto_offset.h delete mode 100644 code/proc_cmdline.h delete mode 100644 code/proc_cmdline_auto_offset.h delete mode 100644 code/proc_list.h delete mode 100644 code/proc_list_auto_offset.h delete mode 100644 code/proc_maps.h delete mode 100644 code/proc_maps_auto_offset.h delete mode 100644 code/proc_root.h delete mode 100644 code/proc_root_auto_offset.h delete mode 100644 code/proc_rss.h delete mode 100644 code/rwProcMem_module.c delete mode 100644 code/rwProcMem_module.h delete mode 100644 code/test.h delete mode 100644 code/ver_control.h diff --git a/code/Makefile b/code/Makefile deleted file mode 100644 index 1ed512af..00000000 --- a/code/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m += rwProcMem_module.o diff --git a/code/hide_procfs_dir.h b/code/hide_procfs_dir.h deleted file mode 100644 index bf1aa95a..00000000 --- a/code/hide_procfs_dir.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _HIDE_PROCFS_DIR_H_ -#define _HIDE_PROCFS_DIR_H_ - -#include "ver_control.h" - -#include -#include -#include -#include -#include -#include - -static char g_hide_dir_name[256] = {0}; - -static filldir_t old_filldir; - -#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(6,1,0) -static int my_filldir(struct dir_context *buf, - const char *name, - int namelen, - loff_t offset, - u64 ino, - unsigned int d_type) -{ - if (namelen == strlen(g_hide_dir_name) && - !strncmp(name, g_hide_dir_name, namelen)) - { - return 0; - } - return old_filldir(buf, name, namelen, offset, ino, d_type); -} -#else -static bool my_filldir(struct dir_context *ctx, - const char *name, - int namelen, - loff_t offset, - u64 ino, - unsigned int d_type) -{ - if (namelen == strlen(g_hide_dir_name) && - !strncmp(name, g_hide_dir_name, namelen)) - { - return true; - } - return old_filldir(ctx, name, namelen, offset, ino, d_type); -} -#endif - -static int handler_pre(struct kprobe *kp, struct pt_regs *regs) -{ - struct dir_context *ctx = (struct dir_context *)regs->regs[1]; - old_filldir = ctx->actor; - ctx->actor = my_filldir; - return 0; -} - -static struct kprobe kp_hide_procfs_dir = { - .symbol_name = "proc_root_readdir", - .pre_handler = handler_pre, -}; - -static bool start_hide_procfs_dir(const char* hide_dir_name) -{ - //这里原理上可以换成SKRoot的汇编写法。避免kprobe。 - int ret; - strlcpy(g_hide_dir_name, hide_dir_name, sizeof(g_hide_dir_name)); - ret = register_kprobe(&kp_hide_procfs_dir); - if (ret) { - printk_debug("[hide_procfs_dir] register_kprobe failed: %d\n", ret); - return false; - } - printk_debug("[hide_procfs_dir] kprobe installed, hiding \"%s\"\n", g_hide_dir_name); - return true; -} - -static void stop_hide_procfs_dir(void) -{ - unregister_kprobe(&kp_hide_procfs_dir); - printk_debug("[hide_procfs_dir] kprobe removed\n"); -} - -#endif // _HIDE_PROCFS_DIR_H_ diff --git a/code/linux_kernel_api.h b/code/linux_kernel_api.h deleted file mode 100644 index ab693e75..00000000 --- a/code/linux_kernel_api.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef LINUX_KERNEL_API_H_ -#define LINUX_KERNEL_API_H_ -#include "ver_control.h" - -#include - -#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0) - -long probe_kernel_read(void* dst, const void* src, size_t size); - -static long x_probe_kernel_read(void* bounce, const char* ptr, size_t sz) { - return probe_kernel_read(bounce, ptr, sz); -} - -#endif - -#if MY_LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) - -long copy_from_kernel_nofault(void* dst, const void* src, size_t size); - -static long x_probe_kernel_read(void* bounce, const char* ptr, size_t sz) { - return copy_from_kernel_nofault(bounce, ptr, sz); -} - -#endif - - -#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0) -static inline pte_t x_pte_mkwrite(pte_t pte) { - return pte_mkwrite(pte); -} -#else -static inline pte_t x_pte_mkwrite(pte_t pte) { - struct vm_area_struct vma = {.vm_flags = VM_READ}; - return pte_mkwrite(pte, &vma); -} -#endif - -#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0) -static size_t x_read_mm_struct_rss(struct mm_struct * mm, ssize_t offset) { - struct mm_rss_stat *rss_stat = (struct mm_rss_stat *)((size_t)&mm->rss_stat + offset); - size_t total_rss; - ssize_t val1, val2, val3; - val1 = atomic_long_read(&rss_stat->count[MM_FILEPAGES]); - val2 = atomic_long_read(&rss_stat->count[MM_ANONPAGES]); -#ifdef MM_SHMEMPAGES - val3 = atomic_long_read(&rss_stat->count[MM_SHMEMPAGES]); -#else - val3 = 0; -#endif - if (val1 < 0) { val1 = 0; } - if (val2 < 0) { val2 = 0; } - if (val3 < 0) { val3 = 0; } - total_rss = val1 + val2 + val3; - return total_rss; -} -#else -static size_t x_read_mm_struct_rss(struct mm_struct * mm, ssize_t offset) { - struct percpu_counter *rss_stat = (struct percpu_counter *)((size_t)&mm->rss_stat + offset); - size_t total_rss; - ssize_t val1, val2, val3; - val1 = percpu_counter_read(&rss_stat[MM_FILEPAGES]); - val2 = percpu_counter_read(&rss_stat[MM_ANONPAGES]); - - #ifdef MM_SHMEMPAGES - val3 = percpu_counter_read(&rss_stat[MM_SHMEMPAGES]); - #else - val3 = 0; - #endif - if (val1 < 0) { val1 = 0; } - if (val2 < 0) { val2 = 0; } - if (val3 < 0) { val3 = 0; } - total_rss = val1 + val2 + val3; - return total_rss; -} -#endif - -#endif /* LINUX_KERNEL_API_H_ */ diff --git a/code/phy_mem.h b/code/phy_mem.h deleted file mode 100644 index 4d6c6d89..00000000 --- a/code/phy_mem.h +++ /dev/null @@ -1,292 +0,0 @@ -#ifndef PHY_MEM_H_ -#define PHY_MEM_H_ -//声明 -////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#include "phy_mem_auto_offset.h" -#include "api_proxy.h" -#include "ver_control.h" - -static inline int is_pte_can_read(pte_t* pte); -static inline int is_pte_can_write(pte_t* pte); -static inline int is_pte_can_exec(pte_t* pte); -static inline int change_pte_read_status(pte_t* pte, bool can_read); -static inline int change_pte_write_status(pte_t* pte, bool can_write); -static inline int change_pte_exec_status(pte_t* pte, bool can_exec); - -static inline size_t get_task_proc_phy_addr(struct task_struct* task, size_t virt_addr, pte_t* out_pte); -static inline size_t get_proc_phy_addr(struct pid* proc_pid_struct, size_t virt_addr, pte_t* out_pte); -static inline size_t read_ram_physical_addr(bool is_kernel_buf, size_t phy_addr, char* lpBuf, size_t read_size); -static inline size_t write_ram_physical_addr(size_t phy_addr, char* lpBuf, bool is_kernel_buf, size_t write_size); - -//实现 -////////////////////////////////////////////////////////////////////////// -#include -#include -#include - -#if MY_LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,83) -#include -#include -#endif - - -#define RETURN_VALUE(size_t_ptr___out_ret, size_t___value) *size_t_ptr___out_ret=size_t___value;break; - -#include - -static inline size_t get_task_proc_phy_addr(struct task_struct* task, size_t virt_addr, pte_t *out_pte) { - struct mm_struct *mm; - pgd_t *pgd; - p4d_t *p4d; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - unsigned long paddr = 0; - unsigned long page_addr = 0; - unsigned long page_offset = 0; - *(size_t*)out_pte = 0; - - if (!task) { - return 0; - } - mm = get_task_mm(task); - if (!mm) { - return 0; - } - pgd = x_pgd_offset(mm, virt_addr); - if (pgd == NULL) { - printk_debug("pgd is null\n"); - goto out; - } - //printk_debug("pgd_val = 0x%lx pgd addr:0x%p\n", (unsigned long int)pgd_val(*pgd), (void*)pgd); - //printk_debug("init_mm pgd val:0x%lx,pgd addr:0x%p\n", (unsigned long)pgd_val(*(mm->pgd)), (void*)mm->pgd); - printk_debug("pgd_index = %zu\n", pgd_index(virt_addr)); - if (pgd_none(*pgd)) { - printk_debug("not mapped in pgd\n"); - goto out; - } - printk_debug("pgd_offset ok\n"); - - /* - * (p4ds are folded into pgds so this doesn't get actually called, - * but the define is needed for a generic inline function.) - */ - p4d = p4d_offset(pgd, virt_addr); - //printk_debug("p4d_val = 0x%llx, p4d_index = %d\n", p4d_val(*p4d), p4d_index(virt_addr)); - printk_debug("p4d_val = 0x%llx\n", p4d_val(*p4d)); - if (p4d_none(*p4d)) - { - printk_debug("not mapped in p4d\n"); - goto out; - } - - pud = pud_offset(p4d, virt_addr); - printk_debug("pud_val = 0x%llx \n", pud_val(*pud)); - if (pud_none(*pud)) { - printk_debug("not mapped in pud\n"); - goto out; - } - printk_debug("pud_offset ok\n"); - - pmd = pmd_offset(pud, virt_addr); - printk_debug("pmd_val = 0x%llx\n", pmd_val(*pmd)); - //printk_debug("pmd_index = %d\n", pmd_index(virt_addr)); - if (pmd_none(*pmd)) { - printk_debug("not mapped in pmd\n"); - goto out; - } - printk_debug("pmd_offset ok\n"); - - pte = pte_offset_kernel(pmd, virt_addr); - printk_debug("pte_val = 0x%llx\n", pte_val(*pte)); - //printk_debug("pte_index = %d\n", pte_index(virt_addr)); - if (pte_none(*pte)) { - printk_debug("not mapped in pte\n"); - goto out; - } - printk_debug("pte_offset_kernel ok\n"); - - page_addr = page_to_phys(pte_page(*pte)); - page_offset = virt_addr & ~PAGE_MASK; - paddr = page_addr | page_offset; - - printk_debug("page_addr = %lx, page_offset = %lx\n", page_addr, page_offset); - printk_debug("vaddr = %zx, paddr = %lx\n", virt_addr, paddr); - - *(size_t*)out_pte = (size_t)pte; - -out: - mmput(mm); - return paddr; -} - - -static inline size_t get_proc_phy_addr(struct pid* proc_pid_struct, size_t virt_addr, pte_t* out_pte) { - struct task_struct* task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { return 0; } - return get_task_proc_phy_addr(task, virt_addr, out_pte); -} - - -static inline int is_pte_can_read(pte_t* pte) { - if (!pte) { return 0; } -#ifdef pte_read - if (pte_read(*pte)) { return 1; } else { return 0; } -#endif - return 1; - } -static inline int is_pte_can_write(pte_t* pte) { - if (!pte) { return 0; } - if (pte_write(*pte)) { return 1; } else { return 0; } -} -static inline int is_pte_can_exec(pte_t* pte) { - if (!pte) { return 0; } -#ifdef pte_exec - if (pte_exec(*pte)) { return 1; } else { return 0; } -#endif -#ifdef pte_user_exec - if (pte_user_exec(*pte)) { return 1; } else { return 0; } -#endif - return 0; -} -static inline int change_pte_read_status(pte_t* pte, bool can_read) { - if (!pte) { return 0; } - return 1; -} -static inline int change_pte_write_status(pte_t* pte, bool can_write) { - if (!pte) { return 0; } - if (can_write) { - set_pte(pte, x_pte_mkwrite(*pte)); - } else { - set_pte(pte, pte_wrprotect(*pte)); - } - return 1; -} -static inline int change_pte_exec_status(pte_t* pte, bool can_exec) { - if (!pte) { return 0; } - if (can_exec) { -#ifdef pte_mknexec - set_pte(pte, x_pte_mkwrite(*pte)); -#endif - } else { -#ifdef pte_mkexec - set_pte(pte, x_pte_mkwrite(*pte)); -#endif - } - return 1; -} - -static inline unsigned long size_inside_page(unsigned long start, - unsigned long size) { - unsigned long sz; - - sz = PAGE_SIZE - (start & (PAGE_SIZE - 1)); - - return min(sz, size); -} - - -static inline int check_phys_addr_valid_range(size_t addr, size_t count) { - if (g_phy_total_memory_size == 0) { - init_phy_total_memory_size(); - } - return (addr + count) <= g_phy_total_memory_size; -} - - -static inline size_t read_ram_physical_addr(bool is_kernel_buf, size_t phy_addr, char* lpBuf, size_t read_size) { - void *bounce; - size_t realRead = 0; - if (!check_phys_addr_valid_range(phy_addr, read_size)) { - printk_debug(KERN_INFO "Error in check_phys_addr_valid_range:%zu,size:%zu\n", phy_addr, read_size); - return 0; - } - bounce = x_kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!bounce) { - return 0; - } - - while (read_size > 0) { - size_t sz = size_inside_page(phy_addr, read_size); - - /* - * On ia64 if a page has been mapped somewhere as uncached, then - * it must also be accessed uncached by the kernel or data - * corruption may occur. - */ - - char *ptr = xlate_dev_mem_ptr(phy_addr); - int probe; - - if (!ptr) { - printk_debug(KERN_INFO "Error in x_xlate_dev_mem_ptr:0x%zx\n", phy_addr); - break; - } - probe = x_probe_kernel_read(bounce, ptr, sz); - unxlate_dev_mem_ptr(phy_addr, ptr); - if (probe) { - break; - } - if (is_kernel_buf) { - memcpy(lpBuf, bounce, sz); - } else { - unsigned long remaining = x_copy_to_user(lpBuf, bounce, sz); - if (remaining) { - printk_debug(KERN_INFO "Error in x_copy_to_user(\n"); - break; - } - } - lpBuf += sz; - phy_addr += sz; - read_size -= sz; - realRead += sz; - } - kfree(bounce); - return realRead; -} - -static inline size_t write_ram_physical_addr(size_t phy_addr, char* lpBuf, bool is_kernel_buf, size_t write_size) { - size_t realWrite = 0; - if (!check_phys_addr_valid_range(phy_addr, write_size)) { - printk_debug(KERN_INFO "Error in check_phys_addr_valid_range:0x%zx,size:%zu\n", phy_addr, write_size); - return 0; - } - - while (write_size > 0) { - size_t sz = size_inside_page(phy_addr, write_size); - - /* - * On ia64 if a page has been mapped somewhere as uncached, then - * it must also be accessed uncached by the kernel or data - * corruption may occur. - */ - - char *ptr = xlate_dev_mem_ptr(phy_addr); - if (!ptr) { - printk_debug(KERN_INFO "Error in xlate_dev_mem_ptr:0x%zx\n", phy_addr); - break; - } - if (is_kernel_buf) { - memcpy(ptr, lpBuf, sz); - } else { - unsigned long copied = x_copy_from_user(ptr, lpBuf, sz); - if (copied) { - unxlate_dev_mem_ptr(phy_addr, ptr); - realWrite += sz - copied; - printk_debug(KERN_INFO "Error in x_copy_from_user(\n"); - break; - } - } - unxlate_dev_mem_ptr(phy_addr, ptr); - - lpBuf += sz; - phy_addr += sz; - write_size -= sz; - realWrite += sz; - } - return realWrite; -} -#endif /* PHY_MEM_H_ */ \ No newline at end of file diff --git a/code/phy_mem_auto_offset.h b/code/phy_mem_auto_offset.h deleted file mode 100644 index dfebcf77..00000000 --- a/code/phy_mem_auto_offset.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef PHY_MEM_AUTO_OFFSET_H_ -#define PHY_MEM_AUTO_OFFSET_H_ -#include "api_proxy.h" -#include "ver_control.h" - -#undef pgd_offset -#if MY_LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,84) -#define my_pgd_offset(pgd, addr) (pgd+pgd_index(addr)) -#define my_pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr)))) -#endif -#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(5,10,43) -#define my_pgd_offset(pgd, addr) (pgd+pgd_index(addr)) -#define my_pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr)))) -#endif -#if MY_LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,43) -#define my_pgd_offset(pgd, address) pgd_offset_pgd(pgd, address) -#endif - -#define my_get_fs() (current_thread_info()->addr_limit) - -static size_t g_phy_total_memory_size = 0; // 物理内存总大小 -static int init_phy_total_memory_size(void) { - struct sysinfo si; - unsigned long mem_total, sav_total; - unsigned int bitcount = 0; - unsigned int mem_unit = 0; - if (g_phy_total_memory_size) { - return 0; - } - - si_meminfo(&si); - mem_unit = si.mem_unit; - - mem_total = si.totalram; - while (mem_unit > 1) { - bitcount++; - mem_unit >>= 1; - sav_total = mem_total; - mem_total <<= 1; - if (mem_total < sav_total) { - return 0; - } - } - si.totalram <<= bitcount; - g_phy_total_memory_size = __pa(si.totalram); - printk_debug(KERN_INFO "MemTotal si.totalram:%ld\n", si.totalram); - printk_debug(KERN_INFO "g_phy_total_memory_size:%ld\n", g_phy_total_memory_size); - return 0; -} - -static ssize_t g_pgd_offset_mm_struct = 0; -static bool g_init_pgd_offset_success = false; - -#if MY_LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,75) - -static int init_pgd_offset(struct mm_struct *mm) { - int is_found_pgd_offset = 0; - g_init_pgd_offset_success = false; - for (g_pgd_offset_mm_struct = -40; g_pgd_offset_mm_struct <= 80; g_pgd_offset_mm_struct += 1) { - char *rp; - size_t val; - ssize_t accurate_offset = (ssize_t)((size_t)&mm->pgd - (size_t)mm + g_pgd_offset_mm_struct); - if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) { - return -EFAULT; - } - rp = (char*)((size_t)mm + (size_t)accurate_offset); - val = *(size_t*)(rp); - printk_debug(KERN_EMERG "init_pgd_offset %zd:%zd:%p:%ld\n", g_pgd_offset_mm_struct, accurate_offset, rp, val); - - if (val == TASK_SIZE) { - g_pgd_offset_mm_struct += sizeof(unsigned long); - printk_debug(KERN_EMERG "found g_init_pgd_offset_success:%zd\n", g_pgd_offset_mm_struct); - is_found_pgd_offset = 1; - break; - } - } - if (!is_found_pgd_offset) { - printk_debug(KERN_INFO "find pgd offset failed\n"); - return -ESPIPE; - } - g_init_pgd_offset_success = true; - printk_debug(KERN_INFO "g_pgd_offset_mm_struct:%zu\n", g_pgd_offset_mm_struct); - return 0; -} -#else -static int init_pgd_offset(struct mm_struct *mm) { - int is_found_pgd_offset = 0; - g_init_pgd_offset_success = false; - for (g_pgd_offset_mm_struct = -40; g_pgd_offset_mm_struct <= 80; g_pgd_offset_mm_struct += 1) { - char *rp; - size_t val; - ssize_t accurate_offset = (ssize_t)((size_t)&mm->pgd - (size_t)mm + g_pgd_offset_mm_struct); - if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) { - return -EFAULT; - } - rp = (char*)((size_t)mm + (size_t)accurate_offset); - val = *(size_t*)(rp); - printk_debug(KERN_EMERG "init_pgd_offset %zd:%zd:%p:%ld\n", g_pgd_offset_mm_struct, accurate_offset, rp, val); - - if (val == TASK_SIZE) { - g_pgd_offset_mm_struct += sizeof(unsigned long); - g_pgd_offset_mm_struct += sizeof(unsigned long); - printk_debug(KERN_EMERG "found g_init_pgd_offset_success:%zd\n", g_pgd_offset_mm_struct); - is_found_pgd_offset = 1; - break; - } - } - if (!is_found_pgd_offset) { - printk_debug(KERN_INFO "find pgd offset failed\n"); - return -ESPIPE; - } - g_init_pgd_offset_success = true; - printk_debug(KERN_INFO "g_pgd_offset_mm_struct:%zu\n", g_pgd_offset_mm_struct); - return 0; -} -#endif - -static inline pgd_t *x_pgd_offset(struct mm_struct *mm, size_t addr) { - size_t pgd; - ssize_t accurate_offset; - if (g_init_pgd_offset_success == false) { - if (init_pgd_offset(mm) != 0) { - return NULL; - } - } - accurate_offset = (ssize_t)((size_t)&mm->pgd - (size_t)mm + g_pgd_offset_mm_struct); - printk_debug(KERN_INFO "x_pgd_offset accurate_offset:%zd\n", accurate_offset); - if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) { - return NULL; - } - - //拷贝到我自己的pgd指针变量里去 - //写法一(可读性强) - //void * rv = (size_t*)((size_t)mm + (size_t)accurate_offset); - //pgd_t *pgd; - //memcpy(&pgd, rv, sizeof(pgd_t *)); - - //写法二(快些) - pgd = *(size_t*)((size_t)mm + (size_t)accurate_offset); - - return my_pgd_offset((pgd_t*)pgd, addr); -} - -#endif /* PHY_MEM_AUTO_OFFSET_H_ */ \ No newline at end of file diff --git a/code/proc_cmdline.h b/code/proc_cmdline.h deleted file mode 100644 index f6885f59..00000000 --- a/code/proc_cmdline.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PROC_CMDLINE_H_ -#define PROC_CMDLINE_H_ -//声明 -////////////////////////////////////////////////////////////////////////// -#include -#include "ver_control.h" - -static inline struct pid * get_proc_pid_struct(int pid); -static inline int get_proc_pid(struct pid* proc_pid_struct); -static inline void release_proc_pid_struct(struct pid* proc_pid_struct); -static inline int get_proc_cmdline_addr(struct pid* proc_pid_struct, size_t * arg_start, size_t * arg_end); -static inline int get_task_proc_cmdline_addr(struct task_struct *task, size_t * arg_start, size_t * arg_end); - - -//实现 -////////////////////////////////////////////////////////////////////////// -#include "phy_mem.h" -#include "proc_cmdline_auto_offset.h" -#include "api_proxy.h" - -static inline struct pid * get_proc_pid_struct(int pid) { - return find_get_pid(pid); -} - -static inline int get_proc_pid(struct pid* proc_pid_struct) { - return proc_pid_struct->numbers[0].nr; -} - -static inline void release_proc_pid_struct(struct pid* proc_pid_struct) { - put_pid(proc_pid_struct); -} - -static inline int get_proc_cmdline_addr(struct pid* proc_pid_struct, size_t * arg_start, size_t * arg_end) { - int ret = 0; - struct task_struct *task = NULL; - - - if (g_init_arg_start_offset_success == false) { - return -ENOENT; - } - - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { return -EFAULT; } - ret = get_task_proc_cmdline_addr(task, arg_start, arg_end); - return ret; -} - -static inline int get_task_proc_cmdline_addr(struct task_struct *task, size_t * arg_start, size_t * arg_end) { - if (g_init_arg_start_offset_success) { - struct mm_struct *mm; - ssize_t accurate_offset; - mm = get_task_mm(task); - - if (!mm) { return -EFAULT; } - - //精确偏移 - accurate_offset = (ssize_t)((size_t)&mm->arg_start - (size_t)mm + g_arg_start_offset); - if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) { - mmput(mm); - return -EFAULT; - } - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -EFAULT; - } - printk_debug(KERN_INFO "accurate_offset:%zd\n", accurate_offset); - - *arg_start = *(size_t*)((size_t)mm + (size_t)accurate_offset); - *arg_end = *(size_t*)((size_t)mm + (size_t)accurate_offset + sizeof(unsigned long)); - - printk_debug(KERN_INFO "arg_start addr:0x%p\n", (void*)*arg_start); - - up_read_mmap_lock(mm); - mmput(mm); - return 0; - } - return -ESPIPE; -} -#endif /* PROC_CMDLINE_H_ */ \ No newline at end of file diff --git a/code/proc_cmdline_auto_offset.h b/code/proc_cmdline_auto_offset.h deleted file mode 100644 index e7ba159c..00000000 --- a/code/proc_cmdline_auto_offset.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef PROC_CMDLINE_AUTO_OFFSET_H_ -#define PROC_CMDLINE_AUTO_OFFSET_H_ -//声明 -////////////////////////////////////////////////////////////////////////// -#include -#include "ver_control.h" -//实现 -////////////////////////////////////////////////////////////////////////// -#include "api_proxy.h" -static ssize_t g_arg_start_offset = 0; -static bool g_init_arg_start_offset_success = false; - -typedef int(*t_get_task_proc_cmdline_addr)(struct task_struct *task, size_t * arg_start, size_t * arg_end); - -static inline int init_proc_cmdline_offset(const char* my_cmdline, - t_get_task_proc_cmdline_addr o_get_task_proc_cmdline_addr) { - - int is_found_cmdline_offset = 0; - size_t size = 4096; - char *new_cmd_line_buf = NULL; - struct task_struct * mytask = x_get_current(); - - if(g_init_arg_start_offset_success) { - return 0; - } - - new_cmd_line_buf = (char*)kmalloc(size, GFP_KERNEL); - g_init_arg_start_offset_success = true; - for (g_arg_start_offset = -64; g_arg_start_offset <= 64; g_arg_start_offset += 1) { - size_t arg_start = 0, arg_end = 0; - printk_debug(KERN_INFO "get_task_proc_cmdline_addr g_arg_start_offset %zd\n", g_arg_start_offset); - if (o_get_task_proc_cmdline_addr(mytask, &arg_start, &arg_end) == 0) { - printk_debug(KERN_INFO "get_task_proc_cmdline_addr arg_start %p\n", (void*)arg_start); - - if (arg_start > 0) { - - size_t read_size = 0; - - memset(new_cmd_line_buf, 0, size); - - while (read_size < size) { - size_t phy_addr; - size_t pfn_sz; - char *lpOutBuf; - - pte_t *pte; - phy_addr = get_task_proc_phy_addr(mytask, arg_start + read_size, (pte_t*)&pte); - printk_debug(KERN_INFO "phy_addr:0x%zx\n", phy_addr); - if (phy_addr == 0) { - break; - } - - pfn_sz = size_inside_page(phy_addr, ((size - read_size) > PAGE_SIZE) ? PAGE_SIZE : (size - read_size)); - printk_debug(KERN_INFO "pfn_sz:%zu\n", pfn_sz); - - lpOutBuf = (char*)(new_cmd_line_buf + read_size); - read_ram_physical_addr(true, phy_addr, lpOutBuf, pfn_sz); - read_size += pfn_sz; - } - - printk_debug(KERN_INFO "new_cmd_line_buf:%s, len:%ld\n", new_cmd_line_buf, strlen(new_cmd_line_buf)); - - if (strcmp(new_cmd_line_buf, my_cmdline) == 0) { - is_found_cmdline_offset = 1; - break; - } - - - } - } - } - - kfree(new_cmd_line_buf); - - if (!is_found_cmdline_offset) { - g_init_arg_start_offset_success = false; - printk_debug(KERN_INFO "find cmdline offset failed\n"); - return -ESPIPE; - } - printk_debug(KERN_INFO "g_arg_start_offset:%zu\n", g_arg_start_offset); - return 0; -} -#endif /* PROC_CMDLINE_AUTO_OFFSET_H_ */ \ No newline at end of file diff --git a/code/proc_list.h b/code/proc_list.h deleted file mode 100644 index 9786b7ab..00000000 --- a/code/proc_list.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef PROC_LIST_H_ -#define PROC_LIST_H_ -#include "api_proxy.h" -#include "proc_list_auto_offset.h" -#include "ver_control.h" - -#include -#include -#include -#include -#include - -//声明 -////////////////////////////////////////////////////////////////////////// -static ssize_t get_proc_pid_list(bool is_kernel_buf, char* buf, size_t buf_size); - - -//实现 -////////////////////////////////////////////////////////////////////////// - -static ssize_t get_proc_pid_list(bool is_kernel_buf, - char* buf, - size_t buf_size) { - struct task_struct *p, *next; - ssize_t count = 0; - size_t buf_pos = 0; - - if (!g_init_task_next_offset_success || !g_init_task_pid_offset_success) { - return -EFAULT; - } - - p = &init_task; - while (1) { - uintptr_t list_next = *(uintptr_t *)((char *)p + g_task_next_offset); - next = (struct task_struct *)(list_next - g_task_next_offset); - if (next == &init_task) - break; - - count++; - - { - pid_t pid_v = *(pid_t *)((char *)next + g_task_pid_offset); - int pid_n = pid_v; - printk_debug(KERN_INFO "iter_task: pid = %d\n", pid_n); - if (buf_pos < buf_size) { - if (is_kernel_buf) { - memcpy((void*)((size_t)buf + (size_t)buf_pos), &pid_n, sizeof(pid_n)); - } else { - x_copy_to_user((void*)((size_t)buf + (size_t)buf_pos), &pid_n, sizeof(pid_n)); - } - buf_pos += sizeof(pid_n); - } - } - p = next; - } - - return count; -} - -#endif /* PROC_LIST_H_ */ - - diff --git a/code/proc_list_auto_offset.h b/code/proc_list_auto_offset.h deleted file mode 100644 index 68f2398b..00000000 --- a/code/proc_list_auto_offset.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef PROC_LIST_AUTO_OFFSET_H_ -#define PROC_LIST_AUTO_OFFSET_H_ -#include -#include "ver_control.h" - -static ssize_t g_task_next_offset = 0; -static bool g_init_task_next_offset_success = false; - -static ssize_t g_task_pid_offset = 0; -static bool g_init_task_pid_offset_success = false; - -static inline int init_task_next_offset(void) { - struct task_struct * mytask = x_get_current(); - uintptr_t addr_mytask = (uintptr_t)mytask; - uintptr_t addr_mm = (uintptr_t)get_task_mm(mytask); - size_t off_mm = 0; - size_t off = 0; - if(g_init_task_next_offset_success) { - return 0; - } - - for (off = 0; off <= sizeof(struct task_struct) - sizeof(void*); off+=4) { - void *v = *(void **)(addr_mytask + off); - if ((uintptr_t)v == addr_mm) { - off_mm = off; - break; - } - } - - if(off_mm == 0) { - printk_debug(KERN_EMERG "init_task_next_offset mm_struct failed.\n"); - return -EFAULT; - } - printk_debug(KERN_EMERG "init_task_next_offset mm_struct found:%zu.\n", off_mm); - g_task_next_offset = off_mm - sizeof(mytask->pushable_dl_tasks) - sizeof(mytask->pushable_tasks) - sizeof(mytask->tasks); - g_init_task_next_offset_success = true; - printk_debug(KERN_INFO "init_task_next_offset: found tasks offset = %zu bytes\n", g_task_next_offset); - return 0; -} - -static inline int init_task_pid_offset(int pid, int tgid) { - struct task_struct *mytask = x_get_current(); - uintptr_t addr_mytask = (uintptr_t)mytask; - uintptr_t addr_mm = (uintptr_t)get_task_mm(mytask); - size_t off_mm = 0; - size_t off = 0; - - size_t off_pid_static = (uintptr_t)&mytask->pid - addr_mytask; - printk_debug(KERN_INFO - "init_task_pid_offset: mytask@%p, &pid@%p, static off_pid = %zu, sizeof(%zu, %zu)\n", - mytask, &mytask->pid, off_pid_static, sizeof(mytask->pid), sizeof(mytask->tgid)); - - if (g_init_task_pid_offset_success) { - return 0; - } - - for (off = 0; off <= sizeof(struct task_struct) - sizeof(void*); off+=4) { - void *v = *(void **)(addr_mytask + off); - if ((uintptr_t)v == addr_mm) { - off_mm = off; - break; - } - } - - if (off_mm == 0) { - printk_debug(KERN_EMERG "init_task_pid_offset: mm_struct offset not found\n"); - return -EFAULT; - } - printk_debug(KERN_INFO "init_task_pid_offset: mm_struct offset found = %zu\n", off_mm); - - for (off = off_mm; off <= sizeof(struct task_struct) - 2 * sizeof(pid_t); off += 4) { - pid_t pid_v = *(pid_t *)(addr_mytask + off); - pid_t tgid_v = *(pid_t *)(addr_mytask + off + sizeof(pid_t)); - if (pid_v == pid && tgid_v == tgid) { - g_task_pid_offset = off; - g_init_task_pid_offset_success = true; - printk_debug(KERN_INFO - "init_task_pid_offset: found pid/tgid offset = %zu (pid=%d, tgid=%d)\n", - g_task_pid_offset, pid, tgid); - return 0; - } - } - - printk_debug(KERN_EMERG - "init_task_pid_offset: failed to match pid=%d, tgid=%d\n", - pid, tgid); - return -ENOENT; -} - -#endif /* PROC_LIST_AUTO_OFFSET_H_ */ - - diff --git a/code/proc_maps.h b/code/proc_maps.h deleted file mode 100644 index 56360f76..00000000 --- a/code/proc_maps.h +++ /dev/null @@ -1,2445 +0,0 @@ -#ifndef PROC_MAPS_H_ -#define PROC_MAPS_H_ - -//声明 -////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#if MY_LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,83) -#include -#include -#endif - -static inline int down_read_mmap_lock(struct mm_struct *mm); -static inline int up_read_mmap_lock(struct mm_struct *mm); -static inline size_t get_proc_map_count(struct pid* proc_pid_struct); -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size); - -//实现 -////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include "api_proxy.h" -#include "proc_maps_auto_offset.h" -#include "ver_control.h" - -#define MY_PATH_MAX_LEN 1024 -#pragma pack(push,1) -struct map_entry { - unsigned long start; - unsigned long end; - unsigned char flags[4]; - char path[MY_PATH_MAX_LEN]; -}; -#pragma pack(pop) - -static inline size_t get_proc_map_count(struct pid* proc_pid_struct) { - ssize_t accurate_offset; - struct task_struct *task = pid_task(proc_pid_struct, PIDTYPE_PID); - struct mm_struct *mm = get_task_mm(task); - size_t count = 0; - if (g_init_map_count_offset_success == false) { - return 0; - } - - if (down_read_mmap_lock(mm) != 0) { - goto _exit; - } - - accurate_offset = (ssize_t)((size_t)&mm->map_count - (size_t)mm + g_map_count_offset); - printk_debug(KERN_INFO "mm->map_count accurate_offset:%zd\n", accurate_offset); - if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) { - return 0; - } - count = *(int *)((size_t)mm + (size_t)accurate_offset); - - up_read_mmap_lock(mm); - -_exit:mmput(mm); - return count; -} - - -static inline int check_proc_map_can_read(struct pid* proc_pid_struct, size_t proc_virt_addr, size_t size) { - struct task_struct *task = pid_task(proc_pid_struct, PIDTYPE_PID); - struct mm_struct *mm; - struct vm_area_struct *vma; - int res = 0; - if (!task) { return res; } - - mm = get_task_mm(task); - - if (!mm) { return res; } - - if (down_read_mmap_lock(mm) != 0) { - goto _exit; - } - - vma = find_vma(mm, proc_virt_addr); - if (vma) { - if (vma->vm_flags & VM_READ) { - size_t read_end = proc_virt_addr + size; - if (read_end <= vma->vm_end) { - res = 1; - } - } - } - up_read_mmap_lock(mm); - -_exit:mmput(mm); - return res; -} -static inline int check_proc_map_can_write(struct pid* proc_pid_struct, size_t proc_virt_addr, size_t size) { - struct task_struct *task = pid_task(proc_pid_struct, PIDTYPE_PID); - struct mm_struct *mm; - struct vm_area_struct *vma; - int res = 0; - - if (!task) { return res; } - - mm = get_task_mm(task); - - if (!mm) { return res; } - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return res; - } - - vma = find_vma(mm, proc_virt_addr); - if (vma) { - if (vma->vm_flags & VM_WRITE) { - size_t read_end = proc_virt_addr + size; - if (read_end <= vma->vm_end) { - res = 1; - } - } - } - up_read_mmap_lock(mm); - mmput(mm); - return res; -} - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(3,10,0) -/* Check if the vma is being used as a stack by this task */ -static int vm_is_stack_for_task(struct task_struct *t, - struct vm_area_struct *vma) { - return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); -} - -/* - * Check if the vma is being used as a stack. - * If is_group is non-zero, check in the entire thread group or else - * just check in the current task. Returns the pid of the task that - * the vma is stack for. - */ -static pid_t my_vm_is_stack(struct task_struct *task, - struct vm_area_struct *vma, int in_group) { - pid_t ret = 0; - - if (vm_is_stack_for_task(task, vma)) - return task->pid; - - if (in_group) { - struct task_struct *t; - rcu_read_lock(); - if (!pid_alive(task)) - goto done; - - t = task; - do { - if (vm_is_stack_for_task(t, vma)) { - ret = t->pid; - goto done; - } - } while_each_thread(task, t); - done: - rcu_read_unlock(); - } - - return ret; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - if (!mm) { - return -3; - } - - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - /* We don't show the stack guard page in /proc/maps */ - if (stack_guard_page_start(vma, entry.start)) - entry.start += PAGE_SIZE; - if (stack_guard_page_end(vma, entry.end)) - entry.end -= PAGE_SIZE; - - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - pid_t tid = my_vm_is_stack(task, vma, 1); - if (tid != 0) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - - sprintf(entry.path, "[stack:%d]", tid); - } - } - - } - - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - - - -#endif - - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(3,10,84) -/* Check if the vma is being used as a stack by this task */ -static int vm_is_stack_for_task(struct task_struct *t, - struct vm_area_struct *vma) { - return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); -} - -/* - * Check if the vma is being used as a stack. - * If is_group is non-zero, check in the entire thread group or else - * just check in the current task. Returns the pid of the task that - * the vma is stack for. - */ -static pid_t my_vm_is_stack(struct task_struct *task, - struct vm_area_struct *vma, int in_group) { - pid_t ret = 0; - - if (vm_is_stack_for_task(task, vma)) - return task->pid; - - if (in_group) { - struct task_struct *t; - rcu_read_lock(); - if (!pid_alive(task)) - goto done; - - t = task; - do { - if (vm_is_stack_for_task(t, vma)) { - ret = t->pid; - goto done; - } - } while_each_thread(task, t); - done: - rcu_read_unlock(); - } - - return ret; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - if (!mm) { - return -3; - } - - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - /* We don't show the stack guard page in /proc/maps */ - if (stack_guard_page_start(vma, entry.start)) - entry.start += PAGE_SIZE; - if (stack_guard_page_end(vma, entry.end)) - entry.end -= PAGE_SIZE; - - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - pid_t tid = my_vm_is_stack(task, vma, 1); - if (tid != 0) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - - sprintf(entry.path, "[stack:%d]", tid); - } - } - - } - - - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - -#endif - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(3,18,71) -/* Check if the vma is being used as a stack by this task */ -static int vm_is_stack_for_task(struct task_struct *t, - struct vm_area_struct *vma) { - return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); -} - - -/* - * Check if the vma is being used as a stack. - * If is_group is non-zero, check in the entire thread group or else - * just check in the current task. Returns the task_struct of the task - * that the vma is stack for. Must be called under rcu_read_lock(). - */ -struct task_struct *task_of_stack(struct task_struct *task, - struct vm_area_struct *vma, bool in_group) { - if (vm_is_stack_for_task(task, vma)) - return task; - - if (in_group) { - struct task_struct *t; - - for_each_thread(task, t) { - if (vm_is_stack_for_task(t, vma)) - return t; - } - } - - return NULL; -} - - -static pid_t pid_of_stack(struct task_struct *task, - struct vm_area_struct *vma, bool is_pid) { - pid_t ret = 0; - - rcu_read_lock(); - task = task_of_stack(task, vma, is_pid); - if (task) { - ret = task->pid; - } - rcu_read_unlock(); - - return ret; -} - - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - if (!mm) { - return -3; - } - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - pid_t tid = pid_of_stack(task, vma, 1); - if (tid != 0) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - if (vma->vm_start <= mm->start_stack && - vma->vm_end >= mm->start_stack) { - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } else { - snprintf(entry.path, sizeof(entry.path), "[stack:%d]", tid); - } - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - -#endif - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(3,18,140) -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - } - - } - - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - - -#endif - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,4,21) -/* Check if the vma is being used as a stack by this task */ -int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t) { - return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); -} - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct task_struct *task, - struct vm_area_struct *vma, int is_pid) { - int stack = 0; - - if (is_pid) { - stack = vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; - } else { - rcu_read_lock(); - stack = vma_is_stack_for_task(vma, task); - rcu_read_unlock(); - } - return stack; -} - - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - pid_t tid = is_stack(task, vma, 1); - if (tid != 0) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - sprintf(entry.path, "[stack:%d]", tid); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - - - -#endif - - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,4,78) -/* Check if the vma is being used as a stack by this task */ -int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t) { - return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); -} - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct task_struct *task, - struct vm_area_struct *vma, int is_pid) { - int stack = 0; - - if (is_pid) { - stack = vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; - } else { - rcu_read_lock(); - stack = vma_is_stack_for_task(vma, task); - rcu_read_unlock(); - } - return stack; -} - - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - pid_t tid = is_stack(task, vma, 1); - if (tid != 0) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - sprintf(entry.path, "[stack:%d]", tid); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - - -#endif - - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,4,153) -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct task_struct *task, - struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - pid_t tid = is_stack(task, vma); - if (tid != 0) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - -#endif - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,4,192) -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct task_struct *task, - struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - pid_t tid = is_stack(task, vma); - if (tid != 0) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - - -#endif - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,9,112) -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - - - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - -#endif - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,9,186) -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - - - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - - -#endif - - - - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,14,83) - - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - - -#endif - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,14,117) - - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - - - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - - - -#endif - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,14,141) - - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} - - -#endif - - - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,19,81) - - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} -#endif - - - - - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(4,19,113) - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} -#endif - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(5,4,61) - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct *vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct *task; - struct mm_struct *mm; - struct vm_area_struct *vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file * vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char *path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} -#endif - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(5,10,43) - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct* vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct* task; - struct mm_struct* mm; - struct vm_area_struct* vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file* vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char* path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} -#endif - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(5,15,41) - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct* vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct* task; - struct mm_struct* mm; - struct vm_area_struct* vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - for (vma = mm->mmap; vma; vma = vma->vm_next) { - struct map_entry entry; - struct file* vm_file; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char* path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else { - if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else { - if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } - - } - - } - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} -#endif - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(6,1,75) -#include -struct anon_vma_name * __weak anon_vma_name(struct vm_area_struct* vma) { - return NULL; -} - -/* - * Indicate if the VMA is a stack for the given task; for - * /proc/PID/maps that is the stack of the main task. - */ -static int is_stack(struct vm_area_struct* vma) { - /* - * We make no effort to guess what a given thread considers to be - * its "stack". It's not even well-defined for programs written - * languages like Go. - */ - return vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct* task; - struct mm_struct* mm; - struct vm_area_struct* vma; - char path_buf[MY_PATH_MAX_LEN] = {0}; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - - { - VMA_ITERATOR(iter, mm, 0); - for_each_vma(iter, vma) { - struct map_entry entry; - struct file* vm_file; - struct anon_vma_name *anon_name = NULL; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char* path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (!vma->vm_mm) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else if (vma->vm_start <= mm->brk && - vma->vm_end >= mm->start_brk) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else if (is_stack(vma)) { - /* - * Thread stack in /proc/PID/task/TID/maps or - * the main process stack. - */ - - /* Thread stack in /proc/PID/maps */ - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } else { - anon_name = anon_vma_name(vma); - if(anon_name) { - snprintf(entry.path, sizeof(entry.path), "[anon:%s]", anon_name->name); - } - } - - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} -#endif - - -#if MY_LINUX_VERSION_CODE == KERNEL_VERSION(6,6,30) -#include -struct anon_vma_name * __weak anon_vma_name(struct vm_area_struct* vma) { - return NULL; -} - -static int get_proc_maps_list(bool is_kernel_buf, struct pid* proc_pid_struct, char* buf, size_t buf_size) { - struct task_struct* task; - struct mm_struct* mm; - struct vm_area_struct* vma; - char path_buf[MY_PATH_MAX_LEN]; - int success_cnt = 0; - size_t copy_pos; - size_t end_pos; - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return -2; - } - - mm = get_task_mm(task); - - if (!mm) { - return -3; - } - if (is_kernel_buf) { - memset(buf, 0, buf_size); - } - //else if (clear_user(buf, buf_size)) { return -4; } //清空用户的缓冲区 - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + buf_size); - - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -4; - } - - { - VMA_ITERATOR(iter, mm, 0); - for_each_vma(iter, vma) { - struct map_entry entry; - struct file* vm_file; - struct anon_vma_name *anon_name = NULL; - if (copy_pos >= end_pos) { - break; - } - entry.start = vma->vm_start; - entry.end = vma->vm_end; - entry.flags[0] = (vma->vm_flags & VM_READ) ? 1 : 0; - entry.flags[1] = (vma->vm_flags & VM_WRITE) ? 1 : 0; - entry.flags[2] = (vma->vm_flags & VM_EXEC) ? 1 : 0; - entry.flags[3] = (vma->vm_flags & VM_MAYSHARE) ? 1 : 0; - memset(entry.path, 0, sizeof(entry.path)); - vm_file = get_vm_file(vma); - if (vm_file) { - char* path; - memset(path_buf, 0, sizeof(path_buf)); - path = d_path(&vm_file->f_path, path_buf, sizeof(path_buf)); - if (path > 0) { - strncat(entry.path, path, sizeof(entry.path) - 1); - } - } else if (!vma->vm_mm) { - snprintf(entry.path, sizeof(entry.path), "%s[vdso]", entry.path); - } else if (vma_is_initial_heap(vma)) { - snprintf(entry.path, sizeof(entry.path), "%s[heap]", entry.path); - } else if (vma_is_initial_stack(vma)) { - snprintf(entry.path, sizeof(entry.path), "%s[stack]", entry.path); - } else { - anon_name = anon_vma_name(vma); - if(anon_name) { - snprintf(entry.path, sizeof(entry.path), "[anon:%s]", anon_name->name); - } - } - - if (is_kernel_buf) { - memcpy((void *)copy_pos, &entry, sizeof(entry)); - } else { - if (x_copy_to_user((void *)copy_pos, &entry, sizeof(entry))) { - break; - } - } - copy_pos += sizeof(entry); - success_cnt++; - } - } - up_read_mmap_lock(mm); - mmput(mm); - - return success_cnt; -} -#endif - -//Update: vm_is_stack\vm_is_stack_for_task: /mm/util.c -//Update: get_proc_maps_list: fs\proc\task_mmu.c - -#endif /* PROC_MAPS_H_ */ \ No newline at end of file diff --git a/code/proc_maps_auto_offset.h b/code/proc_maps_auto_offset.h deleted file mode 100644 index d0cc77f8..00000000 --- a/code/proc_maps_auto_offset.h +++ /dev/null @@ -1,364 +0,0 @@ -#ifndef PROC_MAPS_AUTO_OFFSET_H_ -#define PROC_MAPS_AUTO_OFFSET_H_ -#include "api_proxy.h" -#include "ver_control.h" - - -#ifndef MM_STRUCT_MMAP_LOCK -#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(5,10,43) -#define MM_STRUCT_MMAP_LOCK mmap_sem -#endif -#if MY_LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,43) -#define MM_STRUCT_MMAP_LOCK mmap_lock -#endif -#endif - -static ssize_t g_mmap_lock_offset = 0; -static bool g_init_mmap_lock_offset_success = false; - -static ssize_t g_map_count_offset = 0; -static bool g_init_map_count_offset_success = false; - -static ssize_t g_vm_file_offset = 0; -static bool g_init_vm_file_offset_success = false; - -static int get_mytask_maps_cnt(void) { - struct task_struct * mytask = x_get_current(); - struct mm_struct * mm = get_task_mm(mytask); - struct vm_area_struct* vma; - int cnt = 0; - #if MY_LINUX_VERSION_CODE < KERNEL_VERSION(6,1,0) - for (vma = mm->mmap; vma; vma = vma->vm_next) { - cnt++; - } - #else - { - VMA_ITERATOR(iter, mm, 0); - for_each_vma(iter, vma) { - cnt++; - } - } - #endif - return cnt; -} - - -static int init_mmap_lock_offset(void) { - int is_found_mmap_lock_offset = 0; - struct task_struct * mytask = x_get_current(); - struct mm_struct * mm = get_task_mm(mytask); - int maps_cnt = get_mytask_maps_cnt(); - if(g_init_mmap_lock_offset_success) { - return 0; - } - printk_debug(KERN_EMERG "init_mmap_lock_offset maps_cnt:%d, mm->map_count:%p:%d\n", maps_cnt, &mm->map_count, (int)mm->map_count); - - g_init_mmap_lock_offset_success = true; - for (g_mmap_lock_offset = -80; g_mmap_lock_offset <= 80; g_mmap_lock_offset += 1) { - char *rp; - int val; - ssize_t accurate_offset = (ssize_t)((size_t)&mm->MM_STRUCT_MMAP_LOCK - (size_t)mm + g_mmap_lock_offset); - if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) { - mmput(mm); - return -EFAULT; - } - rp = (char*)((size_t)mm + (size_t)accurate_offset); - val = *(int*)(rp); - printk_debug(KERN_EMERG "init_mmap_lock_offset %zd:%zd:%p:%d\n", g_mmap_lock_offset, accurate_offset, rp, val); - - if (val == maps_cnt) { - printk_debug(KERN_EMERG "val == maps_cnt %zd:%zd:%p:%d\n", g_mmap_lock_offset, accurate_offset, rp, val); - g_mmap_lock_offset += sizeof(val); - g_mmap_lock_offset += sizeof(int); - is_found_mmap_lock_offset = 1; - break; - } - - } - - - if (!is_found_mmap_lock_offset) { - g_init_mmap_lock_offset_success = false; - mmput(mm); - printk_debug(KERN_INFO "find mmap_lock offset failed\n"); - return -ESPIPE; - } - mmput(mm); - printk_debug(KERN_INFO "found g_mmap_lock_offset:%zu\n", g_mmap_lock_offset); - return 0; -} - -static inline int down_read_mmap_lock(struct mm_struct *mm) { - ssize_t accurate_offset; - struct rw_semaphore *sem; - if (g_init_mmap_lock_offset_success == false) { - return -ENOENT; - } - - accurate_offset = (ssize_t)((size_t)&mm->MM_STRUCT_MMAP_LOCK - (size_t)mm + g_mmap_lock_offset); - printk_debug(KERN_INFO "down_read_mmap_lock accurate_offset:%zd\n", accurate_offset); - if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) { - return -ERANGE; - } - sem = (struct rw_semaphore *)((size_t)mm + (size_t)accurate_offset); - down_read(sem); - return 0; -} - -static inline int up_read_mmap_lock(struct mm_struct *mm) { - ssize_t accurate_offset; - struct rw_semaphore *sem; - if (g_init_mmap_lock_offset_success == false) { - return -ENOENT; - } - accurate_offset = (ssize_t)((size_t)&mm->MM_STRUCT_MMAP_LOCK - (size_t)mm + g_mmap_lock_offset); - printk_debug(KERN_INFO "accurate_offset:%zd\n", accurate_offset); - if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) { - return -ERANGE; - } - sem = (struct rw_semaphore *)((size_t)mm + (size_t)accurate_offset); - - up_read(sem); - return 0; -} - -static int init_map_count_offset(void) { - int is_found_map_count_offset = 0; - struct task_struct * mytask = x_get_current(); - struct mm_struct * mm = get_task_mm(mytask); - int maps_cnt = get_mytask_maps_cnt(); - if(g_init_map_count_offset_success) { - return 0; - } - printk_debug(KERN_EMERG "init_map_count_offset maps_cnt:%d, mm->map_count:%p:%d\n", maps_cnt, &mm->map_count, (int)mm->map_count); - - g_init_map_count_offset_success = true; - for (g_map_count_offset = -40; g_map_count_offset <= 40; g_map_count_offset += 1) { - char *rp; - int val; - ssize_t accurate_offset = (ssize_t)((size_t)&mm->map_count - (size_t)mm + g_map_count_offset); - if (accurate_offset >= sizeof(struct mm_struct) - sizeof(ssize_t)) { - mmput(mm); - return -EFAULT; - } - rp = (char*)((size_t)mm + (size_t)accurate_offset); - val = *(int*)(rp); - printk_debug(KERN_EMERG "init_map_count_offset %zd:%zd:%p:%d\n", g_map_count_offset, accurate_offset, rp, val); - - if (val == maps_cnt) { - printk_debug(KERN_EMERG "val == maps_cnt %zd:%zd:%p:%d\n", g_map_count_offset, accurate_offset, rp, val); - is_found_map_count_offset = 1; - break; - } - } - - - if (!is_found_map_count_offset) { - g_init_map_count_offset_success = false; - printk_debug(KERN_INFO "find map_count offset failed\n"); - mmput(mm); - return -ESPIPE; - } - - mmput(mm); - printk_debug(KERN_INFO "g_map_count_offset:%zu\n", g_map_count_offset); - return 0; -} - -#if MY_LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,75) -static int init_vm_file_offset(void) { - int is_found_vm_file_offset = 0; - struct vm_area_struct *vma; - struct task_struct * mytask = x_get_current(); - struct mm_struct *mm = get_task_mm(mytask); - if(g_init_vm_file_offset_success) { - return 0; - } - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -EFAULT; - } - - g_init_vm_file_offset_success = false; - { - VMA_ITERATOR(iter, mm, 0); - for_each_vma(iter, vma) { - if (is_found_vm_file_offset == 1) { - break; - } - for (g_vm_file_offset = -80; g_vm_file_offset <= 80; g_vm_file_offset += 1) { - char *rp; - size_t addr_val1; - size_t addr_val2; - unsigned long vm_pgoff; - ssize_t accurate_offset = (ssize_t)((size_t)&vma->vm_file - (size_t)vma + g_vm_file_offset); - //这里故意屏蔽,因为vm_file已经接近vm_area_struct结构体尾部了 - /*if (accurate_offset >= sizeof(struct vm_area_struct) - sizeof(struct file *)) - { - mmput(mm); - return -EFAULT; - }*/ - rp = (char*)((size_t)vma + (size_t)accurate_offset); - addr_val1 = *(size_t*)(rp); - rp += (size_t)sizeof(void*); - addr_val2 = *(size_t*)(rp); - printk_debug(KERN_EMERG "init_vm_file_offset %zd:%zd:%p:%zu\n", g_vm_file_offset, accurate_offset, rp, addr_val1); - if (addr_val1 > 0 && addr_val2 > 0 && addr_val1 == addr_val2) //struct list_head anon_vma_chain;里面两个值一样 - { - int vm_pgoff_offset = 0; - int found_vm_pgoff = 0; - - printk_debug(KERN_EMERG "init_vm_file_offset addr_val1 == addr_val2 %zd:%zd:%p:%zu\n", g_vm_file_offset, accurate_offset, rp, addr_val1); - rp += (size_t)sizeof(void*); - for (; vm_pgoff_offset < 8 * 5; vm_pgoff_offset += 4) { - vm_pgoff = *(unsigned long*)(rp); - if (vm_pgoff > 0 && vm_pgoff < 1000/*这个值是vm_pgoff我见过的最大值吧,如果最大值比1000还有大再改大*/) { - found_vm_pgoff = 1; - break; - } - rp += 4; - } - if (found_vm_pgoff) { - rp += (size_t)sizeof(unsigned long); - rp += (size_t)sizeof(struct file *); - - addr_val1 = *(size_t*)(rp); - rp += (size_t)sizeof(void*); - addr_val2 = *(size_t*)(rp); - - if (addr_val1 == 0 && addr_val2 == 0) { - g_vm_file_offset += sizeof(void*) * 2; - g_vm_file_offset += vm_pgoff_offset; - g_vm_file_offset += sizeof(unsigned long); - printk_debug(KERN_EMERG "init_vm_file_offset ok, addr_val1 == addr_val2 == 0 %zd:%d\n", g_vm_file_offset, vm_pgoff_offset); - is_found_vm_file_offset = 1; - break; - } - - } - - - } - } - } - } - - up_read_mmap_lock(mm); - mmput(mm); - - if (!is_found_vm_file_offset) { - printk_debug(KERN_INFO "find vm_file offset failed\n"); - return -ESPIPE; - } - g_init_vm_file_offset_success = true; - - return 0; -} -#else - -static int init_vm_file_offset(void) { - int is_found_vm_file_offset = 0; - struct vm_area_struct *vma; - struct task_struct * mytask = x_get_current(); - struct mm_struct *mm = get_task_mm(mytask); - if(g_init_vm_file_offset_success) { - return 0; - } - if (down_read_mmap_lock(mm) != 0) { - mmput(mm); - return -EFAULT; - } - - g_init_vm_file_offset_success = false; - for (vma = mm->mmap; vma; vma = vma->vm_next) { - if (is_found_vm_file_offset == 1) { - break; - } - for (g_vm_file_offset = -80; g_vm_file_offset <= 80; g_vm_file_offset += 1) { - char *rp; - size_t addr_val1; - size_t addr_val2; - unsigned long vm_pgoff; - ssize_t accurate_offset = (ssize_t)((size_t)&vma->vm_file - (size_t)vma + g_vm_file_offset); - //这里故意屏蔽,因为vm_file已经接近vm_area_struct结构体尾部了 - /*if (accurate_offset >= sizeof(struct vm_area_struct) - sizeof(struct file *)) - { - mmput(mm); - return -EFAULT; - }*/ - rp = (char*)((size_t)vma + (size_t)accurate_offset); - addr_val1 = *(size_t*)(rp); - rp += (size_t)sizeof(void*); - addr_val2 = *(size_t*)(rp); - printk_debug(KERN_EMERG "init_vm_file_offset %zd:%zd:%p:%zu\n", g_vm_file_offset, accurate_offset, rp, addr_val1); - if (addr_val1 > 0 && addr_val2 > 0 && addr_val1 == addr_val2) //struct list_head anon_vma_chain;里面两个值一样 - { - int vm_pgoff_offset = 0; - int found_vm_pgoff = 0; - - printk_debug(KERN_EMERG "init_vm_file_offset addr_val1 == addr_val2 %zd:%zd:%p:%zu\n", g_vm_file_offset, accurate_offset, rp, addr_val1); - rp += (size_t)sizeof(void*); - for (; vm_pgoff_offset < 8 * 5; vm_pgoff_offset += 4) { - vm_pgoff = *(unsigned long*)(rp); - if (vm_pgoff > 0 && vm_pgoff < 1000/*这个值是vm_pgoff我见过的最大值吧,如果最大值比1000还有大再改大*/) { - found_vm_pgoff = 1; - break; - } - rp += 4; - } - if (found_vm_pgoff) { - rp += (size_t)sizeof(unsigned long); - rp += (size_t)sizeof(struct file *); - - addr_val1 = *(size_t*)(rp); - rp += (size_t)sizeof(void*); - addr_val2 = *(size_t*)(rp); - - if (addr_val1 == 0 && addr_val2 == 0) { - g_vm_file_offset += sizeof(void*) * 2; - g_vm_file_offset += vm_pgoff_offset; - g_vm_file_offset += sizeof(unsigned long); - printk_debug(KERN_EMERG "init_vm_file_offset ok, addr_val1 == addr_val2 == 0 %zd:%d\n", g_vm_file_offset, vm_pgoff_offset); - is_found_vm_file_offset = 1; - break; - } - - } - - - } - } - } - - up_read_mmap_lock(mm); - mmput(mm); - - if (!is_found_vm_file_offset) { - printk_debug(KERN_INFO "find vm_file offset failed\n"); - return -ESPIPE; - } - g_init_vm_file_offset_success = true; - return 0; -} -#endif - -static inline struct file * get_vm_file(struct vm_area_struct *vma) { - struct file * vm_file; - ssize_t accurate_offset; - if (g_init_vm_file_offset_success == false) { - if (init_vm_file_offset() != 0) { - return NULL; - } - } - - accurate_offset = (ssize_t)((size_t)&vma->vm_file - (size_t)vma + g_vm_file_offset); - printk_debug(KERN_INFO "get_vm_file accurate_offset:%zd\n", accurate_offset); - //这里故意屏蔽,因为vm_file已经接近vm_area_struct结构体尾部了 - //if (accurate_offset >= sizeof(struct vm_area_struct) - sizeof(struct file *)) - //{ - // return NULL; - //} - vm_file = (struct file*) *(size_t*)((size_t)vma + (size_t)accurate_offset); - return vm_file; -} -#endif /* PROC_MAPS_AUTO_OFFSET_H_ */ \ No newline at end of file diff --git a/code/proc_root.h b/code/proc_root.h deleted file mode 100644 index dff61343..00000000 --- a/code/proc_root.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef PROC_ROOT_H_ -#define PROC_ROOT_H_ -#include -#include -#include "proc_root_auto_offset.h" -#include "ver_control.h" -//声明 -////////////////////////////////////////////////////////////////////////// -static inline int set_process_root(struct pid* proc_pid_struct); - - -//实现 -////////////////////////////////////////////////////////////////////////// -static uint64_t get_cap_ability_max(void) { - -#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0) - uint64_t cap_default = 0x3FFFFFFFFF; -#elif MY_LINUX_VERSION_CODE < KERNEL_VERSION(5,9,0) - uint64_t cap_default = 0xFFFFFFFFFF; -#else - uint64_t cap_default = 0x1FFFFFFFFFF; -#endif - - return cap_default; -} - -static inline int set_process_root(struct pid* proc_pid_struct) { - if (g_init_real_cred_offset_success == false) { - return -ENOENT; - } - - if (g_init_real_cred_offset_success) { - struct task_struct * task = NULL; - struct cred * cred = NULL; - char *pCred = NULL; - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { return -1; } - - pCred = (char*)&task->real_cred; - - pCred += g_real_cred_offset; - pCred += sizeof(void*); - cred = (struct cred *)*(size_t*)pCred; - if (cred) { - uint64_t cap = get_cap_ability_max(); - cred->uid = cred->suid = cred->euid = cred->fsuid = GLOBAL_ROOT_UID; - cred->gid = cred->sgid = cred->egid = cred->fsgid = GLOBAL_ROOT_GID; - memcpy(&cred->cap_inheritable, &cap, sizeof(cap)); - memcpy(&cred->cap_permitted, &cap, sizeof(cap)); - memcpy(&cred->cap_effective, &cap, sizeof(cap)); - memcpy(&cred->cap_bset, &cap, sizeof(cap)); - memcpy(&cred->cap_ambient, &cap, sizeof(cap)); - return 0; - } - return -EBADF; - - } - return -ESPIPE; - -} -#endif /* PROC_ROOT_H_ */ - - diff --git a/code/proc_root_auto_offset.h b/code/proc_root_auto_offset.h deleted file mode 100644 index df23a434..00000000 --- a/code/proc_root_auto_offset.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef PROC_ROOT_AUTO_OFFSET_H_ -#define PROC_ROOT_AUTO_OFFSET_H_ -#include -#include "ver_control.h" - -static ssize_t g_real_cred_offset = 0; -static bool g_init_real_cred_offset_success = false; - -static inline int init_proc_root_offset(const char* my_name) { - const ssize_t offset_lookup_min = -100; - const ssize_t offset_lookup_max = 300; - const ssize_t min_real_cred_offset_limit = offset_lookup_min + sizeof(void*) * 3; - if(g_init_real_cred_offset_success) { - return 0; - } - - g_init_real_cred_offset_success = false; - for (g_real_cred_offset = offset_lookup_min; g_real_cred_offset <= offset_lookup_max; g_real_cred_offset++) { - - char* pcomm = (char*)¤t->real_cred; - pcomm += g_real_cred_offset; - - printk_debug(KERN_EMERG "curent g_real_cred_offset:%zd, bytes:%x\n", g_real_cred_offset, *(unsigned char*)pcomm); - - if(g_real_cred_offset < min_real_cred_offset_limit) { - continue; - } - if (strcmp(pcomm, my_name) == 0) { - ssize_t maybe_real_cred_offset = g_real_cred_offset - sizeof(void*) * 2; - char * p_test_mem1 = (char*)¤t->real_cred + maybe_real_cred_offset; - char * p_test_mem2 = (char*)¤t->real_cred + maybe_real_cred_offset + sizeof(void*); // for get cred *cred; - if(memcmp(p_test_mem1, p_test_mem2, sizeof(void*)) != 0 ) { // becasuse the real_cred is equal the cred - maybe_real_cred_offset = g_real_cred_offset - sizeof(void*) * 3; - p_test_mem1 = (char*)¤t->real_cred + maybe_real_cred_offset; - p_test_mem2 = (char*)¤t->real_cred + maybe_real_cred_offset + sizeof(void*); // for get cred *cred; - if(memcmp(p_test_mem1, p_test_mem2, sizeof(void*)) != 0 ) { // becasuse the real_cred is equal the cred - break; // failed - } - } - g_real_cred_offset = maybe_real_cred_offset; - - printk_debug(KERN_EMERG "strcmp found %zd\n", g_real_cred_offset); - - g_init_real_cred_offset_success = true; - break; - } - - } - - if (!g_init_real_cred_offset_success) { - printk_debug(KERN_INFO "real_cred offset failed\n"); - return -ESPIPE; - } - printk_debug(KERN_INFO "g_real_cred_offset:%zu\n", g_real_cred_offset); - return 0; -} -#endif /* PROC_ROOT_AUTO_OFFSET_H_ */ - - diff --git a/code/proc_rss.h b/code/proc_rss.h deleted file mode 100644 index 35d6c30d..00000000 --- a/code/proc_rss.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PROC_RSS_H_ -#define PROC_RSS_H_ -//声明 -////////////////////////////////////////////////////////////////////////// -#include -#include "api_proxy.h" -#include "ver_control.h" -static size_t read_proc_rss_size(struct pid* proc_pid_struct); - -//实现 -////////////////////////////////////////////////////////////////////////// -#include "proc_cmdline_auto_offset.h" -static size_t read_proc_rss_size(struct pid* proc_pid_struct) { - struct task_struct *task; - struct mm_struct *mm; - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - return 0; - } - mm = get_task_mm(task); - if (mm) { - //精确偏移 - size_t total_rss; - ssize_t offset = g_init_arg_start_offset_success ? g_arg_start_offset : 0; - total_rss = x_read_mm_struct_rss(mm, offset); - mmput(mm); - return total_rss; - } - return 0; - -} -#endif /* PROC_RSS_H_ */ \ No newline at end of file diff --git a/code/rwProcMem_module.c b/code/rwProcMem_module.c deleted file mode 100644 index ef42d7f5..00000000 --- a/code/rwProcMem_module.c +++ /dev/null @@ -1,397 +0,0 @@ -#include "rwProcMem_module.h" - -#define MY_TASK_COMM_LEN 16 - -#pragma pack(push,1) -struct ioctl_request { - char cmd; /* 1 字节命令 */ - uint64_t param1; /* 参数1 */ - uint64_t param2; /* 参数2 */ - uint64_t param3; /* 参数3 */ - uint64_t buf_size; /* 紧随其后的动态数据长度 */ -}; -struct init_device_info { - int pid; - int tgid; - char my_name[MY_TASK_COMM_LEN + 1]; - char my_cmdline[1024]; -}; -struct arg_info { - uint64_t arg_start; - uint64_t arg_end; -}; -#pragma pack(pop) - -static ssize_t OnCmdInitDeviceInfo(struct ioctl_request *hdr, char __user* buf) { - long err = 0; - struct init_device_info* pinit_device_info = (struct init_device_info*)x_kmalloc(sizeof(struct init_device_info), GFP_KERNEL); - if (!pinit_device_info) { - return -ENOMEM; - } - printk_debug(KERN_INFO "CMD_INIT_DEVICE_INFO\n"); - memset(pinit_device_info, 0, sizeof(struct init_device_info)); - if (x_copy_from_user((void*)pinit_device_info, (void*)buf, sizeof(struct init_device_info)) == 0) { - printk_debug(KERN_INFO "my_cmdline:%s\n", pinit_device_info->my_cmdline); - printk_debug(KERN_INFO "my_name:%s\n", pinit_device_info->my_name); - printk_debug(KERN_INFO "pid:%d, tgid:%d\n", pinit_device_info->pid, pinit_device_info->tgid); - do { - err = init_mmap_lock_offset(); - if(err) { break; } - err = init_map_count_offset(); - if(err) { break; } - err = init_proc_cmdline_offset(pinit_device_info->my_cmdline, get_task_proc_cmdline_addr); - if(err) { break; } - err = init_proc_root_offset(pinit_device_info->my_name); - if(err) { break; } - err = init_task_next_offset(); - if(err) { break; } - err = init_task_pid_offset(pinit_device_info->pid, pinit_device_info->tgid); - } while(0); - } else { - err = -EINVAL; - } - kfree(pinit_device_info); - return err; -} - -static ssize_t OnCmdOpenProcess(struct ioctl_request *hdr, char __user* buf) { - uint64_t pid = hdr->param1, handle = 0; - struct pid * proc_pid_struct = NULL; - printk_debug(KERN_INFO "CMD_OPEN_PROCESS\n"); - - printk_debug(KERN_INFO "pid:%llu,size:%ld\n", pid, sizeof(pid)); - proc_pid_struct = get_proc_pid_struct(pid); - printk_debug(KERN_INFO "proc_pid_struct *:0x%p\n", (void*)proc_pid_struct); - if (!proc_pid_struct) { - return -EINVAL; - } - handle = (uint64_t)proc_pid_struct; - - printk_debug(KERN_INFO "handle:%llu,size:%ld\n", handle, sizeof(handle)); - if (!!x_copy_to_user((void*)buf, (void*)&handle, sizeof(handle))) { - return -EINVAL; - } - return 0; -} - -static ssize_t OnCmdCloseProcess(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - printk_debug(KERN_INFO "CMD_CLOSE_PROCESS\n"); - printk_debug(KERN_INFO "proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - release_proc_pid_struct(proc_pid_struct); - return 0; -} - -static ssize_t OnCmdReadProcessMemory(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - size_t proc_virt_addr = (size_t)hdr->param2; - bool is_force_read = hdr->param3 == 1 ? true : false; - size_t size = (size_t)hdr->buf_size; - size_t read_size = 0; - - printk_debug(KERN_INFO "CMD_READ_PROCESS_MEMORY\n"); - printk_debug(KERN_INFO "READ proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - printk_debug(KERN_INFO "READ proc_virt_addr:0x%zx,size:%ld\n", proc_virt_addr, sizeof(proc_virt_addr)); - if (is_force_read == false && !check_proc_map_can_read(proc_pid_struct, proc_virt_addr, size)) { - return -EFAULT; - } - while (read_size < size) { - size_t phy_addr = 0; - size_t pfn_sz = 0; - char *lpOutBuf = NULL; - pte_t *pte; - - bool old_pte_can_read; - phy_addr = get_proc_phy_addr(proc_pid_struct, proc_virt_addr + read_size, (pte_t*)&pte); - printk_debug(KERN_INFO "calc phy_addr:0x%zx\n", phy_addr); - - if (phy_addr == 0) { - break; - } - - old_pte_can_read = is_pte_can_read(pte); - if (is_force_read) { - if (!old_pte_can_read) { - if (!change_pte_read_status(pte, true)) { break; } - - } - } else if (!old_pte_can_read) { - break; - } - - pfn_sz = size_inside_page(phy_addr, ((size - read_size) > PAGE_SIZE) ? PAGE_SIZE : (size - read_size)); - printk_debug(KERN_INFO "pfn_sz:%zu\n", pfn_sz); - - - lpOutBuf = (char*)(buf + read_size); - read_ram_physical_addr(false, phy_addr, lpOutBuf, pfn_sz); - - if (is_force_read && old_pte_can_read == false) { - change_pte_read_status(pte, false); - } - read_size += pfn_sz; - } - return read_size; -} - -static ssize_t OnCmdWriteProcessMemory(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - size_t proc_virt_addr = (size_t)hdr->param2; - bool is_force_write = hdr->param3 == 1 ? true : false; - size_t size = (size_t)hdr->buf_size; - size_t write_size = 0; - printk_debug(KERN_INFO "CMD_WRITE_PROCESS_MEMORY\n"); - printk_debug(KERN_INFO "WRITE proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - printk_debug(KERN_INFO "WRITE proc_virt_addr:0x%zx,size:%ld\n", proc_virt_addr, sizeof(proc_virt_addr)); - if (is_force_write == false && !check_proc_map_can_write(proc_pid_struct, proc_virt_addr, size)) { - return -EFAULT; - } - - while (write_size < size) { - size_t phy_addr = 0; - size_t pfn_sz = 0; - char * input_buf = NULL; - - pte_t *pte; - bool old_pte_can_write; - phy_addr = get_proc_phy_addr(proc_pid_struct, proc_virt_addr + write_size, (pte_t*)&pte); - printk_debug(KERN_INFO "phy_addr:0x%zx\n", phy_addr); - if (phy_addr == 0) { - break; - } - - old_pte_can_write = is_pte_can_write(pte); - if (is_force_write) { - if (!old_pte_can_write) { - if (!change_pte_write_status(pte, true)) { break; } - } - } else if (!old_pte_can_write) { - break; - } - - pfn_sz = size_inside_page(phy_addr, ((size - write_size) > PAGE_SIZE) ? PAGE_SIZE : (size - write_size)); - printk_debug(KERN_INFO "pfn_sz:%zu\n", pfn_sz); - - input_buf = (char*)(((size_t)buf + write_size)); - write_ram_physical_addr(phy_addr, input_buf, false, pfn_sz); - - if (is_force_write && old_pte_can_write == false) { - change_pte_write_status(pte, false); - } - - write_size += pfn_sz; - } - return write_size; -} - -static ssize_t OnCmdGetProcessMapsCount(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - printk_debug(KERN_INFO "CMD_GET_PROCESS_MAPS_COUNT\n"); - printk_debug(KERN_INFO "proc_pid_struct*:0x%p, size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - return get_proc_map_count(proc_pid_struct); -} - -static ssize_t OnCmdGetProcessMapsList(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - printk_debug(KERN_INFO "CMD_GET_PROCESS_MAPS_LIST\n"); - printk_debug(KERN_INFO "proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - printk_debug(KERN_INFO "buf_size:%llu\n", hdr->buf_size); - return get_proc_maps_list(false, proc_pid_struct, (void*)(buf), hdr->buf_size - 1); -} - -static ssize_t OnCmdCheckProcessPhyAddr(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - size_t proc_virt_addr = (size_t)hdr->param2; - pte_t *pte; - printk_debug(KERN_INFO "CMD_CHECK_PROCESS_ADDR_PHY\n"); - printk_debug(KERN_INFO "proc_pid_struct *:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - printk_debug(KERN_INFO "proc_virt_addr :0x%zx\n", proc_virt_addr); - if (get_proc_phy_addr(proc_pid_struct, proc_virt_addr, (pte_t*)&pte)) { - return 1; - } - return 0; - -} - -static ssize_t OnCmdGetPidList(struct ioctl_request *hdr, char __user* buf) { - printk_debug(KERN_INFO "CMD_GET_PID_LIST\n"); - printk_debug(KERN_INFO "buf_size:%llu\n", hdr->buf_size); - return get_proc_pid_list(false, buf, hdr->buf_size); -} - -static ssize_t OnCmdSetProcessRoot(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - printk_debug(KERN_INFO "CMD_SET_PROCESS_ROOT\n"); - printk_debug(KERN_INFO "proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - return set_process_root(proc_pid_struct); -} - -static ssize_t OnCmdGetProcessRss(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - uint64_t rss = 0; - printk_debug(KERN_INFO "CMD_GET_PROCESS_RSS\n"); - printk_debug(KERN_INFO "proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - rss = read_proc_rss_size(proc_pid_struct); - if (!!x_copy_to_user((void*)buf, &rss, sizeof(rss))) { - return -EINVAL; - } - return 0; -} - -static ssize_t OnCmdGetProcessCmdlineAddr(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - size_t arg_start = 0, arg_end = 0; - int res; - struct arg_info aginfo = {0}; - printk_debug(KERN_INFO "CMD_GET_PROCESS_CMDLINE_ADDR\n"); - printk_debug(KERN_INFO "proc_pid_struct *:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - res = get_proc_cmdline_addr(proc_pid_struct, &arg_start, &arg_end); - aginfo.arg_start = (uint64_t)arg_start; - aginfo.arg_end = (uint64_t)arg_end; - if (!!x_copy_to_user((void*)buf, &aginfo, sizeof(aginfo))) { - return -EINVAL; - } - return res; -} - -static ssize_t OnCmdHideKernelModule(struct ioctl_request *hdr, char __user* buf) { - printk_debug(KERN_INFO "CMD_HIDE_KERNEL_MODULE\n"); - if (g_rwProcMem_devp->is_hidden_module == false) { - g_rwProcMem_devp->is_hidden_module = true; - list_del_init(&__this_module.list); - kobject_del(&THIS_MODULE->mkobj.kobj); - } - return 0; -} - -static inline ssize_t DispatchCommand(struct ioctl_request *hdr, char __user* buf) { - switch (hdr->cmd) { - case CMD_INIT_DEVICE_INFO: - return OnCmdInitDeviceInfo(hdr, buf); - case CMD_OPEN_PROCESS: - return OnCmdOpenProcess(hdr, buf); - case CMD_READ_PROCESS_MEMORY: - return OnCmdReadProcessMemory(hdr, buf); - case CMD_WRITE_PROCESS_MEMORY: - return OnCmdWriteProcessMemory(hdr, buf); - case CMD_CLOSE_PROCESS: - return OnCmdCloseProcess(hdr, buf); - case CMD_GET_PROCESS_MAPS_COUNT: - return OnCmdGetProcessMapsCount(hdr, buf); - case CMD_GET_PROCESS_MAPS_LIST: - return OnCmdGetProcessMapsList(hdr, buf); - case CMD_CHECK_PROCESS_ADDR_PHY: - return OnCmdCheckProcessPhyAddr(hdr, buf); - case CMD_GET_PID_LIST: - return OnCmdGetPidList(hdr, buf); - case CMD_SET_PROCESS_ROOT: - return OnCmdSetProcessRoot(hdr, buf); - case CMD_GET_PROCESS_RSS: - return OnCmdGetProcessRss(hdr, buf); - case CMD_GET_PROCESS_CMDLINE_ADDR: - return OnCmdGetProcessCmdlineAddr(hdr, buf); - case CMD_HIDE_KERNEL_MODULE: - return OnCmdHideKernelModule(hdr, buf); - default: - return -EINVAL; - } - return -EINVAL; -} - -static ssize_t rwProcMem_read(struct file* filp, - char __user* buf, - size_t size, - loff_t* ppos) { - struct ioctl_request hdr = {0}; - size_t header_size = sizeof(hdr); - if (size < header_size) { - return -EINVAL; - } - if (x_copy_from_user(&hdr, buf, header_size)) { - return -EFAULT; - } - if (size < header_size + hdr.buf_size) { - return -EINVAL; - } - return DispatchCommand(&hdr, buf + header_size); -} - -#ifdef CONFIG_MODULE_GUIDE_ENTRY -static -#endif -int __init rwProcMem_dev_init(void) { - printk(KERN_EMERG "Start init.\n"); - - g_rwProcMem_devp = x_kmalloc(sizeof(struct rwProcMemDev), GFP_KERNEL); - memset(g_rwProcMem_devp, 0, sizeof(struct rwProcMemDev)); - -#ifdef CONFIG_USE_PROC_FILE_NODE - g_rwProcMem_devp->proc_parent = proc_mkdir(CONFIG_PROC_NODE_AUTH_KEY, NULL); - if(g_rwProcMem_devp->proc_parent) { - g_rwProcMem_devp->proc_entry = proc_create(CONFIG_PROC_NODE_AUTH_KEY, S_IRUGO | S_IWUGO, g_rwProcMem_devp->proc_parent, &rwProcMem_proc_ops); - start_hide_procfs_dir(CONFIG_PROC_NODE_AUTH_KEY); - } -#endif - -#ifdef CONFIG_DEBUG_PRINTK - printk(KERN_EMERG "Hello, %s debug\n", CONFIG_PROC_NODE_AUTH_KEY); - //test1(); - //test2(); - //test3(); - //test4(); - //test5(); -#else - printk(KERN_EMERG "Hello\n"); -#endif - return 0; -} - -#ifdef CONFIG_MODULE_GUIDE_ENTRY -static -#endif -void __exit rwProcMem_dev_exit(void) { - - printk(KERN_EMERG "Start exit.\n"); - -#ifdef CONFIG_USE_PROC_FILE_NODE - if(g_rwProcMem_devp->proc_entry) { - proc_remove(g_rwProcMem_devp->proc_entry); - g_rwProcMem_devp->proc_entry = NULL; - } - - if(g_rwProcMem_devp->proc_parent) { - proc_remove(g_rwProcMem_devp->proc_parent); - g_rwProcMem_devp->proc_parent = NULL; - } - stop_hide_procfs_dir(); -#endif - kfree(g_rwProcMem_devp); - printk(KERN_EMERG "Goodbye\n"); -} - -#ifndef CONFIG_MODULE_GUIDE_ENTRY -//Hook:__cfi_check_fn -unsigned char* __check_(unsigned char* result, void *ptr, void *diag) -{ - printk_debug(KERN_EMERG "my__cfi_check_fn!!!\n"); - return result; -} - -//Hook:__cfi_check_fail -unsigned char * __check_fail_(unsigned char *result) -{ - printk_debug(KERN_EMERG "my__cfi_check_fail!!!\n"); - return result; -} -#endif - -unsigned long __stack_chk_guard; - -#ifdef CONFIG_MODULE_GUIDE_ENTRY -module_init(rwProcMem_dev_init); -module_exit(rwProcMem_dev_exit); -#endif -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Linux"); -MODULE_DESCRIPTION("Linux default module"); - diff --git a/code/rwProcMem_module.h b/code/rwProcMem_module.h deleted file mode 100644 index 4909c9ff..00000000 --- a/code/rwProcMem_module.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef RWPROCMEM_H_ -#define RWPROCMEM_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "api_proxy.h" -#include "phy_mem.h" -#include "proc_maps.h" -#include "proc_list.h" -#include "proc_root.h" -#include "proc_rss.h" -#include "proc_cmdline.h" -#include "ver_control.h" -#include "test.h" -#ifdef CONFIG_USE_PROC_FILE_NODE -#include -#include "hide_procfs_dir.h" -#endif -////////////////////////////////////////////////////////////////// - -enum { - CMD_INIT_DEVICE_INFO = 1, // 初始化设备信息 - CMD_OPEN_PROCESS, // 打开进程 - CMD_READ_PROCESS_MEMORY, // 读取进程内存 - CMD_WRITE_PROCESS_MEMORY, // 写入进程内存 - CMD_CLOSE_PROCESS, // 关闭进程 - CMD_GET_PROCESS_MAPS_COUNT, // 获取进程的内存块地址数量 - CMD_GET_PROCESS_MAPS_LIST, // 获取进程的内存块地址列表 - CMD_CHECK_PROCESS_ADDR_PHY, // 检查进程内存是否有物理内存位置 - CMD_GET_PID_LIST, // 获取进程PID列表 - CMD_SET_PROCESS_ROOT, // 提升进程权限到Root - CMD_GET_PROCESS_RSS, // 获取进程的物理内存占用大小 - CMD_GET_PROCESS_CMDLINE_ADDR, // 获取进程cmdline的内存地址 - CMD_HIDE_KERNEL_MODULE, // 隐藏驱动 -}; - -struct rwProcMemDev { -#ifdef CONFIG_USE_PROC_FILE_NODE - struct proc_dir_entry *proc_parent; - struct proc_dir_entry *proc_entry; -#endif - bool is_hidden_module; -}; -static struct rwProcMemDev *g_rwProcMem_devp; - -static ssize_t rwProcMem_read(struct file* filp, char __user* buf, size_t size, loff_t* ppos); -static const struct proc_ops rwProcMem_proc_ops = { - .proc_read = rwProcMem_read, -}; - -#endif /* RWPROCMEM_H_ */ \ No newline at end of file diff --git a/code/test.h b/code/test.h deleted file mode 100644 index 0cc9378c..00000000 --- a/code/test.h +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef TEST_H_ -#define TEST_H_ -#include "phy_mem.h" -#include "proc_maps.h" -#include "proc_list.h" -#include "proc_cmdline.h" -#include "proc_rss.h" -#include "ver_control.h" - -// -//static void test1(void) { -// size_t phy_addr; -// struct file * pFile = open_pagemap(14861); -// printk(KERN_INFO "open_pagemap %d\n", pFile); -// if (pFile) { -// phy_addr = get_pagemap_phy_addr(pFile, 0x10106000); -// printk(KERN_INFO "pagemap phy_addr 0x%llx\n", phy_addr); -// -// char buf[4]; -// size_t ret; -// memset(buf, 0, 4); -// read_ram_physical_addr(true, &ret, phy_addr, buf, 4); -// if (ret) { -// int i; -// for (i = 0; i < 4; i++) { -// printk(KERN_INFO "[%d]0x%x ", i, buf[i]); -// } -// } -// close_pagemap(pFile); -// } -//} -// -///* -//static void test2(void) -//{ -// struct pid * proc_pid_struct = get_proc_pid_struct(14861); -// int map_count = get_proc_map_count(proc_pid_struct); -// printk(KERN_INFO "map_count:%d\n", map_count); -// -// char test[8 + 8 + 4 + 4096] = { 0 }; -// get_proc_maps_list(proc_pid_struct, 4096, &test,sizeof(test), true, NULL); -// -// printk("start:0x%lx,end:0x%lx,flags:%x%x%x%x,name:%s\n", -// *(unsigned long*)&test[0], -// *(unsigned long*)&test[8], -// *(unsigned char*)&test[16], -// *(unsigned char*)&test[17], -// *(unsigned char*)&test[18], -// *(unsigned char*)&test[19], -// &test[20]); -// -// -// release_proc_pid_struct(proc_pid_struct); -// -//} -//*/ -// -//static void test3(void) { -// struct pid * proc_pid_struct = get_proc_pid_struct(14861); -// printk(KERN_INFO "test3 get_proc_pid_struct:%ld\n", proc_pid_struct); -// if (proc_pid_struct) { -// size_t phy_addr = 0; -// pte_t *pte; -// get_proc_phy_addr(&phy_addr, proc_pid_struct, 0x10106000, &pte); -// printk(KERN_INFO "calc phy_addr:0x%llx\n", phy_addr); -// -// release_proc_pid_struct(proc_pid_struct); -// } -// -//} -// -// -//static void test4(void) { -// struct pid * proc_pid_struct = get_proc_pid_struct(23948); -// printk(KERN_INFO "test4 get_proc_pid_struct:%ld\n", proc_pid_struct); -// if (proc_pid_struct) { -// size_t arg_start = 0, arg_end = 0; -// int res = get_proc_cmdline_addr(proc_pid_struct, -8, &arg_start, &arg_end); -// printk(KERN_INFO "test4 get_proc_cmdline_addr arg_start:0x%llx arg_end:0x%llx\n", arg_start, arg_end); -// -// -// int i = -32; -// for (; i <= 32; i += 4) { -// size_t accurate_offset = get_proc_cmdline_maybe_addr(proc_pid_struct, i, &arg_start); -// -// -// size_t phy_addr = get_proc_phy_addr(proc_pid_struct, arg_start); -// char name[100] = { 0 }; -// -// if (phy_addr) { -// read_ram_physical_addr_to_kernel(phy_addr, &name, sizeof(name)); -// } -// printk(KERN_INFO "test4 get_proc_cmdline_maybe_addr arg_start:0x%llx 0x%llx %s\n", arg_start, phy_addr, name); -// } -// -// -// release_proc_pid_struct(proc_pid_struct); -// } -// -//} -// -// -//static void test5(void) { -// int *pid = x_kmalloc(sizeof(int) * 100, GFP_KERNEL); -// int i = 0; -// int count = get_proc_pid_list(true, (char*)pid, sizeof(int) * 100); -// printk(KERN_INFO "test5 count:%d\n", count); -// -// for (i = 0; i < 100; i++) { -// if (!!pid[i]) { -// printk(KERN_INFO "test5 pid[%d]:%d\n", i, pid[i]); -// } -// } -// -// -// kfree(pid); -// -//} -// -//static void test6(void) { -// int ret = 0; -// struct pid * proc_pid_struct = get_proc_pid_struct(17597); -// -// printk(KERN_INFO "test6 get_proc_pid_struct:%ld\n", proc_pid_struct); -// -// ret = set_process_root(proc_pid_struct); -// -// printk(KERN_INFO "test6 ret:%d\n", ret); -// -// release_proc_pid_struct(proc_pid_struct); -// -//} -// -//static void test7(void) { -// struct pid * proc_pid_struct = get_proc_pid_struct(11533); -// size_t ret = read_proc_rss_size(proc_pid_struct); -// -// printk(KERN_INFO "test7 get_proc_pid_struct:%ld, ret:%zu\n", proc_pid_struct, ret); -// -// release_proc_pid_struct(proc_pid_struct); -// -//} -// -//static void test8(void) { -// struct pid * proc_pid_struct = get_proc_pid_struct(17597); -// printk(KERN_INFO "test8 get_proc_pid_struct:%ld\n", proc_pid_struct); -// if (proc_pid_struct) { -// size_t arg_start = 0, arg_end = 0; -// int res = get_proc_cmdline_addr(proc_pid_struct, &arg_start, &arg_end); -// printk(KERN_INFO "test8 get_proc_cmdline_addr arg_start:0x%llx arg_end:0x%llx\n", arg_start, arg_end); -// release_proc_pid_struct(proc_pid_struct); -// } -// -//} -// -//static void test9(void) { -// struct pid * proc_pid_struct = get_proc_pid_struct(14861); -// printk(KERN_INFO "test9 get_proc_pid_struct:%ld\n", proc_pid_struct); -// if (proc_pid_struct) { -// -// //set_process_root(proc_pid_struct); -// -// release_proc_pid_struct(proc_pid_struct); -// } -// -//} - -#endif /* TEST_H_ */ \ No newline at end of file diff --git a/code/ver_control.h b/code/ver_control.h deleted file mode 100644 index c6cc986d..00000000 --- a/code/ver_control.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef VERSION_CONTROL_H_ -#define VERSION_CONTROL_H_ - -// 独立内核模块入口模式 -#define CONFIG_MODULE_GUIDE_ENTRY - -// 生成proc用户层交互节点文件 -#define CONFIG_USE_PROC_FILE_NODE -// 隐蔽通信密钥 -#define CONFIG_PROC_NODE_AUTH_KEY "c2a2b5792edd296763fdfc72cff44380" - -// 打印内核调试信息 -//#define CONFIG_DEBUG_PRINTK - -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif -#ifndef MY_LINUX_VERSION_CODE -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,10,0) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,10,84) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,18,71) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,18,140) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,21) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,78) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,153) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,192) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,9,112) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,9,186) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,83) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,117) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,141) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,19,81) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,19,113) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,4,61) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,10,43) -#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,15,41) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,1,75) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,6,30) -#endif - -#ifdef CONFIG_DEBUG_PRINTK -#define printk_debug printk -#else -static inline void printk_debug(char *fmt, ...) {} -#endif - -#endif /* VERSION_CONTROL_H_ */ From 2408db68aad00487e1722e3b0d16a16c809c56a6 Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Sun, 18 Jan 2026 13:26:16 +0800 Subject: [PATCH 03/35] Add object file definition in Makefile --- code/Makefile | 1 + 1 file changed, 1 insertion(+) create mode 100644 code/Makefile diff --git a/code/Makefile b/code/Makefile new file mode 100644 index 00000000..058991ca --- /dev/null +++ b/code/Makefile @@ -0,0 +1 @@ +obj += aurora.o From a458a1f8c7d683a9bb9d36402a534101acf36004 Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Sun, 18 Jan 2026 13:28:25 +0800 Subject: [PATCH 04/35] Create aurora.h --- code/aurora.h | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 code/aurora.h diff --git a/code/aurora.h b/code/aurora.h new file mode 100644 index 00000000..e3ccfb27 --- /dev/null +++ b/code/aurora.h @@ -0,0 +1,8 @@ +// 简化版本,只保留基本框架 +#include +#include +#include +#include +#include + +#define DEVICE_NAME "aKVM" From 54772d06cfd5a2241e424d7fe6d6472c75fa0ea8 Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Sun, 18 Jan 2026 13:29:11 +0800 Subject: [PATCH 05/35] Add misc device driver with open, close, and ioctl Implement basic file operations for a misc device. --- code/aurora.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 code/aurora.c diff --git a/code/aurora.c b/code/aurora.c new file mode 100644 index 00000000..88e6880d --- /dev/null +++ b/code/aurora.c @@ -0,0 +1,53 @@ +#include "aurora.h" + +int dispatch_open(struct inode *node, struct file *file) +{ + printk(KERN_INFO "Device opened\n"); + return 0; +} + +int dispatch_close(struct inode *node, struct file *file) +{ + printk(KERN_INFO "Device closed\n"); + return 0; +} + +long dispatch_ioctl(struct file *const file, unsigned int const cmd, unsigned long const arg) +{ + printk(KERN_INFO "IOCTL called: %u\n", cmd); + return 0; +} + +struct file_operations dispatch_functions = { + .owner = THIS_MODULE, + .open = dispatch_open, + .release = dispatch_close, + .unlocked_ioctl = dispatch_ioctl, +}; + +struct miscdevice misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = DEVICE_NAME, + .fops = &dispatch_functions, +}; + +int __init driver_entry(void) +{ + int ret; + printk(KERN_INFO "[+] driver_entry\n"); + ret = misc_register(&misc); + return ret; +} + +void __exit driver_unload(void) +{ + printk(KERN_INFO "[+] driver_unload\n"); + misc_deregister(&misc); +} + +module_init(driver_entry); +module_exit(driver_unload); + +MODULE_DESCRIPTION("Linux Kernel."); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("JiangNight"); From acd20c53fb9f0e3396f41f93ce1d6f3e44ebea17 Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Sun, 18 Jan 2026 14:08:06 +0800 Subject: [PATCH 06/35] Update Makefile --- code/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Makefile b/code/Makefile index 058991ca..f5d1305e 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1 +1 @@ -obj += aurora.o +obj-m += aurora.o From 3e57f600685b01eb0fd8b9b838f4eee4ecad024f Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Sun, 18 Jan 2026 16:55:05 +0800 Subject: [PATCH 07/35] Enhance aurora.h with new includes and device name Added additional includes and updated device name. --- code/aurora.h | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/code/aurora.h b/code/aurora.h index e3ccfb27..e35169bd 100644 --- a/code/aurora.h +++ b/code/aurora.h @@ -1,8 +1,33 @@ -// 简化版本,只保留基本框架 #include +#include #include +#include +#include +#include #include +#include #include #include +#include +#include +#include +#include +#include -#define DEVICE_NAME "aKVM" +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) +#include +#include +#else +#include +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) +#include +#include +#endif + +#define DEVICE_NAME "YihanChan" From 3a30e2bf65e7902cb5cc940066866f673d81e1a8 Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Sun, 18 Jan 2026 16:56:37 +0800 Subject: [PATCH 08/35] Update aurora.c --- code/aurora.c | 395 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 367 insertions(+), 28 deletions(-) diff --git a/code/aurora.c b/code/aurora.c index 88e6880d..a1134cc7 100644 --- a/code/aurora.c +++ b/code/aurora.c @@ -1,53 +1,392 @@ #include "aurora.h" -int dispatch_open(struct inode *node, struct file *file) + +typedef struct _COPY_MEMORY { + pid_t pid; + uintptr_t addr; + void __user *buffer; + size_t size; +} COPY_MEMORY, *PCOPY_MEMORY; + +typedef struct _MODULE_BASE { + pid_t pid; + char __user *name; + uintptr_t base; +} MODULE_BASE, *PMODULE_BASE; + +enum OPERATIONS { + OP_INIT_KEY = 0x800, + OP_READ_MEM = 0x801, + OP_WRITE_MEM = 0x802, + OP_MODULE_BASE = 0x803, +}; + +static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va); +static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size); +static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size); +static bool read_process_memory(pid_t pid, uintptr_t addr, void __user *buffer, size_t size); +static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user *buffer, size_t size); +static uintptr_t get_module_base(pid_t pid, const char *name); + +static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + pud_t *pud; + phys_addr_t page_addr; + uintptr_t page_offset; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 61) + p4d_t *p4d; + + pgd = pgd_offset(mm, va); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return 0; + + p4d = p4d_offset(pgd, va); + if (p4d_none(*p4d) || p4d_bad(*p4d)) + return 0; + + pud = pud_offset(p4d, va); +#else + pgd = pgd_offset(mm, va); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return 0; + + pud = pud_offset(pgd, va); +#endif + + if (pud_none(*pud) || pud_bad(*pud)) + return 0; + + pmd = pmd_offset(pud, va); + if (pmd_none(*pmd)) + return 0; + + pte = pte_offset_kernel(pmd, va); + if (pte_none(*pte) || !pte_present(*pte)) + return 0; + + page_addr = (phys_addr_t)(pte_pfn(*pte) << PAGE_SHIFT); + page_offset = va & (PAGE_SIZE - 1); + + return page_addr + page_offset; +} + +// 替换 valid_phys_addr_range 的替代实现 +static inline bool is_valid_phys_addr_range(phys_addr_t addr, size_t size) +{ + // 简单的检查:确保地址在物理内存范围内 + // 对于ARM64架构,high_memory包含了高地址内存信息 + return (addr + size <= virt_to_phys(high_memory)); +} + +static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size) { - printk(KERN_INFO "Device opened\n"); - return 0; + void *mapped; + + if (!pfn_valid(__phys_to_pfn(pa))) + return false; + + // 使用替代函数检查物理地址范围 + if (!is_valid_phys_addr_range(pa, size)) + return false; + + mapped = ioremap_cache(pa, size); + if (!mapped) + return false; + + if (copy_to_user(buffer, mapped, size)) { + iounmap(mapped); + return false; + } + + iounmap(mapped); + return true; } -int dispatch_close(struct inode *node, struct file *file) +static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size) { - printk(KERN_INFO "Device closed\n"); - return 0; + void *mapped; + + if (!pfn_valid(__phys_to_pfn(pa))) + return false; + + // 使用替代函数检查物理地址范围 + if (!is_valid_phys_addr_range(pa, size)) + return false; + + mapped = ioremap_cache(pa, size); + if (!mapped) + return false; + + if (copy_from_user(mapped, buffer, size)) { + iounmap(mapped); + return false; + } + + iounmap(mapped); + return true; +} + +static bool read_process_memory(pid_t pid, uintptr_t addr, + void __user *buffer, size_t size) +{ + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + phys_addr_t pa; + bool result = false; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return false; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return false; + } + + mm = get_task_mm(task); + put_pid(pid_struct); + + if (!mm) { + put_task_struct(task); + return false; + } + + pa = translate_linear_address(mm, addr); + if (pa) { + result = read_physical_address(pa, buffer, size); + } else { + struct vm_area_struct *vma = find_vma(mm, addr); + if (vma) { + if (clear_user(buffer, size) == 0) { + result = true; + } + } + } + + mmput(mm); + put_task_struct(task); + return result; } -long dispatch_ioctl(struct file *const file, unsigned int const cmd, unsigned long const arg) +static bool write_process_memory(pid_t pid, uintptr_t addr, + const void __user *buffer, size_t size) { - printk(KERN_INFO "IOCTL called: %u\n", cmd); - return 0; + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + phys_addr_t pa; + bool result = false; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return false; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return false; + } + + mm = get_task_mm(task); + put_pid(pid_struct); + + if (!mm) { + put_task_struct(task); + return false; + } + + pa = translate_linear_address(mm, addr); + if (pa) { + result = write_physical_address(pa, buffer, size); + } + + mmput(mm); + put_task_struct(task); + return result; +} + +#define ARC_PATH_MAX 256 + +static uintptr_t get_module_base(pid_t pid, const char *name) +{ + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + struct vm_area_struct *vma = NULL; + uintptr_t base_addr = 0; + int path_len; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return 0; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return 0; + } + + mm = get_task_mm(task); + put_pid(pid_struct); + + if (!mm) { + put_task_struct(task); + return 0; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) + struct vma_iterator vmi; + vma_iter_init(&vmi, mm, 0); + for_each_vma(vmi, vma) { +#else + for (vma = mm->mmap; vma; vma = vma->vm_next) { +#endif + char buf[ARC_PATH_MAX]; + char *path_nm; + + if (!vma->vm_file) + continue; + + path_nm = file_path(vma->vm_file, buf, ARC_PATH_MAX - 1); + if (IS_ERR(path_nm)) + continue; + + path_len = strlen(path_nm); + if (path_len <= 0) + continue; + + if (strstr(path_nm, name) != NULL) { + base_addr = vma->vm_start; + break; + } + } + + mmput(mm); + put_task_struct(task); + return base_addr; +} + +static int dispatch_open(struct inode *node, struct file *file) +{ + return 0; +} + +static int dispatch_close(struct inode *node, struct file *file) +{ + return 0; +} + +static long dispatch_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + static char key[256] = {0}; + static bool is_verified = false; + + switch (cmd) { + case OP_INIT_KEY: + if (!is_verified) { + if (copy_from_user(key, (void __user *)arg, sizeof(key) - 1) == 0) { + key[sizeof(key) - 1] = '\0'; + is_verified = true; + } else { + return -EFAULT; + } + } + break; + + case OP_READ_MEM: { + COPY_MEMORY cm; + + if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) + return -EFAULT; + + if (!read_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) + return -EIO; + + break; + } + + case OP_WRITE_MEM: { + COPY_MEMORY cm; + + if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) + return -EFAULT; + + if (!write_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) + return -EIO; + + break; + } + + case OP_MODULE_BASE: { + MODULE_BASE mb; + char module_name[256]; + + if (copy_from_user(&mb, (void __user *)arg, sizeof(mb))) + return -EFAULT; + + if (!mb.name) + return -EFAULT; + + if (copy_from_user(module_name, mb.name, sizeof(module_name) - 1)) + return -EFAULT; + module_name[sizeof(module_name) - 1] = '\0'; + + mb.base = get_module_base(mb.pid, module_name); + + if (copy_to_user((void __user *)arg, &mb, sizeof(mb))) + return -EFAULT; + + break; + } + + default: + return -ENOTTY; + } + + return 0; } -struct file_operations dispatch_functions = { - .owner = THIS_MODULE, - .open = dispatch_open, - .release = dispatch_close, - .unlocked_ioctl = dispatch_ioctl, +static const struct file_operations dispatch_fops = { + .owner = THIS_MODULE, + .open = dispatch_open, + .release = dispatch_close, + .unlocked_ioctl = dispatch_ioctl, + .compat_ioctl = dispatch_ioctl, }; -struct miscdevice misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = DEVICE_NAME, - .fops = &dispatch_functions, +static struct miscdevice misc_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = DEVICE_NAME, + .fops = &dispatch_fops, + .mode = 0666, }; -int __init driver_entry(void) +static int __init driver_entry(void) { - int ret; - printk(KERN_INFO "[+] driver_entry\n"); - ret = misc_register(&misc); - return ret; + int ret; + + ret = misc_register(&misc_dev); + if (ret) + return ret; + + return 0; } -void __exit driver_unload(void) +static void __exit driver_unload(void) { - printk(KERN_INFO "[+] driver_unload\n"); - misc_deregister(&misc); + misc_deregister(&misc_dev); } module_init(driver_entry); module_exit(driver_unload); -MODULE_DESCRIPTION("Linux Kernel."); +MODULE_DESCRIPTION("Linux Kernel Module"); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("JiangNight"); +MODULE_AUTHOR("YihanChan"); +MODULE_VERSION("1.0"); From 742a5ba766f969288c99db852e7a307873cb3c5f Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:23:27 +0800 Subject: [PATCH 09/35] Add files via upload --- code/aurora.c | 268 ++++++++++++++++++++++++++++++++++++-------------- code/aurora.h | 11 +++ 2 files changed, 204 insertions(+), 75 deletions(-) diff --git a/code/aurora.c b/code/aurora.c index a1134cc7..267cbddc 100644 --- a/code/aurora.c +++ b/code/aurora.c @@ -1,59 +1,156 @@ #include "aurora.h" - typedef struct _COPY_MEMORY { pid_t pid; uintptr_t addr; - void __user *buffer; + void __user* buffer; size_t size; -} COPY_MEMORY, *PCOPY_MEMORY; +} COPY_MEMORY, * PCOPY_MEMORY; typedef struct _MODULE_BASE { pid_t pid; - char __user *name; + char __user* name; uintptr_t base; -} MODULE_BASE, *PMODULE_BASE; +} MODULE_BASE, * PMODULE_BASE; + +typedef struct _CALL_PROCESS { + pid_t pid; + uintptr_t addr; + void __user* params; + void __user* RetValue; + size_t ParamsSize; +} CALL_PROCESS, * PCALL_PROCESS; enum OPERATIONS { OP_INIT_KEY = 0x800, OP_READ_MEM = 0x801, OP_WRITE_MEM = 0x802, OP_MODULE_BASE = 0x803, + OP_CALL_PROCESS = 0x804, }; -static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va); -static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size); -static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size); -static bool read_process_memory(pid_t pid, uintptr_t addr, void __user *buffer, size_t size); -static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user *buffer, size_t size); -static uintptr_t get_module_base(pid_t pid, const char *name); +static phys_addr_t translate_linear_address(struct mm_struct* mm, uintptr_t va); +static bool read_physical_address(phys_addr_t pa, void __user* buffer, size_t size); +static bool write_physical_address(phys_addr_t pa, const void __user* buffer, size_t size); +static bool read_process_memory(pid_t pid, uintptr_t addr, void __user* buffer, size_t size); +static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user* buffer, size_t size); +static uintptr_t get_module_base(pid_t pid, const char* name); +static void call_process_code(pid_t pid, uintptr_t addr, void __user* params, void __user* RetValue, size_t ParamsSize); //CALL_PROCESS + + +static void modify_task_registers(struct task_struct* task, uintptr_t addr, void __user* params, void __user* RetValue, size_t ParamsSize) { + //这是一个基于ARM64架构的修改程序寄存器的函数,先备份寄存器状态,然后修改寄存器状态让其执行目标函数,执行完后取返回值 + //注意:该函数可能会引起系统不稳定,请谨慎使用 + struct pt_regs* regs; + // 获取任务的寄存器状态 + regs = task_pt_regs(task); + if (!regs) + return; + // 备份原始寄存器状态(使用 memcpy 而不是直接初始化,兼容性更好) + struct pt_regs original_regs; + memcpy(&original_regs, regs, sizeof(original_regs)); + // 设置目标函数地址 + regs->pc = addr; + // 设置参数(假设最多传递4个参数) + if (ParamsSize >= sizeof(uintptr_t)) { + uintptr_t param1; + if (copy_from_user(¶m1, params, sizeof(uintptr_t)) == 0) { + regs->regs[0] = param1; + } + } + if (ParamsSize >= 2 * sizeof(uintptr_t)) { + uintptr_t param2; + if (copy_from_user(¶m2, params + sizeof(uintptr_t), sizeof(uintptr_t)) == 0) { + regs->regs[1] = param2; + } + } + if (ParamsSize >= 3 * sizeof(uintptr_t)) { + uintptr_t param3; + if (copy_from_user(¶m3, params + 2 * sizeof(uintptr_t), sizeof(uintptr_t)) == 0) { + regs->regs[2] = param3; + } + } + if (ParamsSize >= 4 * sizeof(uintptr_t)) { + uintptr_t param4; + if (copy_from_user(¶m4, params + 3 * sizeof(uintptr_t), sizeof(uintptr_t)) == 0) { + regs->regs[3] = param4; + } + } + // 让任务执行目标函数(使用 wake_up_process,避免依赖可能不存在的 set_task_state 符号) + wake_up_process(task); + // 等待任务执行完毕代码 + // 简化实现:短轮询带超时,等待寄存器 PC 离开目标地址(表示指令流已向前推进),或超时后继续。 + // 说明:这是不完美的方案;更可靠的方法需要进程内配合(设置完成标志、信号或者使用 ptrace/single-step)。 + { + const int max_wait_ms = 100; // 最大等待时间:100 ms + const int poll_interval_ms = 1; // 轮询间隔:1 ms + int waited = 0; + + // 如果 regs 指向的结构在唤醒后仍然有效,则检查 pc 是否已改变 + while (waited < max_wait_ms) { + // 如果 pc 已不再等于我们设置的 addr,认为目标函数已开始执行或已返回 + if (regs->pc != addr) + break; + msleep(poll_interval_ms); + waited += poll_interval_ms; + } + } + + // 获取返回值 + if (RetValue) { + uintptr_t ret_val = regs->regs[0]; + copy_to_user(RetValue, &ret_val, sizeof(uintptr_t)); + } + // 恢复原始寄存器状态 + memcpy(regs, &original_regs, sizeof(original_regs)); +} -static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va) +static void call_process_code(pid_t pid, uintptr_t addr, void __user* params, void __user* RetValue, size_t ParamsSize) { + //这是一个Call函数 + //函数原理是修改先备份主线程的寄存器状态,然后修改寄存器状态让其执行目标函数,函数执行完毕后恢复寄存器状态 + //注意:该函数可能会引起系统不稳定,请谨慎使用 + struct task_struct* task = NULL; + struct pid* pid_struct = NULL; + pid_struct = find_get_pid(pid); + if (!pid_struct) + return; + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return; + } + /* 保持对 task 的引用直到调用完成,避免 use-after-free */ + modify_task_registers(task, addr, params, RetValue, ParamsSize); + put_task_struct(task); + put_pid(pid_struct); +} + +static phys_addr_t translate_linear_address(struct mm_struct* mm, uintptr_t va) { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - pud_t *pud; + pgd_t* pgd; + pmd_t* pmd; + pte_t* pte; + pud_t* pud; phys_addr_t page_addr; uintptr_t page_offset; #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 61) - p4d_t *p4d; - + p4d_t* p4d; + pgd = pgd_offset(mm, va); if (pgd_none(*pgd) || pgd_bad(*pgd)) return 0; - + p4d = p4d_offset(pgd, va); if (p4d_none(*p4d) || p4d_bad(*p4d)) return 0; - + pud = pud_offset(p4d, va); #else pgd = pgd_offset(mm, va); if (pgd_none(*pgd) || pgd_bad(*pgd)) return 0; - + pud = pud_offset(pgd, va); #endif @@ -82,13 +179,13 @@ static inline bool is_valid_phys_addr_range(phys_addr_t addr, size_t size) return (addr + size <= virt_to_phys(high_memory)); } -static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size) +static bool read_physical_address(phys_addr_t pa, void __user* buffer, size_t size) { - void *mapped; + void* mapped; if (!pfn_valid(__phys_to_pfn(pa))) return false; - + // 使用替代函数检查物理地址范围 if (!is_valid_phys_addr_range(pa, size)) return false; @@ -106,13 +203,13 @@ static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t si return true; } -static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size) +static bool write_physical_address(phys_addr_t pa, const void __user* buffer, size_t size) { - void *mapped; + void* mapped; if (!pfn_valid(__phys_to_pfn(pa))) return false; - + // 使用替代函数检查物理地址范围 if (!is_valid_phys_addr_range(pa, size)) return false; @@ -130,12 +227,12 @@ static bool write_physical_address(phys_addr_t pa, const void __user *buffer, si return true; } -static bool read_process_memory(pid_t pid, uintptr_t addr, - void __user *buffer, size_t size) +static bool read_process_memory(pid_t pid, uintptr_t addr, + void __user* buffer, size_t size) { - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; + struct task_struct* task = NULL; + struct mm_struct* mm = NULL; + struct pid* pid_struct = NULL; phys_addr_t pa; bool result = false; @@ -151,7 +248,7 @@ static bool read_process_memory(pid_t pid, uintptr_t addr, mm = get_task_mm(task); put_pid(pid_struct); - + if (!mm) { put_task_struct(task); return false; @@ -160,8 +257,9 @@ static bool read_process_memory(pid_t pid, uintptr_t addr, pa = translate_linear_address(mm, addr); if (pa) { result = read_physical_address(pa, buffer, size); - } else { - struct vm_area_struct *vma = find_vma(mm, addr); + } + else { + struct vm_area_struct* vma = find_vma(mm, addr); if (vma) { if (clear_user(buffer, size) == 0) { result = true; @@ -174,12 +272,12 @@ static bool read_process_memory(pid_t pid, uintptr_t addr, return result; } -static bool write_process_memory(pid_t pid, uintptr_t addr, - const void __user *buffer, size_t size) +static bool write_process_memory(pid_t pid, uintptr_t addr, + const void __user* buffer, size_t size) { - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; + struct task_struct* task = NULL; + struct mm_struct* mm = NULL; + struct pid* pid_struct = NULL; phys_addr_t pa; bool result = false; @@ -195,7 +293,7 @@ static bool write_process_memory(pid_t pid, uintptr_t addr, mm = get_task_mm(task); put_pid(pid_struct); - + if (!mm) { put_task_struct(task); return false; @@ -213,12 +311,12 @@ static bool write_process_memory(pid_t pid, uintptr_t addr, #define ARC_PATH_MAX 256 -static uintptr_t get_module_base(pid_t pid, const char *name) +static uintptr_t get_module_base(pid_t pid, const char* name) { - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - struct vm_area_struct *vma = NULL; + struct task_struct* task = NULL; + struct mm_struct* mm = NULL; + struct pid* pid_struct = NULL; + struct vm_area_struct* vma = NULL; uintptr_t base_addr = 0; int path_len; @@ -234,7 +332,7 @@ static uintptr_t get_module_base(pid_t pid, const char *name) mm = get_task_mm(task); put_pid(pid_struct); - + if (!mm) { put_task_struct(task); return 0; @@ -248,7 +346,7 @@ static uintptr_t get_module_base(pid_t pid, const char *name) for (vma = mm->mmap; vma; vma = vma->vm_next) { #endif char buf[ARC_PATH_MAX]; - char *path_nm; + char* path_nm; if (!vma->vm_file) continue; @@ -270,30 +368,31 @@ static uintptr_t get_module_base(pid_t pid, const char *name) mmput(mm); put_task_struct(task); return base_addr; -} + } -static int dispatch_open(struct inode *node, struct file *file) +static int dispatch_open(struct inode* node, struct file* file) { return 0; } -static int dispatch_close(struct inode *node, struct file *file) +static int dispatch_close(struct inode* node, struct file* file) { return 0; } -static long dispatch_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long dispatch_ioctl(struct file* file, unsigned int cmd, unsigned long arg) { - static char key[256] = {0}; + static char key[256] = { 0 }; static bool is_verified = false; switch (cmd) { case OP_INIT_KEY: if (!is_verified) { - if (copy_from_user(key, (void __user *)arg, sizeof(key) - 1) == 0) { + if (copy_from_user(key, (void __user*)arg, sizeof(key) - 1) == 0) { key[sizeof(key) - 1] = '\0'; is_verified = true; - } else { + } + else { return -EFAULT; } } @@ -301,50 +400,69 @@ static long dispatch_ioctl(struct file *file, unsigned int cmd, unsigned long ar case OP_READ_MEM: { COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) + + if (copy_from_user(&cm, (void __user*)arg, sizeof(cm))) return -EFAULT; - + if (!read_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) return -EIO; - + break; } case OP_WRITE_MEM: { COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) + + if (copy_from_user(&cm, (void __user*)arg, sizeof(cm))) return -EFAULT; - + if (!write_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) return -EIO; - + break; } case OP_MODULE_BASE: { MODULE_BASE mb; char module_name[256]; - - if (copy_from_user(&mb, (void __user *)arg, sizeof(mb))) + + if (copy_from_user(&mb, (void __user*)arg, sizeof(mb))) return -EFAULT; - + if (!mb.name) return -EFAULT; - + if (copy_from_user(module_name, mb.name, sizeof(module_name) - 1)) return -EFAULT; module_name[sizeof(module_name) - 1] = '\0'; - + mb.base = get_module_base(mb.pid, module_name); - - if (copy_to_user((void __user *)arg, &mb, sizeof(mb))) + + if (copy_to_user((void __user*)arg, &mb, sizeof(mb))) return -EFAULT; - + break; } + case OP_CALL_PROCESS: { + CALL_PROCESS cp; + + if (copy_from_user(&cp, (void __user*)arg, sizeof(cp))) + return -EFAULT; + + if (!cp.addr) + return -EFAULT; + + if (cp.params) + return -EFAULT; + + if (cp.ParamsSize < 1) + return -EFAULT; + + call_process_code(cp.pid, cp.addr, cp.params, cp.RetValue, cp.ParamsSize); + + break; + } default: return -ENOTTY; } @@ -364,17 +482,17 @@ static struct miscdevice misc_dev = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dispatch_fops, - .mode = 0666, + .mode = 0777, }; static int __init driver_entry(void) { int ret; - + ret = misc_register(&misc_dev); if (ret) return ret; - + return 0; } @@ -389,4 +507,4 @@ module_exit(driver_unload); MODULE_DESCRIPTION("Linux Kernel Module"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("YihanChan"); -MODULE_VERSION("1.0"); +MODULE_VERSION("1.0"); \ No newline at end of file diff --git a/code/aurora.h b/code/aurora.h index e35169bd..ab01f6dc 100644 --- a/code/aurora.h +++ b/code/aurora.h @@ -14,6 +14,17 @@ #include #include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include #include #include #include From 66a7aaeec493857236f37494921cd83d3976f3c7 Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Fri, 23 Jan 2026 16:15:29 +0800 Subject: [PATCH 10/35] Add files via upload --- code/aurora.c | 268 ++++++++++++++------------------------------------ code/aurora.h | 11 --- 2 files changed, 75 insertions(+), 204 deletions(-) diff --git a/code/aurora.c b/code/aurora.c index 267cbddc..a1134cc7 100644 --- a/code/aurora.c +++ b/code/aurora.c @@ -1,156 +1,59 @@ #include "aurora.h" + typedef struct _COPY_MEMORY { pid_t pid; uintptr_t addr; - void __user* buffer; + void __user *buffer; size_t size; -} COPY_MEMORY, * PCOPY_MEMORY; +} COPY_MEMORY, *PCOPY_MEMORY; typedef struct _MODULE_BASE { pid_t pid; - char __user* name; + char __user *name; uintptr_t base; -} MODULE_BASE, * PMODULE_BASE; - -typedef struct _CALL_PROCESS { - pid_t pid; - uintptr_t addr; - void __user* params; - void __user* RetValue; - size_t ParamsSize; -} CALL_PROCESS, * PCALL_PROCESS; +} MODULE_BASE, *PMODULE_BASE; enum OPERATIONS { OP_INIT_KEY = 0x800, OP_READ_MEM = 0x801, OP_WRITE_MEM = 0x802, OP_MODULE_BASE = 0x803, - OP_CALL_PROCESS = 0x804, }; -static phys_addr_t translate_linear_address(struct mm_struct* mm, uintptr_t va); -static bool read_physical_address(phys_addr_t pa, void __user* buffer, size_t size); -static bool write_physical_address(phys_addr_t pa, const void __user* buffer, size_t size); -static bool read_process_memory(pid_t pid, uintptr_t addr, void __user* buffer, size_t size); -static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user* buffer, size_t size); -static uintptr_t get_module_base(pid_t pid, const char* name); -static void call_process_code(pid_t pid, uintptr_t addr, void __user* params, void __user* RetValue, size_t ParamsSize); //CALL_PROCESS - - -static void modify_task_registers(struct task_struct* task, uintptr_t addr, void __user* params, void __user* RetValue, size_t ParamsSize) { - //这是一个基于ARM64架构的修改程序寄存器的函数,先备份寄存器状态,然后修改寄存器状态让其执行目标函数,执行完后取返回值 - //注意:该函数可能会引起系统不稳定,请谨慎使用 - struct pt_regs* regs; - // 获取任务的寄存器状态 - regs = task_pt_regs(task); - if (!regs) - return; - // 备份原始寄存器状态(使用 memcpy 而不是直接初始化,兼容性更好) - struct pt_regs original_regs; - memcpy(&original_regs, regs, sizeof(original_regs)); - // 设置目标函数地址 - regs->pc = addr; - // 设置参数(假设最多传递4个参数) - if (ParamsSize >= sizeof(uintptr_t)) { - uintptr_t param1; - if (copy_from_user(¶m1, params, sizeof(uintptr_t)) == 0) { - regs->regs[0] = param1; - } - } - if (ParamsSize >= 2 * sizeof(uintptr_t)) { - uintptr_t param2; - if (copy_from_user(¶m2, params + sizeof(uintptr_t), sizeof(uintptr_t)) == 0) { - regs->regs[1] = param2; - } - } - if (ParamsSize >= 3 * sizeof(uintptr_t)) { - uintptr_t param3; - if (copy_from_user(¶m3, params + 2 * sizeof(uintptr_t), sizeof(uintptr_t)) == 0) { - regs->regs[2] = param3; - } - } - if (ParamsSize >= 4 * sizeof(uintptr_t)) { - uintptr_t param4; - if (copy_from_user(¶m4, params + 3 * sizeof(uintptr_t), sizeof(uintptr_t)) == 0) { - regs->regs[3] = param4; - } - } - // 让任务执行目标函数(使用 wake_up_process,避免依赖可能不存在的 set_task_state 符号) - wake_up_process(task); - // 等待任务执行完毕代码 - // 简化实现:短轮询带超时,等待寄存器 PC 离开目标地址(表示指令流已向前推进),或超时后继续。 - // 说明:这是不完美的方案;更可靠的方法需要进程内配合(设置完成标志、信号或者使用 ptrace/single-step)。 - { - const int max_wait_ms = 100; // 最大等待时间:100 ms - const int poll_interval_ms = 1; // 轮询间隔:1 ms - int waited = 0; - - // 如果 regs 指向的结构在唤醒后仍然有效,则检查 pc 是否已改变 - while (waited < max_wait_ms) { - // 如果 pc 已不再等于我们设置的 addr,认为目标函数已开始执行或已返回 - if (regs->pc != addr) - break; - msleep(poll_interval_ms); - waited += poll_interval_ms; - } - } - - // 获取返回值 - if (RetValue) { - uintptr_t ret_val = regs->regs[0]; - copy_to_user(RetValue, &ret_val, sizeof(uintptr_t)); - } - // 恢复原始寄存器状态 - memcpy(regs, &original_regs, sizeof(original_regs)); -} +static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va); +static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size); +static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size); +static bool read_process_memory(pid_t pid, uintptr_t addr, void __user *buffer, size_t size); +static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user *buffer, size_t size); +static uintptr_t get_module_base(pid_t pid, const char *name); -static void call_process_code(pid_t pid, uintptr_t addr, void __user* params, void __user* RetValue, size_t ParamsSize) { - //这是一个Call函数 - //函数原理是修改先备份主线程的寄存器状态,然后修改寄存器状态让其执行目标函数,函数执行完毕后恢复寄存器状态 - //注意:该函数可能会引起系统不稳定,请谨慎使用 - struct task_struct* task = NULL; - struct pid* pid_struct = NULL; - pid_struct = find_get_pid(pid); - if (!pid_struct) - return; - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return; - } - /* 保持对 task 的引用直到调用完成,避免 use-after-free */ - modify_task_registers(task, addr, params, RetValue, ParamsSize); - put_task_struct(task); - put_pid(pid_struct); -} - -static phys_addr_t translate_linear_address(struct mm_struct* mm, uintptr_t va) +static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va) { - pgd_t* pgd; - pmd_t* pmd; - pte_t* pte; - pud_t* pud; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + pud_t *pud; phys_addr_t page_addr; uintptr_t page_offset; #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 61) - p4d_t* p4d; - + p4d_t *p4d; + pgd = pgd_offset(mm, va); if (pgd_none(*pgd) || pgd_bad(*pgd)) return 0; - + p4d = p4d_offset(pgd, va); if (p4d_none(*p4d) || p4d_bad(*p4d)) return 0; - + pud = pud_offset(p4d, va); #else pgd = pgd_offset(mm, va); if (pgd_none(*pgd) || pgd_bad(*pgd)) return 0; - + pud = pud_offset(pgd, va); #endif @@ -179,13 +82,13 @@ static inline bool is_valid_phys_addr_range(phys_addr_t addr, size_t size) return (addr + size <= virt_to_phys(high_memory)); } -static bool read_physical_address(phys_addr_t pa, void __user* buffer, size_t size) +static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size) { - void* mapped; + void *mapped; if (!pfn_valid(__phys_to_pfn(pa))) return false; - + // 使用替代函数检查物理地址范围 if (!is_valid_phys_addr_range(pa, size)) return false; @@ -203,13 +106,13 @@ static bool read_physical_address(phys_addr_t pa, void __user* buffer, size_t si return true; } -static bool write_physical_address(phys_addr_t pa, const void __user* buffer, size_t size) +static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size) { - void* mapped; + void *mapped; if (!pfn_valid(__phys_to_pfn(pa))) return false; - + // 使用替代函数检查物理地址范围 if (!is_valid_phys_addr_range(pa, size)) return false; @@ -227,12 +130,12 @@ static bool write_physical_address(phys_addr_t pa, const void __user* buffer, si return true; } -static bool read_process_memory(pid_t pid, uintptr_t addr, - void __user* buffer, size_t size) +static bool read_process_memory(pid_t pid, uintptr_t addr, + void __user *buffer, size_t size) { - struct task_struct* task = NULL; - struct mm_struct* mm = NULL; - struct pid* pid_struct = NULL; + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; phys_addr_t pa; bool result = false; @@ -248,7 +151,7 @@ static bool read_process_memory(pid_t pid, uintptr_t addr, mm = get_task_mm(task); put_pid(pid_struct); - + if (!mm) { put_task_struct(task); return false; @@ -257,9 +160,8 @@ static bool read_process_memory(pid_t pid, uintptr_t addr, pa = translate_linear_address(mm, addr); if (pa) { result = read_physical_address(pa, buffer, size); - } - else { - struct vm_area_struct* vma = find_vma(mm, addr); + } else { + struct vm_area_struct *vma = find_vma(mm, addr); if (vma) { if (clear_user(buffer, size) == 0) { result = true; @@ -272,12 +174,12 @@ static bool read_process_memory(pid_t pid, uintptr_t addr, return result; } -static bool write_process_memory(pid_t pid, uintptr_t addr, - const void __user* buffer, size_t size) +static bool write_process_memory(pid_t pid, uintptr_t addr, + const void __user *buffer, size_t size) { - struct task_struct* task = NULL; - struct mm_struct* mm = NULL; - struct pid* pid_struct = NULL; + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; phys_addr_t pa; bool result = false; @@ -293,7 +195,7 @@ static bool write_process_memory(pid_t pid, uintptr_t addr, mm = get_task_mm(task); put_pid(pid_struct); - + if (!mm) { put_task_struct(task); return false; @@ -311,12 +213,12 @@ static bool write_process_memory(pid_t pid, uintptr_t addr, #define ARC_PATH_MAX 256 -static uintptr_t get_module_base(pid_t pid, const char* name) +static uintptr_t get_module_base(pid_t pid, const char *name) { - struct task_struct* task = NULL; - struct mm_struct* mm = NULL; - struct pid* pid_struct = NULL; - struct vm_area_struct* vma = NULL; + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + struct vm_area_struct *vma = NULL; uintptr_t base_addr = 0; int path_len; @@ -332,7 +234,7 @@ static uintptr_t get_module_base(pid_t pid, const char* name) mm = get_task_mm(task); put_pid(pid_struct); - + if (!mm) { put_task_struct(task); return 0; @@ -346,7 +248,7 @@ static uintptr_t get_module_base(pid_t pid, const char* name) for (vma = mm->mmap; vma; vma = vma->vm_next) { #endif char buf[ARC_PATH_MAX]; - char* path_nm; + char *path_nm; if (!vma->vm_file) continue; @@ -368,31 +270,30 @@ static uintptr_t get_module_base(pid_t pid, const char* name) mmput(mm); put_task_struct(task); return base_addr; - } +} -static int dispatch_open(struct inode* node, struct file* file) +static int dispatch_open(struct inode *node, struct file *file) { return 0; } -static int dispatch_close(struct inode* node, struct file* file) +static int dispatch_close(struct inode *node, struct file *file) { return 0; } -static long dispatch_ioctl(struct file* file, unsigned int cmd, unsigned long arg) +static long dispatch_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - static char key[256] = { 0 }; + static char key[256] = {0}; static bool is_verified = false; switch (cmd) { case OP_INIT_KEY: if (!is_verified) { - if (copy_from_user(key, (void __user*)arg, sizeof(key) - 1) == 0) { + if (copy_from_user(key, (void __user *)arg, sizeof(key) - 1) == 0) { key[sizeof(key) - 1] = '\0'; is_verified = true; - } - else { + } else { return -EFAULT; } } @@ -400,69 +301,50 @@ static long dispatch_ioctl(struct file* file, unsigned int cmd, unsigned long ar case OP_READ_MEM: { COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user*)arg, sizeof(cm))) + + if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) return -EFAULT; - + if (!read_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) return -EIO; - + break; } case OP_WRITE_MEM: { COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user*)arg, sizeof(cm))) + + if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) return -EFAULT; - + if (!write_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) return -EIO; - + break; } case OP_MODULE_BASE: { MODULE_BASE mb; char module_name[256]; - - if (copy_from_user(&mb, (void __user*)arg, sizeof(mb))) + + if (copy_from_user(&mb, (void __user *)arg, sizeof(mb))) return -EFAULT; - + if (!mb.name) return -EFAULT; - + if (copy_from_user(module_name, mb.name, sizeof(module_name) - 1)) return -EFAULT; module_name[sizeof(module_name) - 1] = '\0'; - + mb.base = get_module_base(mb.pid, module_name); - - if (copy_to_user((void __user*)arg, &mb, sizeof(mb))) + + if (copy_to_user((void __user *)arg, &mb, sizeof(mb))) return -EFAULT; - + break; } - case OP_CALL_PROCESS: { - CALL_PROCESS cp; - - if (copy_from_user(&cp, (void __user*)arg, sizeof(cp))) - return -EFAULT; - - if (!cp.addr) - return -EFAULT; - - if (cp.params) - return -EFAULT; - - if (cp.ParamsSize < 1) - return -EFAULT; - - call_process_code(cp.pid, cp.addr, cp.params, cp.RetValue, cp.ParamsSize); - - break; - } default: return -ENOTTY; } @@ -482,17 +364,17 @@ static struct miscdevice misc_dev = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dispatch_fops, - .mode = 0777, + .mode = 0666, }; static int __init driver_entry(void) { int ret; - + ret = misc_register(&misc_dev); if (ret) return ret; - + return 0; } @@ -507,4 +389,4 @@ module_exit(driver_unload); MODULE_DESCRIPTION("Linux Kernel Module"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("YihanChan"); -MODULE_VERSION("1.0"); \ No newline at end of file +MODULE_VERSION("1.0"); diff --git a/code/aurora.h b/code/aurora.h index ab01f6dc..e35169bd 100644 --- a/code/aurora.h +++ b/code/aurora.h @@ -14,17 +14,6 @@ #include #include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include #include #include #include From c1e70a100cc247d6ff5aa87921720d6c57945e7c Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Fri, 23 Jan 2026 16:15:56 +0800 Subject: [PATCH 11/35] Delete README_zh.md --- README_zh.md | 85 ---------------------------------------------------- 1 file changed, 85 deletions(-) delete mode 100644 README_zh.md diff --git a/README_zh.md b/README_zh.md deleted file mode 100644 index 70cadf95..00000000 --- a/README_zh.md +++ /dev/null @@ -1,85 +0,0 @@ -**其他语言版本: [English](README.md), [中文](README_zh.md).** -# 自动化内核驱动构建工具 -本 GitHub Action 可在云端自动化编译 Android 内核驱动程序,无需本地编译环境。解决访问 Google 源码仓库等问题,编译时间控制在 30min内。 - -## 核心功能 - -- ✅ **云端编译** - 无需本地环境配置 -- ✅ **自动源码管理** - 从官方仓库获取 Android 内核源码 -- ✅ **版本感知构建** - 自动选择正确的构建系统 -- ✅ **参数化输入** - 通过工作流参数自定义构建 -- ✅ **结果打包** - 下载编译好的驱动和内核镜像 - -## 使用指南 - -### 1. 仓库设置 -1. 在仓库中创建 `code` 目录 -2. 将以下文件放入 `code` 目录: - - 驱动源文件 (`.c` 和 `.h`) - - 驱动的 `Makefile` - - 其他依赖文件 - -### 2. 运行工作流 -1. 转到 GitHub 仓库的 **Actions** 标签页 -2. 选择 **Android Kernel Driver Builder** -3. 点击 **Run workflow** -4. 提供以下参数: - - `android_version`: Android 版本(内核) (例如 `14`) - - `kernel_version`: 内核版本 (例如 `6.1`) - - `driver_name`: 驱动文件名 (例如 `mydriver.ko`) - - `target_arch`: 设备架构 (默认 `aarch64`) - -### 3. 获取结果 -编译成功后 (30 分钟): -1. 转到完成的工作流运行 -2. 下载 `kernel-driver-<架构>` 产物 -3. 解压后包含: - - 编译好的驱动 (`.ko` 文件) - - 内核镜像 (`boot.img`) - - 构建日志 - -## 配置参考 - -### 输入参数 - -| 参数 | 说明 | 示例 | -|------|------|------| -| `android_version` | Android 系统版本 | `11`, `12`, `13`, `14` | -| `kernel_version` | Linux 内核版本 | `5.10`, `5.15`, `6.1` | -| `driver_name` | 驱动文件名 | `custom_driver.ko` | -| `target_arch` | 设备 CPU 架构 | `aarch64`, `x86_64` | - -### 技术说明 - -1. **构建系统选择**: - - Android 11 及更早版本:使用传统 `build.sh` 系统 - - Android 12 及更新版本:使用现代 Bazel 构建系统 - -2. **源码管理**: - - 自动从 Google 仓库获取内核源码 - - 使用并行下载加速同步过程 - -3. **驱动集成**: - - 自动将驱动添加到内核构建系统 - - 注册驱动为 GKI 模块 - - 自动处理 Makefile 修改 - -## 故障排除 - -**Q: "repo sync" 步骤失败** -A: 重新运行工作流,Google 服务器偶尔会出现超时 - -**Q: 输出产物中找不到驱动文件** -A: 检查: -- `driver_name` 参数是否正确(需与 Makefile 匹配) -- 源文件是否在 `/code` 目录 -- Makefile 是否生成预期的 `.ko` 文件 - -**Q: 出现 "Kernel configuration not found" 错误** -A: 确认内核版本在 [Android 内核源码](https://android.googlesource.com/kernel/manifest/) 中存在对应分支 - -## 支持 - -问题反馈和功能请求: -- [提交 Issue](https://github.com/systemnb/compile_android_driver/issues) -- 请提供工作流日志和输入参数 From 55efe8653c79455846dfb536ff554ba7626aadd7 Mon Sep 17 00:00:00 2001 From: vesirvit <114746884+vesirvit@users.noreply.github.com> Date: Fri, 23 Jan 2026 16:17:57 +0800 Subject: [PATCH 12/35] Update README.md --- README.md | 88 ++----------------------------------------------------- 1 file changed, 2 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index 14b76eae..86bb6603 100644 --- a/README.md +++ b/README.md @@ -1,86 +1,2 @@ -**Read this in other languages: [English](README.md), [中文](README_zh.md).** -# Automated Kernel Driver Builder - -This GitHub Action automates the process of building Android kernel drivers in the cloud, eliminating the need for local compilation environments. It solves common issues like accessing Google's source repositories and reduces compilation time to under 30min. - -## Key Features - -- ✅ **Cloud-based compilation** - No local setup required -- ✅ **Automatic source handling** - Fetches official Android kernel sources -- ✅ **Version-aware building** - Automatically selects correct build system -- ✅ **Parameterized inputs** - Customize builds via workflow inputs -- ✅ **Artifact packaging** - Downloads compiled drivers and kernel images - -## Usage Guide - -### 1. Repository Setup -1. Create a `code` directory in your repository -2. Place these files in the `code` directory: - - Driver source files (`.c` and `.h`) - - `Makefile` for your driver - - Any additional dependencies - -### 2. Running the Workflow -1. Go to your GitHub repository's **Actions** tab -2. Select **Android Kernel Driver Builder** -3. Click **Run workflow** -4. Provide these parameters: - - `android_version`: Your Android version (Kernel) (e.g., `14`) - - `kernel_version`: Kernel version (e.g., `6.1`) - - `driver_name`: Your driver filename (e.g., `mydriver.ko`) - - `target_arch`: Device architecture (default: `aarch64`) - -### 3. Retrieving Results -After successful compilation (30minutes): -1. Go to the completed workflow run -2. Download the `kernel-driver-` artifact -3. Extract to find: - - Compiled driver (`.ko` file) - - Kernel images (`boot.img`) - - Build logs - -## Configuration Reference - -### Input Parameters - -| Parameter | Description | Example | -|-----------|-------------|---------| -| `android_version` | Android OS version | `11`, `12`, `13`, `14` | -| `kernel_version` | Linux kernel version | `5.10`, `5.15`, `6.1` | -| `driver_name` | Output driver filename | `custom_driver.ko` | -| `target_arch` | Device CPU architecture | `aarch64`, `x86_64` | - -### Technical Notes - -1. **Build System Selection**: - - Android 11 and earlier: Legacy `build.sh` system - - Android 12 and later: Modern Bazel build system - -2. **Source Management**: - - Automatically fetches kernel sources from Google's repositories - - Uses parallel downloading for faster sync - -3. **Driver Integration**: - - Automatically adds driver to kernel build system - - Registers driver as GKI module - - Handles Makefile modifications - -## Troubleshooting - -**Q: Build fails with "repo sync" errors** -A: Retry the workflow. Google's servers can occasionally timeout. - -**Q: Driver not found in output artifacts** -A: Verify: -- Correct `driver_name` parameter (must match Makefile) -- Source files are in `/code` directory -- Makefile produces expected `.ko` filename - -**Q: "Kernel configuration not found" error** -A: Confirm your kernel_version matches existing branches at [Android Kernel Sources](https://android.googlesource.com/kernel/manifest/) - -## Support - -For issues and feature requests: -- [Open an Issue](https://github.com/systemnb/compile_android_driver/issues) -- Provide workflow logs and input parameters +陈依涵的内核驱动项目,采用systemnb的Action编译。 +由于本人还是初学者,所以会不定期学习新内容并更新 From 49c3589babc56081bc2c1ab38d731b2bacb0bab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 27 Jan 2026 15:08:35 +0800 Subject: [PATCH 13/35] Delete code/aurora.c --- code/aurora.c | 392 -------------------------------------------------- 1 file changed, 392 deletions(-) delete mode 100644 code/aurora.c diff --git a/code/aurora.c b/code/aurora.c deleted file mode 100644 index a1134cc7..00000000 --- a/code/aurora.c +++ /dev/null @@ -1,392 +0,0 @@ -#include "aurora.h" - - -typedef struct _COPY_MEMORY { - pid_t pid; - uintptr_t addr; - void __user *buffer; - size_t size; -} COPY_MEMORY, *PCOPY_MEMORY; - -typedef struct _MODULE_BASE { - pid_t pid; - char __user *name; - uintptr_t base; -} MODULE_BASE, *PMODULE_BASE; - -enum OPERATIONS { - OP_INIT_KEY = 0x800, - OP_READ_MEM = 0x801, - OP_WRITE_MEM = 0x802, - OP_MODULE_BASE = 0x803, -}; - -static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va); -static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size); -static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size); -static bool read_process_memory(pid_t pid, uintptr_t addr, void __user *buffer, size_t size); -static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user *buffer, size_t size); -static uintptr_t get_module_base(pid_t pid, const char *name); - -static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - pud_t *pud; - phys_addr_t page_addr; - uintptr_t page_offset; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 61) - p4d_t *p4d; - - pgd = pgd_offset(mm, va); - if (pgd_none(*pgd) || pgd_bad(*pgd)) - return 0; - - p4d = p4d_offset(pgd, va); - if (p4d_none(*p4d) || p4d_bad(*p4d)) - return 0; - - pud = pud_offset(p4d, va); -#else - pgd = pgd_offset(mm, va); - if (pgd_none(*pgd) || pgd_bad(*pgd)) - return 0; - - pud = pud_offset(pgd, va); -#endif - - if (pud_none(*pud) || pud_bad(*pud)) - return 0; - - pmd = pmd_offset(pud, va); - if (pmd_none(*pmd)) - return 0; - - pte = pte_offset_kernel(pmd, va); - if (pte_none(*pte) || !pte_present(*pte)) - return 0; - - page_addr = (phys_addr_t)(pte_pfn(*pte) << PAGE_SHIFT); - page_offset = va & (PAGE_SIZE - 1); - - return page_addr + page_offset; -} - -// 替换 valid_phys_addr_range 的替代实现 -static inline bool is_valid_phys_addr_range(phys_addr_t addr, size_t size) -{ - // 简单的检查:确保地址在物理内存范围内 - // 对于ARM64架构,high_memory包含了高地址内存信息 - return (addr + size <= virt_to_phys(high_memory)); -} - -static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size) -{ - void *mapped; - - if (!pfn_valid(__phys_to_pfn(pa))) - return false; - - // 使用替代函数检查物理地址范围 - if (!is_valid_phys_addr_range(pa, size)) - return false; - - mapped = ioremap_cache(pa, size); - if (!mapped) - return false; - - if (copy_to_user(buffer, mapped, size)) { - iounmap(mapped); - return false; - } - - iounmap(mapped); - return true; -} - -static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size) -{ - void *mapped; - - if (!pfn_valid(__phys_to_pfn(pa))) - return false; - - // 使用替代函数检查物理地址范围 - if (!is_valid_phys_addr_range(pa, size)) - return false; - - mapped = ioremap_cache(pa, size); - if (!mapped) - return false; - - if (copy_from_user(mapped, buffer, size)) { - iounmap(mapped); - return false; - } - - iounmap(mapped); - return true; -} - -static bool read_process_memory(pid_t pid, uintptr_t addr, - void __user *buffer, size_t size) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - phys_addr_t pa; - bool result = false; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return false; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return false; - } - - mm = get_task_mm(task); - put_pid(pid_struct); - - if (!mm) { - put_task_struct(task); - return false; - } - - pa = translate_linear_address(mm, addr); - if (pa) { - result = read_physical_address(pa, buffer, size); - } else { - struct vm_area_struct *vma = find_vma(mm, addr); - if (vma) { - if (clear_user(buffer, size) == 0) { - result = true; - } - } - } - - mmput(mm); - put_task_struct(task); - return result; -} - -static bool write_process_memory(pid_t pid, uintptr_t addr, - const void __user *buffer, size_t size) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - phys_addr_t pa; - bool result = false; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return false; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return false; - } - - mm = get_task_mm(task); - put_pid(pid_struct); - - if (!mm) { - put_task_struct(task); - return false; - } - - pa = translate_linear_address(mm, addr); - if (pa) { - result = write_physical_address(pa, buffer, size); - } - - mmput(mm); - put_task_struct(task); - return result; -} - -#define ARC_PATH_MAX 256 - -static uintptr_t get_module_base(pid_t pid, const char *name) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - struct vm_area_struct *vma = NULL; - uintptr_t base_addr = 0; - int path_len; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return 0; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return 0; - } - - mm = get_task_mm(task); - put_pid(pid_struct); - - if (!mm) { - put_task_struct(task); - return 0; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) - struct vma_iterator vmi; - vma_iter_init(&vmi, mm, 0); - for_each_vma(vmi, vma) { -#else - for (vma = mm->mmap; vma; vma = vma->vm_next) { -#endif - char buf[ARC_PATH_MAX]; - char *path_nm; - - if (!vma->vm_file) - continue; - - path_nm = file_path(vma->vm_file, buf, ARC_PATH_MAX - 1); - if (IS_ERR(path_nm)) - continue; - - path_len = strlen(path_nm); - if (path_len <= 0) - continue; - - if (strstr(path_nm, name) != NULL) { - base_addr = vma->vm_start; - break; - } - } - - mmput(mm); - put_task_struct(task); - return base_addr; -} - -static int dispatch_open(struct inode *node, struct file *file) -{ - return 0; -} - -static int dispatch_close(struct inode *node, struct file *file) -{ - return 0; -} - -static long dispatch_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - static char key[256] = {0}; - static bool is_verified = false; - - switch (cmd) { - case OP_INIT_KEY: - if (!is_verified) { - if (copy_from_user(key, (void __user *)arg, sizeof(key) - 1) == 0) { - key[sizeof(key) - 1] = '\0'; - is_verified = true; - } else { - return -EFAULT; - } - } - break; - - case OP_READ_MEM: { - COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) - return -EFAULT; - - if (!read_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) - return -EIO; - - break; - } - - case OP_WRITE_MEM: { - COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) - return -EFAULT; - - if (!write_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) - return -EIO; - - break; - } - - case OP_MODULE_BASE: { - MODULE_BASE mb; - char module_name[256]; - - if (copy_from_user(&mb, (void __user *)arg, sizeof(mb))) - return -EFAULT; - - if (!mb.name) - return -EFAULT; - - if (copy_from_user(module_name, mb.name, sizeof(module_name) - 1)) - return -EFAULT; - module_name[sizeof(module_name) - 1] = '\0'; - - mb.base = get_module_base(mb.pid, module_name); - - if (copy_to_user((void __user *)arg, &mb, sizeof(mb))) - return -EFAULT; - - break; - } - - default: - return -ENOTTY; - } - - return 0; -} - -static const struct file_operations dispatch_fops = { - .owner = THIS_MODULE, - .open = dispatch_open, - .release = dispatch_close, - .unlocked_ioctl = dispatch_ioctl, - .compat_ioctl = dispatch_ioctl, -}; - -static struct miscdevice misc_dev = { - .minor = MISC_DYNAMIC_MINOR, - .name = DEVICE_NAME, - .fops = &dispatch_fops, - .mode = 0666, -}; - -static int __init driver_entry(void) -{ - int ret; - - ret = misc_register(&misc_dev); - if (ret) - return ret; - - return 0; -} - -static void __exit driver_unload(void) -{ - misc_deregister(&misc_dev); -} - -module_init(driver_entry); -module_exit(driver_unload); - -MODULE_DESCRIPTION("Linux Kernel Module"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("YihanChan"); -MODULE_VERSION("1.0"); From 82be5d43230c266d8deff7449af59a9beab938b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 27 Jan 2026 15:08:46 +0800 Subject: [PATCH 14/35] Delete code/aurora.h --- code/aurora.h | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 code/aurora.h diff --git a/code/aurora.h b/code/aurora.h deleted file mode 100644 index e35169bd..00000000 --- a/code/aurora.h +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) -#include -#include -#else -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) -#include -#include -#endif - -#define DEVICE_NAME "YihanChan" From f4cf15458fa5a211d016941e2bb7259a54f0fbfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 27 Jan 2026 15:09:12 +0800 Subject: [PATCH 15/35] Add files via upload --- code/Makefile | 2 +- code/hwBreakpointProc_module.c | 827 +++++++++++++++++++++++++++++++++ code/hwBreakpointProc_module.h | 161 +++++++ 3 files changed, 989 insertions(+), 1 deletion(-) create mode 100644 code/hwBreakpointProc_module.c create mode 100644 code/hwBreakpointProc_module.h diff --git a/code/Makefile b/code/Makefile index f5d1305e..20d191c4 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1 +1 @@ -obj-m += aurora.o +obj-m += hwBreakpointProc_module.o diff --git a/code/hwBreakpointProc_module.c b/code/hwBreakpointProc_module.c new file mode 100644 index 00000000..0363c800 --- /dev/null +++ b/code/hwBreakpointProc_module.c @@ -0,0 +1,827 @@ +#include "hwBreakpointProc_module.h" +#include +#include + +////////////////////////////////////////////////////////////////// +// 全局变量定义 +static atomic64_t g_hook_pc; +struct hwBreakpointProcDev *g_hwBreakpointProc_devp; +struct mutex g_hwbp_handle_info_mutex; +static void* g_hwbp_handle_info_arr = NULL; // cvector 类型 + +////////////////////////////////////////////////////////////////// +// cvector 实现 (简化版) +#define MIN_LEN 1024 +#define CVEFAILED -1 +#define CVESUCCESS 0 +#define CVEPUSHBACK 1 +#define CVEPOPBACK 2 +#define CVEINSERT 3 +#define CVERM 4 +#define EXPANED_VAL 1 +#define REDUSED_VAL 2 + +typedef void *citerator; +typedef struct _cvector *cvector; + +struct _cvector { + void *cv_pdata; + size_t cv_len, cv_tot_len, cv_size; +}; + +static void* vmalloc_realloc(void *old_ptr, size_t old_size, size_t new_size) { + void *new_ptr; + if (!old_ptr) { + return vmalloc(new_size); + } + if (new_size == 0) { + vfree(old_ptr); + return NULL; + } + new_ptr = vmalloc(new_size); + if (!new_ptr) { + pr_err("vmalloc realloc failed for size: %zu\n", new_size); + return NULL; + } + memcpy(new_ptr, old_ptr, min(old_size, new_size)); + vfree(old_ptr); + return new_ptr; +} + +static cvector cvector_create(const size_t size) { + cvector cv = (cvector)kmalloc(sizeof(struct _cvector), GFP_KERNEL); + if (!cv) return NULL; + + cv->cv_pdata = vmalloc(MIN_LEN * size); + if (!cv->cv_pdata) { + kfree(cv); + return NULL; + } + + cv->cv_size = size; + cv->cv_tot_len = MIN_LEN; + cv->cv_len = 0; + return cv; +} + +static void cvector_destroy(const cvector cv) { + vfree(cv->cv_pdata); + kfree(cv); +} + +static size_t cvector_length(const cvector cv) { + return cv->cv_len; +} + +static int cvector_pushback(const cvector cv, void *memb) { + if (cv->cv_len >= cv->cv_tot_len) { + void *pd_sav = cv->cv_pdata; + size_t old_size = cv->cv_tot_len * cv->cv_size; + cv->cv_tot_len <<= EXPANED_VAL; + cv->cv_pdata = vmalloc_realloc(cv->cv_pdata, old_size, cv->cv_tot_len * cv->cv_size); + + if (!cv->cv_pdata) { + cv->cv_pdata = pd_sav; + cv->cv_tot_len >>= EXPANED_VAL; + return CVEPUSHBACK; + } + } + + memcpy((char *)cv->cv_pdata + cv->cv_len * cv->cv_size, memb, cv->cv_size); + cv->cv_len++; + return CVESUCCESS; +} + +static citerator cvector_begin(const cvector cv) { + return cv->cv_pdata; +} + +static citerator cvector_end(const cvector cv) { + return (char *)cv->cv_pdata + (cv->cv_size * cv->cv_len); +} + +static citerator cvector_next(const cvector cv, citerator iter) { + return (char *)iter + cv->cv_size; +} + +static int cvector_rm(const cvector cv, citerator iter) { + citerator from = iter; + citerator end = cvector_end(cv); + + if (iter < cvector_begin(cv) || iter >= end) { + return CVEFAILED; + } + + memcpy(from, (char *)from + cv->cv_size, (char *)end - (char *)from); + cv->cv_len--; + + if ((cv->cv_tot_len >= (MIN_LEN << REDUSED_VAL)) && + (cv->cv_len <= (cv->cv_tot_len >> REDUSED_VAL))) { + void *pd_sav = cv->cv_pdata; + size_t old_size = cv->cv_tot_len * cv->cv_size; + cv->cv_tot_len >>= EXPANED_VAL; + cv->cv_pdata = vmalloc_realloc(cv->cv_pdata, old_size, cv->cv_tot_len * cv->cv_size); + + if (!cv->cv_pdata) { + cv->cv_tot_len <<= EXPANED_VAL; + cv->cv_pdata = pd_sav; + return CVERM; + } + } + return CVESUCCESS; +} + +////////////////////////////////////////////////////////////////// +// ARM64 寄存器辅助函数 +#define READ_WB_REG_CASE(OFF, N, REG, VAL) \ + case (OFF + N): \ + AARCH64_DBG_READ(N, REG, VAL); \ + break + +#define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ + case (OFF + N): \ + AARCH64_DBG_WRITE(N, REG, VAL); \ + break + +#define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \ + READ_WB_REG_CASE(OFF, 0, REG, VAL); \ + READ_WB_REG_CASE(OFF, 1, REG, VAL); \ + READ_WB_REG_CASE(OFF, 2, REG, VAL); \ + READ_WB_REG_CASE(OFF, 3, REG, VAL); \ + READ_WB_REG_CASE(OFF, 4, REG, VAL); \ + READ_WB_REG_CASE(OFF, 5, REG, VAL); \ + READ_WB_REG_CASE(OFF, 6, REG, VAL); \ + READ_WB_REG_CASE(OFF, 7, REG, VAL); \ + READ_WB_REG_CASE(OFF, 8, REG, VAL); \ + READ_WB_REG_CASE(OFF, 9, REG, VAL); \ + READ_WB_REG_CASE(OFF, 10, REG, VAL); \ + READ_WB_REG_CASE(OFF, 11, REG, VAL); \ + READ_WB_REG_CASE(OFF, 12, REG, VAL); \ + READ_WB_REG_CASE(OFF, 13, REG, VAL); \ + READ_WB_REG_CASE(OFF, 14, REG, VAL); \ + READ_WB_REG_CASE(OFF, 15, REG, VAL) + +static int getCpuNumBrps(void) { + return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1; +} + +static int getCpuNumWrps(void) { + return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1; +} + +static uint64_t read_wb_reg(int reg, int n) { + uint64_t val = 0; + switch (reg + n) { + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); + default: + pr_warn("attempt to read from unknown breakpoint register %d\n", n); + } + return val; +} + +static void write_wb_reg(int reg, int n, uint64_t val) { + switch (reg + n) { + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); + default: + pr_warn("attempt to write to unknown breakpoint register %d\n", n); + } + isb(); +} + +static bool toggle_bp_registers_directly(const struct perf_event_attr * attr, bool is_32bit_task, int enable) { + int i, max_slots, val_reg, ctrl_reg, cur_slot = -1; + u32 ctrl; + uint64_t hw_addr; + + if (!attr) return false; + + // 计算硬件地址 + if (is_32bit_task) { + if (attr->bp_len == HW_BREAKPOINT_LEN_8) + hw_addr = attr->bp_addr & ~0x7; + else + hw_addr = attr->bp_addr & ~0x3; + } else { + if (attr->bp_type == HW_BREAKPOINT_X) + hw_addr = attr->bp_addr & ~0x3; + else + hw_addr = attr->bp_addr & ~0x7; + } + + switch (attr->bp_type) { + case HW_BREAKPOINT_R: + case HW_BREAKPOINT_W: + case HW_BREAKPOINT_RW: + ctrl_reg = AARCH64_DBG_REG_WCR; + val_reg = AARCH64_DBG_REG_WVR; + max_slots = getCpuNumWrps(); + break; + case HW_BREAKPOINT_X: + ctrl_reg = AARCH64_DBG_REG_BCR; + val_reg = AARCH64_DBG_REG_BVR; + max_slots = getCpuNumBrps(); + break; + default: + return false; + } + + for (i = 0; i < max_slots; ++i) { + uint64_t addr = read_wb_reg(val_reg, i); + if (addr == hw_addr) { + cur_slot = i; + break; + } + } + + if (cur_slot == -1) return false; + + ctrl = read_wb_reg(ctrl_reg, cur_slot); + if (enable) + ctrl |= 0x1; + else + ctrl &= ~0x1; + write_wb_reg(ctrl_reg, cur_slot, ctrl); + return true; +} + +////////////////////////////////////////////////////////////////// +// 进程管理函数 +static void* get_proc_pid_struct(uint64_t pid) { + return find_get_pid((pid_t)pid); +} + +static void release_proc_pid_struct(void* proc_pid_struct) { + if (proc_pid_struct) { + put_pid((struct pid *)proc_pid_struct); + } +} + +////////////////////////////////////////////////////////////////// +// API 代理函数 +static struct perf_event* x_register_user_hw_breakpoint(struct perf_event_attr *attr, + perf_overflow_handler_t triggered, + void *context, + struct task_struct *tsk) { +#ifdef CONFIG_KALLSYMS_LOOKUP_NAME + // 这里应该使用 kallsyms_lookup_name 查找实际函数 + // 简化实现:直接调用内核函数 + return register_user_hw_breakpoint(attr, triggered, context, tsk); +#else + return register_user_hw_breakpoint(attr, triggered, context, tsk); +#endif +} + +static void x_unregister_hw_breakpoint(struct perf_event *bp) { +#ifdef CONFIG_KALLSYMS_LOOKUP_NAME + unregister_hw_breakpoint(bp); +#else + unregister_hw_breakpoint(bp); +#endif +} + +static int x_modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) { +#ifdef CONFIG_KALLSYMS_LOOKUP_NAME +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + return modify_user_hw_breakpoint(bp, attr); +#else + return 0; +#endif +#else +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + return modify_user_hw_breakpoint(bp, attr); +#else + return 0; +#endif +#endif +} + +static unsigned long x_copy_from_user(void *to, const void __user *from, unsigned long n) { + return __copy_from_user(to, from, n); +} + +static unsigned long x_copy_to_user(void __user *to, const void *from, unsigned long n) { + return __copy_to_user(to, from, n); +} + +////////////////////////////////////////////////////////////////// +// 硬件断点命中处理 +static void record_hit_details(struct HWBP_HANDLE_INFO *info, struct pt_regs *regs) { + struct HWBP_HIT_ITEM hit_item = {0}; + if (!info || !regs) return; + + hit_item.task_id = info->task_id; + hit_item.hit_addr = regs->pc; + hit_item.hit_time = ktime_get_real_seconds(); + memcpy(&hit_item.regs_info.regs, regs->regs, sizeof(hit_item.regs_info.regs)); + hit_item.regs_info.sp = regs->sp; + hit_item.regs_info.pc = regs->pc; + hit_item.regs_info.pstate = regs->pstate; + hit_item.regs_info.orig_x0 = regs->orig_x0; + hit_item.regs_info.syscallno = regs->syscallno; + + if (info->hit_item_arr) { + cvector cv = (cvector)info->hit_item_arr; + if (cvector_length(cv) < MIN_LEN) { + cvector_pushback(cv, &hit_item); + } + } +} + +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE +static bool arm64_move_bp_to_next_instruction(struct perf_event *bp, uint64_t next_instruction_addr, + struct perf_event_attr *original_attr, + struct perf_event_attr *next_instruction_attr) { + int result; + if (!bp || !original_attr || !next_instruction_attr || !next_instruction_addr) { + return false; + } + + memcpy(next_instruction_attr, original_attr, sizeof(struct perf_event_attr)); + next_instruction_attr->bp_addr = next_instruction_addr; + next_instruction_attr->bp_len = HW_BREAKPOINT_LEN_4; + next_instruction_attr->bp_type = HW_BREAKPOINT_X; + next_instruction_attr->disabled = 0; + + result = x_modify_user_hw_breakpoint(bp, next_instruction_attr); + if (result) { + next_instruction_attr->bp_addr = 0; + return false; + } + return true; +} + +static bool arm64_recovery_bp_to_original(struct perf_event *bp, + struct perf_event_attr *original_attr, + struct perf_event_attr *next_instruction_attr) { + int result; + if (!bp || !original_attr || !next_instruction_attr) { + return false; + } + + result = x_modify_user_hw_breakpoint(bp, original_attr); + if (result) { + return false; + } + next_instruction_attr->bp_addr = 0; + return true; +} +#endif + +static void hwbp_hit_user_info_callback(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs, + struct HWBP_HANDLE_INFO *hwbp_handle_info) { + hwbp_handle_info->hit_total_count++; + record_hit_details(hwbp_handle_info, regs); +} + +////////////////////////////////////////////////////////////////// +// 硬件断点处理主函数 +static void hwbp_handler(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs) { + citerator iter; + uint64_t hook_pc; + printk_debug(KERN_INFO "hw_breakpoint HIT!!!!! bp:%px, pc:%px, id:%d\n", bp, regs->pc, bp->id); + + hook_pc = atomic64_read(&g_hook_pc); + if (hook_pc) { + regs->pc = hook_pc; + return; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + cvector cv = (cvector)g_hwbp_handle_info_arr; + + for (iter = cvector_begin(cv); iter != cvector_end(cv); iter = cvector_next(cv, iter)) { + struct HWBP_HANDLE_INFO *hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp != bp) { + continue; + } + +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + if (hwbp_handle_info->next_instruction_attr.bp_addr != regs->pc) { + // first hit + bool should_toggle = true; + hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); + if (!hwbp_handle_info->is_32bit_task) { + if (arm64_move_bp_to_next_instruction(bp, regs->pc + 4, + &hwbp_handle_info->original_attr, + &hwbp_handle_info->next_instruction_attr)) { + should_toggle = false; + } + } + if (should_toggle) { + toggle_bp_registers_directly(&hwbp_handle_info->original_attr, + hwbp_handle_info->is_32bit_task, 0); + } + } else { + // second hit + if (!arm64_recovery_bp_to_original(bp, &hwbp_handle_info->original_attr, + &hwbp_handle_info->next_instruction_attr)) { + toggle_bp_registers_directly(&hwbp_handle_info->next_instruction_attr, + hwbp_handle_info->is_32bit_task, 0); + } + } +#else + hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); + toggle_bp_registers_directly(&hwbp_handle_info->original_attr, + hwbp_handle_info->is_32bit_task, 0); +#endif + } + mutex_unlock(&g_hwbp_handle_info_mutex); +} + +////////////////////////////////////////////////////////////////// +// 命令处理函数 +static ssize_t OnCmdOpenProcess(struct ioctl_request *hdr, char __user* buf) { + uint64_t pid = hdr->param1, handle = 0; + struct pid *proc_pid_struct = NULL; + printk_debug(KERN_INFO "CMD_OPEN_PROCESS\n"); + printk_debug(KERN_INFO "pid:%llu,size:%ld\n", pid, sizeof(pid)); + + proc_pid_struct = get_proc_pid_struct(pid); + printk_debug(KERN_INFO "proc_pid_struct *:0x%p\n", (void*)proc_pid_struct); + if (!proc_pid_struct) { + return -EINVAL; + } + handle = (uint64_t)proc_pid_struct; + + printk_debug(KERN_INFO "handle:%llu,size:%ld\n", handle, sizeof(handle)); + if (x_copy_to_user((void*)buf, (void*)&handle, sizeof(handle))) { + return -EINVAL; + } + return 0; +} + +static ssize_t OnCmdCloseProcess(struct ioctl_request *hdr, char __user* buf) { + struct pid *proc_pid_struct = (struct pid *)hdr->param1; + printk_debug(KERN_INFO "CMD_CLOSE_PROCESS\n"); + printk_debug(KERN_INFO "proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); + release_proc_pid_struct(proc_pid_struct); + return 0; +} + +static ssize_t OnCmdGetCpuNumBrps(struct ioctl_request *hdr, char __user* buf) { + printk_debug(KERN_INFO "CMD_GET_NUM_BRPS\n"); + return getCpuNumBrps(); +} + +static ssize_t OnCmdGetCpuNumWrps(struct ioctl_request *hdr, char __user* buf) { + printk_debug(KERN_INFO "CMD_GET_NUM_WRPS\n"); + return getCpuNumWrps(); +} + +static ssize_t OnCmdInstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct pid *proc_pid_struct = (struct pid *)hdr->param1; + uint64_t proc_virt_addr = hdr->param2; + char hwbp_len = hdr->param3 & 0xFF; + char hwbp_type = (hdr->param3 >> 8) & 0xFF; + + pid_t pid_val; + struct task_struct *task; + struct HWBP_HANDLE_INFO hwbp_handle_info = { 0 }; + printk_debug(KERN_INFO "CMD_INST_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "proc_pid_struct *:%px\n", proc_pid_struct); + printk_debug(KERN_INFO "proc_virt_addr :%px\n", proc_virt_addr); + printk_debug(KERN_INFO "hwbp_len:%zu\n", hwbp_len); + printk_debug(KERN_INFO "hwbp_type:%d\n", hwbp_type); + + pid_val = pid_nr(proc_pid_struct); + printk_debug(KERN_INFO "pid_val:%d\n", pid_val); + + if (!pid_val) { + printk_debug(KERN_INFO "pid_nr failed.\n"); + return -EINVAL; + } + + task = pid_task(proc_pid_struct, PIDTYPE_PID); + if (!task) { + printk_debug(KERN_INFO "get_pid_task failed.\n"); + return -EINVAL; + } + + hwbp_handle_info.task_id = pid_val; + hwbp_handle_info.is_32bit_task = is_compat_thread(task_thread_info(task)); + + // 初始化断点属性 + memset(&hwbp_handle_info.original_attr, 0, sizeof(struct perf_event_attr)); + hwbp_handle_info.original_attr.bp_addr = proc_virt_addr; + hwbp_handle_info.original_attr.bp_len = hwbp_len; + hwbp_handle_info.original_attr.bp_type = hwbp_type; + hwbp_handle_info.original_attr.disabled = 0; + hwbp_handle_info.original_attr.size = sizeof(struct perf_event_attr); + + hwbp_handle_info.sample_hbp = x_register_user_hw_breakpoint(&hwbp_handle_info.original_attr, + hwbp_handler, NULL, task); + printk_debug(KERN_INFO "register_user_hw_breakpoint return: %px\n", hwbp_handle_info.sample_hbp); + + if (IS_ERR((void __force *)hwbp_handle_info.sample_hbp)) { + int ret = PTR_ERR((void __force *)hwbp_handle_info.sample_hbp); + printk_debug(KERN_INFO "register_user_hw_breakpoint failed: %d\n", ret); + return ret; + } + + hwbp_handle_info.hit_item_arr = cvector_create(sizeof(struct HWBP_HIT_ITEM)); + mutex_lock(&g_hwbp_handle_info_mutex); + cvector_pushback((cvector)g_hwbp_handle_info_arr, &hwbp_handle_info); + mutex_unlock(&g_hwbp_handle_info_mutex); + + if (x_copy_to_user((void*)buf, &hwbp_handle_info.sample_hbp, sizeof(uint64_t))) { + return -EINVAL; + } + return 0; +} + +static ssize_t OnCmdUninstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct perf_event *sample_hbp = (struct perf_event *)hdr->param1; + citerator iter; + bool found = false; + printk_debug(KERN_INFO "CMD_UNINST_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + + if (!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + cvector cv = (cvector)g_hwbp_handle_info_arr; + + for (iter = cvector_begin(cv); iter != cvector_end(cv); iter = cvector_next(cv, iter)) { + struct HWBP_HANDLE_INFO *hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp == sample_hbp) { + if (hwbp_handle_info->hit_item_arr) { + cvector_destroy((cvector)hwbp_handle_info->hit_item_arr); + hwbp_handle_info->hit_item_arr = NULL; + } + cvector_rm(cv, iter); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + + if (found) { + x_unregister_hw_breakpoint(sample_hbp); + } + return 0; +} + +// 其他命令处理函数(简化实现) +static ssize_t OnCmdSuspendProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + // 简化实现 + return 0; +} + +static ssize_t OnCmdResumeProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + // 简化实现 + return 0; +} + +static ssize_t OnCmdGetHwbpHitCount(struct ioctl_request *hdr, char __user* buf) { + // 简化实现 + return 0; +} + +static ssize_t OnCmdGetHwbpHitDetail(struct ioctl_request *hdr, char __user* buf) { + // 简化实现 + return 0; +} + +static ssize_t OnCmdSetHookPc(struct ioctl_request *hdr, char __user* buf) { + uint64_t pc = hdr->param1; + printk_debug(KERN_INFO "CMD_SET_HOOK_PC\n"); + printk_debug(KERN_INFO "pc:%px\n", pc); + atomic64_set(&g_hook_pc, pc); + return 0; +} + +static ssize_t OnCmdHideKernelModule(struct ioctl_request *hdr, char __user* buf) { + printk_debug(KERN_INFO "CMD_HIDE_KERNEL_MODULE\n"); + if (g_hwBreakpointProc_devp->is_hidden_module == false) { + g_hwBreakpointProc_devp->is_hidden_module = true; + list_del_init(&THIS_MODULE->list); + kobject_del(&THIS_MODULE->mkobj.kobj); + } + return 0; +} + +static inline ssize_t DispatchCommand(struct ioctl_request *hdr, char __user* buf) { + switch (hdr->cmd) { + case CMD_OPEN_PROCESS: + return OnCmdOpenProcess(hdr, buf); + case CMD_CLOSE_PROCESS: + return OnCmdCloseProcess(hdr, buf); + case CMD_GET_NUM_BRPS: + return OnCmdGetCpuNumBrps(hdr, buf); + case CMD_GET_NUM_WRPS: + return OnCmdGetCpuNumWrps(hdr, buf); + case CMD_INST_PROCESS_HWBP: + return OnCmdInstProcessHwbp(hdr, buf); + case CMD_UNINST_PROCESS_HWBP: + return OnCmdUninstProcessHwbp(hdr, buf); + case CMD_SUSPEND_PROCESS_HWBP: + return OnCmdSuspendProcessHwbp(hdr, buf); + case CMD_RESUME_PROCESS_HWBP: + return OnCmdResumeProcessHwbp(hdr, buf); + case CMD_GET_HWBP_HIT_COUNT: + return OnCmdGetHwbpHitCount(hdr, buf); + case CMD_GET_HWBP_HIT_DETAIL: + return OnCmdGetHwbpHitDetail(hdr, buf); + case CMD_SET_HOOK_PC: + return OnCmdSetHookPc(hdr, buf); + case CMD_HIDE_KERNEL_MODULE: + return OnCmdHideKernelModule(hdr, buf); + default: + return -EINVAL; + } +} + +////////////////////////////////////////////////////////////////// +// 文件操作函数 +static ssize_t hwBreakpointProc_read(struct file* filp, + char __user* buf, + size_t size, + loff_t* ppos) { + struct ioctl_request hdr = {0}; + size_t header_size = sizeof(hdr); + + if (size < header_size) { + return -EINVAL; + } + + if (x_copy_from_user(&hdr, buf, header_size)) { + return -EFAULT; + } + + if (size < header_size + hdr.buf_size) { + return -EINVAL; + } + + return DispatchCommand(&hdr, buf + header_size); +} + +static void clean_hwbp(void) { + citerator iter; + cvector wait_unregister_bp_arr = cvector_create(sizeof(struct perf_event *)); + if (!wait_unregister_bp_arr || !g_hwbp_handle_info_arr) { + return; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + cvector cv = (cvector)g_hwbp_handle_info_arr; + + for (iter = cvector_begin(cv); iter != cvector_end(cv); iter = cvector_next(cv, iter)) { + struct HWBP_HANDLE_INFO *hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp) { + cvector_pushback(wait_unregister_bp_arr, &hwbp_handle_info->sample_hbp); + hwbp_handle_info->sample_hbp = NULL; + } + if (hwbp_handle_info->hit_item_arr) { + cvector_destroy((cvector)hwbp_handle_info->hit_item_arr); + hwbp_handle_info->hit_item_arr = NULL; + } + } + cvector_destroy(cv); + g_hwbp_handle_info_arr = NULL; + mutex_unlock(&g_hwbp_handle_info_mutex); + + for (iter = cvector_begin(wait_unregister_bp_arr); + iter != cvector_end(wait_unregister_bp_arr); + iter = cvector_next(wait_unregister_bp_arr, iter)) { + struct perf_event *bp = *(struct perf_event **)iter; + x_unregister_hw_breakpoint(bp); + } + cvector_destroy(wait_unregister_bp_arr); +} + +static int hwBreakpointProc_release(struct inode *inode, struct file *filp) { + clean_hwbp(); + mutex_lock(&g_hwbp_handle_info_mutex); + g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); + mutex_unlock(&g_hwbp_handle_info_mutex); + return 0; +} + +#ifdef CONFIG_USE_PROC_FILE_NODE +static const struct proc_ops hwBreakpointProc_proc_ops = { + .proc_read = hwBreakpointProc_read, + .proc_release = hwBreakpointProc_release, +}; +#endif + +////////////////////////////////////////////////////////////////// +// hide_procfs_dir 实现(修复了 filldir_t 问题) +static char g_hide_dir_name[256] = {0}; + +// 关键修复:统一使用 int 返回类型 +static int my_filldir(struct dir_context *ctx, + const char *name, + int namelen, + loff_t offset, + u64 ino, + unsigned int d_type) { + if (namelen == strlen(g_hide_dir_name) && + !strncmp(name, g_hide_dir_name, namelen)) { + return 0; // 跳过隐藏的目录 + } + // 注意:原始 filldir 函数需要传递 + return 0; // 简化实现 +} + +static int handler_pre(struct kprobe *kp, struct pt_regs *regs) { + // 简化实现 + return 0; +} + +static struct kprobe kp_hide_procfs_dir = { + .symbol_name = "proc_root_readdir", + .pre_handler = handler_pre, +}; + +static bool start_hide_procfs_dir(const char* hide_dir_name) { + int ret; + strlcpy(g_hide_dir_name, hide_dir_name, sizeof(g_hide_dir_name)); + ret = register_kprobe(&kp_hide_procfs_dir); + if (ret) { + printk_debug("[hide_procfs_dir] register_kprobe failed: %d\n", ret); + return false; + } + printk_debug("[hide_procfs_dir] kprobe installed, hiding \"%s\"\n", g_hide_dir_name); + return true; +} + +static void stop_hide_procfs_dir(void) { + unregister_kprobe(&kp_hide_procfs_dir); + printk_debug("[hide_procfs_dir] kprobe removed\n"); +} + +////////////////////////////////////////////////////////////////// +// 模块初始化和退出 +static int hwBreakpointProc_dev_init(void) { + g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); + mutex_init(&g_hwbp_handle_info_mutex); + + g_hwBreakpointProc_devp = kmalloc(sizeof(struct hwBreakpointProcDev), GFP_KERNEL); + if (!g_hwBreakpointProc_devp) { + return -ENOMEM; + } + memset(g_hwBreakpointProc_devp, 0, sizeof(struct hwBreakpointProcDev)); + +#ifdef CONFIG_USE_PROC_FILE_NODE + g_hwBreakpointProc_devp->proc_parent = proc_mkdir(CONFIG_PROC_NODE_AUTH_KEY, NULL); + if (g_hwBreakpointProc_devp->proc_parent) { + g_hwBreakpointProc_devp->proc_entry = proc_create(CONFIG_PROC_NODE_AUTH_KEY, + S_IRUGO | S_IWUGO, + g_hwBreakpointProc_devp->proc_parent, + &hwBreakpointProc_proc_ops); + start_hide_procfs_dir(CONFIG_PROC_NODE_AUTH_KEY); + } +#endif + + printk(KERN_EMERG "Hello, hwBreakpointProc module loaded\n"); + return 0; +} + +static void hwBreakpointProc_dev_exit(void) { + clean_hwbp(); + mutex_destroy(&g_hwbp_handle_info_mutex); + +#ifdef CONFIG_USE_PROC_FILE_NODE + if (g_hwBreakpointProc_devp->proc_entry) { + proc_remove(g_hwBreakpointProc_devp->proc_entry); + g_hwBreakpointProc_devp->proc_entry = NULL; + } + + if (g_hwBreakpointProc_devp->proc_parent) { + proc_remove(g_hwBreakpointProc_devp->proc_parent); + g_hwBreakpointProc_devp->proc_parent = NULL; + } + stop_hide_procfs_dir(); +#endif + + kfree(g_hwBreakpointProc_devp); + printk(KERN_EMERG "Goodbye, hwBreakpointProc module unloaded\n"); +} + +////////////////////////////////////////////////////////////////// +// 模块入口 +int __init init_module(void) { + return hwBreakpointProc_dev_init(); +} + +void __exit cleanup_module(void) { + hwBreakpointProc_dev_exit(); +} + +////////////////////////////////////////////////////////////////// +// 模块信息 +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linux"); +MODULE_DESCRIPTION("Hardware Breakpoint Process Module"); \ No newline at end of file diff --git a/code/hwBreakpointProc_module.h b/code/hwBreakpointProc_module.h new file mode 100644 index 00000000..3d32bf52 --- /dev/null +++ b/code/hwBreakpointProc_module.h @@ -0,0 +1,161 @@ +#ifndef _HWBP_PROC_H_ +#define _HWBP_PROC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////// +// 版本控制宏定义 +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +#ifndef MY_LINUX_VERSION_CODE +#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,6,30) +#endif + +// 调试打印模式 +//#define CONFIG_DEBUG_PRINTK + +#ifdef CONFIG_DEBUG_PRINTK +#define printk_debug printk +#else +static inline void printk_debug(const char *fmt, ...) { (void)fmt; } +#endif + +// 配置选项 +#define CONFIG_MODULE_GUIDE_ENTRY +#define CONFIG_USE_PROC_FILE_NODE +#define CONFIG_PROC_NODE_AUTH_KEY "dce3771681d4c7a143d5d06b7d32548e" +#define CONFIG_KALLSYMS_LOOKUP_NAME +#define CONFIG_MODIFY_HIT_NEXT_MODE +#define CONFIG_ANTI_PTRACE_DETECTION_MODE + +////////////////////////////////////////////////////////////////// +// 命令定义 +enum { + CMD_OPEN_PROCESS, // 打开进程 + CMD_CLOSE_PROCESS, // 关闭进程 + CMD_GET_NUM_BRPS, // 获取CPU硬件执行断点支持数量 + CMD_GET_NUM_WRPS, // 获取CPU硬件访问断点支持数量 + CMD_INST_PROCESS_HWBP, // 安装进程硬件断点 + CMD_UNINST_PROCESS_HWBP, // 卸载进程硬件断点 + CMD_SUSPEND_PROCESS_HWBP, // 暂停进程硬件断点 + CMD_RESUME_PROCESS_HWBP, // 恢复进程硬件断点 + CMD_GET_HWBP_HIT_COUNT, // 获取硬件断点命中地址数量 + CMD_GET_HWBP_HIT_DETAIL, // 获取硬件断点命中详细信息 + CMD_SET_HOOK_PC, // 设置无条件Hook跳转 + CMD_HIDE_KERNEL_MODULE, // 隐藏驱动 +}; + +////////////////////////////////////////////////////////////////// +// 结构体定义 +#pragma pack(push,1) +struct my_user_pt_regs { + uint64_t regs[31]; + uint64_t sp; + uint64_t pc; + uint64_t pstate; + uint64_t orig_x0; + uint64_t syscallno; +}; + +struct HWBP_HIT_ITEM { + uint64_t task_id; + uint64_t hit_addr; + uint64_t hit_time; + struct my_user_pt_regs regs_info; +}; + +struct ioctl_request { + char cmd; /* 1 字节命令 */ + uint64_t param1; /* 参数1 */ + uint64_t param2; /* 参数2 */ + uint64_t param3; /* 参数3 */ + uint64_t buf_size; /* 紧随其后的动态数据长度 */ +}; +#pragma pack(pop) + +struct HWBP_HANDLE_INFO { + uint64_t task_id; + struct perf_event * sample_hbp; + struct perf_event_attr original_attr; + bool is_32bit_task; +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + struct perf_event_attr next_instruction_attr; +#endif + size_t hit_total_count; + void* hit_item_arr; // cvector 类型 +}; + +struct hwBreakpointProcDev { +#ifdef CONFIG_USE_PROC_FILE_NODE + struct proc_dir_entry *proc_parent; + struct proc_dir_entry *proc_entry; +#endif + bool is_hidden_module; //是否已经隐藏过驱动列表了 +}; + +////////////////////////////////////////////////////////////////// +// 全局变量声明 +extern struct hwBreakpointProcDev *g_hwBreakpointProc_devp; +extern struct mutex g_hwbp_handle_info_mutex; +extern void* g_hwbp_handle_info_arr; // cvector 类型 + +////////////////////////////////////////////////////////////////// +// 函数声明 +// 设备操作函数 +ssize_t hwBreakpointProc_read(struct file* filp, char __user* buf, size_t size, loff_t* ppos); +int hwBreakpointProc_release(struct inode *inode, struct file *filp); + +// proc文件操作 +#ifdef CONFIG_USE_PROC_FILE_NODE +extern const struct proc_ops hwBreakpointProc_proc_ops; +#endif + +// 硬件断点处理函数 +void hwbp_handler(struct perf_event *bp, struct perf_sample_data *data, struct pt_regs *regs); + +// 辅助函数 +int getCpuNumBrps(void); +int getCpuNumWrps(void); +bool toggle_bp_registers_directly(const struct perf_event_attr * attr, bool is_32bit_task, int enable); + +// 进程管理函数 +void* get_proc_pid_struct(uint64_t pid); +void release_proc_pid_struct(void* proc_pid_struct); + +// 其他功能 +bool start_anti_ptrace_detection(struct mutex *p_mutex, void* p_vector); +void stop_anti_ptrace_detection(void); +bool start_hide_procfs_dir(const char* hide_dir_name); +void stop_hide_procfs_dir(void); + +#endif /* _HWBP_PROC_H_ */ \ No newline at end of file From db700afd2b85f11660b2dcffa5a974dd52775d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:21:42 +0800 Subject: [PATCH 16/35] Delete code/hwBreakpointProc_module.c --- code/hwBreakpointProc_module.c | 827 --------------------------------- 1 file changed, 827 deletions(-) delete mode 100644 code/hwBreakpointProc_module.c diff --git a/code/hwBreakpointProc_module.c b/code/hwBreakpointProc_module.c deleted file mode 100644 index 0363c800..00000000 --- a/code/hwBreakpointProc_module.c +++ /dev/null @@ -1,827 +0,0 @@ -#include "hwBreakpointProc_module.h" -#include -#include - -////////////////////////////////////////////////////////////////// -// 全局变量定义 -static atomic64_t g_hook_pc; -struct hwBreakpointProcDev *g_hwBreakpointProc_devp; -struct mutex g_hwbp_handle_info_mutex; -static void* g_hwbp_handle_info_arr = NULL; // cvector 类型 - -////////////////////////////////////////////////////////////////// -// cvector 实现 (简化版) -#define MIN_LEN 1024 -#define CVEFAILED -1 -#define CVESUCCESS 0 -#define CVEPUSHBACK 1 -#define CVEPOPBACK 2 -#define CVEINSERT 3 -#define CVERM 4 -#define EXPANED_VAL 1 -#define REDUSED_VAL 2 - -typedef void *citerator; -typedef struct _cvector *cvector; - -struct _cvector { - void *cv_pdata; - size_t cv_len, cv_tot_len, cv_size; -}; - -static void* vmalloc_realloc(void *old_ptr, size_t old_size, size_t new_size) { - void *new_ptr; - if (!old_ptr) { - return vmalloc(new_size); - } - if (new_size == 0) { - vfree(old_ptr); - return NULL; - } - new_ptr = vmalloc(new_size); - if (!new_ptr) { - pr_err("vmalloc realloc failed for size: %zu\n", new_size); - return NULL; - } - memcpy(new_ptr, old_ptr, min(old_size, new_size)); - vfree(old_ptr); - return new_ptr; -} - -static cvector cvector_create(const size_t size) { - cvector cv = (cvector)kmalloc(sizeof(struct _cvector), GFP_KERNEL); - if (!cv) return NULL; - - cv->cv_pdata = vmalloc(MIN_LEN * size); - if (!cv->cv_pdata) { - kfree(cv); - return NULL; - } - - cv->cv_size = size; - cv->cv_tot_len = MIN_LEN; - cv->cv_len = 0; - return cv; -} - -static void cvector_destroy(const cvector cv) { - vfree(cv->cv_pdata); - kfree(cv); -} - -static size_t cvector_length(const cvector cv) { - return cv->cv_len; -} - -static int cvector_pushback(const cvector cv, void *memb) { - if (cv->cv_len >= cv->cv_tot_len) { - void *pd_sav = cv->cv_pdata; - size_t old_size = cv->cv_tot_len * cv->cv_size; - cv->cv_tot_len <<= EXPANED_VAL; - cv->cv_pdata = vmalloc_realloc(cv->cv_pdata, old_size, cv->cv_tot_len * cv->cv_size); - - if (!cv->cv_pdata) { - cv->cv_pdata = pd_sav; - cv->cv_tot_len >>= EXPANED_VAL; - return CVEPUSHBACK; - } - } - - memcpy((char *)cv->cv_pdata + cv->cv_len * cv->cv_size, memb, cv->cv_size); - cv->cv_len++; - return CVESUCCESS; -} - -static citerator cvector_begin(const cvector cv) { - return cv->cv_pdata; -} - -static citerator cvector_end(const cvector cv) { - return (char *)cv->cv_pdata + (cv->cv_size * cv->cv_len); -} - -static citerator cvector_next(const cvector cv, citerator iter) { - return (char *)iter + cv->cv_size; -} - -static int cvector_rm(const cvector cv, citerator iter) { - citerator from = iter; - citerator end = cvector_end(cv); - - if (iter < cvector_begin(cv) || iter >= end) { - return CVEFAILED; - } - - memcpy(from, (char *)from + cv->cv_size, (char *)end - (char *)from); - cv->cv_len--; - - if ((cv->cv_tot_len >= (MIN_LEN << REDUSED_VAL)) && - (cv->cv_len <= (cv->cv_tot_len >> REDUSED_VAL))) { - void *pd_sav = cv->cv_pdata; - size_t old_size = cv->cv_tot_len * cv->cv_size; - cv->cv_tot_len >>= EXPANED_VAL; - cv->cv_pdata = vmalloc_realloc(cv->cv_pdata, old_size, cv->cv_tot_len * cv->cv_size); - - if (!cv->cv_pdata) { - cv->cv_tot_len <<= EXPANED_VAL; - cv->cv_pdata = pd_sav; - return CVERM; - } - } - return CVESUCCESS; -} - -////////////////////////////////////////////////////////////////// -// ARM64 寄存器辅助函数 -#define READ_WB_REG_CASE(OFF, N, REG, VAL) \ - case (OFF + N): \ - AARCH64_DBG_READ(N, REG, VAL); \ - break - -#define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ - case (OFF + N): \ - AARCH64_DBG_WRITE(N, REG, VAL); \ - break - -#define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \ - READ_WB_REG_CASE(OFF, 0, REG, VAL); \ - READ_WB_REG_CASE(OFF, 1, REG, VAL); \ - READ_WB_REG_CASE(OFF, 2, REG, VAL); \ - READ_WB_REG_CASE(OFF, 3, REG, VAL); \ - READ_WB_REG_CASE(OFF, 4, REG, VAL); \ - READ_WB_REG_CASE(OFF, 5, REG, VAL); \ - READ_WB_REG_CASE(OFF, 6, REG, VAL); \ - READ_WB_REG_CASE(OFF, 7, REG, VAL); \ - READ_WB_REG_CASE(OFF, 8, REG, VAL); \ - READ_WB_REG_CASE(OFF, 9, REG, VAL); \ - READ_WB_REG_CASE(OFF, 10, REG, VAL); \ - READ_WB_REG_CASE(OFF, 11, REG, VAL); \ - READ_WB_REG_CASE(OFF, 12, REG, VAL); \ - READ_WB_REG_CASE(OFF, 13, REG, VAL); \ - READ_WB_REG_CASE(OFF, 14, REG, VAL); \ - READ_WB_REG_CASE(OFF, 15, REG, VAL) - -static int getCpuNumBrps(void) { - return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1; -} - -static int getCpuNumWrps(void) { - return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1; -} - -static uint64_t read_wb_reg(int reg, int n) { - uint64_t val = 0; - switch (reg + n) { - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); - default: - pr_warn("attempt to read from unknown breakpoint register %d\n", n); - } - return val; -} - -static void write_wb_reg(int reg, int n, uint64_t val) { - switch (reg + n) { - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); - default: - pr_warn("attempt to write to unknown breakpoint register %d\n", n); - } - isb(); -} - -static bool toggle_bp_registers_directly(const struct perf_event_attr * attr, bool is_32bit_task, int enable) { - int i, max_slots, val_reg, ctrl_reg, cur_slot = -1; - u32 ctrl; - uint64_t hw_addr; - - if (!attr) return false; - - // 计算硬件地址 - if (is_32bit_task) { - if (attr->bp_len == HW_BREAKPOINT_LEN_8) - hw_addr = attr->bp_addr & ~0x7; - else - hw_addr = attr->bp_addr & ~0x3; - } else { - if (attr->bp_type == HW_BREAKPOINT_X) - hw_addr = attr->bp_addr & ~0x3; - else - hw_addr = attr->bp_addr & ~0x7; - } - - switch (attr->bp_type) { - case HW_BREAKPOINT_R: - case HW_BREAKPOINT_W: - case HW_BREAKPOINT_RW: - ctrl_reg = AARCH64_DBG_REG_WCR; - val_reg = AARCH64_DBG_REG_WVR; - max_slots = getCpuNumWrps(); - break; - case HW_BREAKPOINT_X: - ctrl_reg = AARCH64_DBG_REG_BCR; - val_reg = AARCH64_DBG_REG_BVR; - max_slots = getCpuNumBrps(); - break; - default: - return false; - } - - for (i = 0; i < max_slots; ++i) { - uint64_t addr = read_wb_reg(val_reg, i); - if (addr == hw_addr) { - cur_slot = i; - break; - } - } - - if (cur_slot == -1) return false; - - ctrl = read_wb_reg(ctrl_reg, cur_slot); - if (enable) - ctrl |= 0x1; - else - ctrl &= ~0x1; - write_wb_reg(ctrl_reg, cur_slot, ctrl); - return true; -} - -////////////////////////////////////////////////////////////////// -// 进程管理函数 -static void* get_proc_pid_struct(uint64_t pid) { - return find_get_pid((pid_t)pid); -} - -static void release_proc_pid_struct(void* proc_pid_struct) { - if (proc_pid_struct) { - put_pid((struct pid *)proc_pid_struct); - } -} - -////////////////////////////////////////////////////////////////// -// API 代理函数 -static struct perf_event* x_register_user_hw_breakpoint(struct perf_event_attr *attr, - perf_overflow_handler_t triggered, - void *context, - struct task_struct *tsk) { -#ifdef CONFIG_KALLSYMS_LOOKUP_NAME - // 这里应该使用 kallsyms_lookup_name 查找实际函数 - // 简化实现:直接调用内核函数 - return register_user_hw_breakpoint(attr, triggered, context, tsk); -#else - return register_user_hw_breakpoint(attr, triggered, context, tsk); -#endif -} - -static void x_unregister_hw_breakpoint(struct perf_event *bp) { -#ifdef CONFIG_KALLSYMS_LOOKUP_NAME - unregister_hw_breakpoint(bp); -#else - unregister_hw_breakpoint(bp); -#endif -} - -static int x_modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) { -#ifdef CONFIG_KALLSYMS_LOOKUP_NAME -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE - return modify_user_hw_breakpoint(bp, attr); -#else - return 0; -#endif -#else -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE - return modify_user_hw_breakpoint(bp, attr); -#else - return 0; -#endif -#endif -} - -static unsigned long x_copy_from_user(void *to, const void __user *from, unsigned long n) { - return __copy_from_user(to, from, n); -} - -static unsigned long x_copy_to_user(void __user *to, const void *from, unsigned long n) { - return __copy_to_user(to, from, n); -} - -////////////////////////////////////////////////////////////////// -// 硬件断点命中处理 -static void record_hit_details(struct HWBP_HANDLE_INFO *info, struct pt_regs *regs) { - struct HWBP_HIT_ITEM hit_item = {0}; - if (!info || !regs) return; - - hit_item.task_id = info->task_id; - hit_item.hit_addr = regs->pc; - hit_item.hit_time = ktime_get_real_seconds(); - memcpy(&hit_item.regs_info.regs, regs->regs, sizeof(hit_item.regs_info.regs)); - hit_item.regs_info.sp = regs->sp; - hit_item.regs_info.pc = regs->pc; - hit_item.regs_info.pstate = regs->pstate; - hit_item.regs_info.orig_x0 = regs->orig_x0; - hit_item.regs_info.syscallno = regs->syscallno; - - if (info->hit_item_arr) { - cvector cv = (cvector)info->hit_item_arr; - if (cvector_length(cv) < MIN_LEN) { - cvector_pushback(cv, &hit_item); - } - } -} - -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE -static bool arm64_move_bp_to_next_instruction(struct perf_event *bp, uint64_t next_instruction_addr, - struct perf_event_attr *original_attr, - struct perf_event_attr *next_instruction_attr) { - int result; - if (!bp || !original_attr || !next_instruction_attr || !next_instruction_addr) { - return false; - } - - memcpy(next_instruction_attr, original_attr, sizeof(struct perf_event_attr)); - next_instruction_attr->bp_addr = next_instruction_addr; - next_instruction_attr->bp_len = HW_BREAKPOINT_LEN_4; - next_instruction_attr->bp_type = HW_BREAKPOINT_X; - next_instruction_attr->disabled = 0; - - result = x_modify_user_hw_breakpoint(bp, next_instruction_attr); - if (result) { - next_instruction_attr->bp_addr = 0; - return false; - } - return true; -} - -static bool arm64_recovery_bp_to_original(struct perf_event *bp, - struct perf_event_attr *original_attr, - struct perf_event_attr *next_instruction_attr) { - int result; - if (!bp || !original_attr || !next_instruction_attr) { - return false; - } - - result = x_modify_user_hw_breakpoint(bp, original_attr); - if (result) { - return false; - } - next_instruction_attr->bp_addr = 0; - return true; -} -#endif - -static void hwbp_hit_user_info_callback(struct perf_event *bp, - struct perf_sample_data *data, - struct pt_regs *regs, - struct HWBP_HANDLE_INFO *hwbp_handle_info) { - hwbp_handle_info->hit_total_count++; - record_hit_details(hwbp_handle_info, regs); -} - -////////////////////////////////////////////////////////////////// -// 硬件断点处理主函数 -static void hwbp_handler(struct perf_event *bp, - struct perf_sample_data *data, - struct pt_regs *regs) { - citerator iter; - uint64_t hook_pc; - printk_debug(KERN_INFO "hw_breakpoint HIT!!!!! bp:%px, pc:%px, id:%d\n", bp, regs->pc, bp->id); - - hook_pc = atomic64_read(&g_hook_pc); - if (hook_pc) { - regs->pc = hook_pc; - return; - } - - mutex_lock(&g_hwbp_handle_info_mutex); - cvector cv = (cvector)g_hwbp_handle_info_arr; - - for (iter = cvector_begin(cv); iter != cvector_end(cv); iter = cvector_next(cv, iter)) { - struct HWBP_HANDLE_INFO *hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if (hwbp_handle_info->sample_hbp != bp) { - continue; - } - -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE - if (hwbp_handle_info->next_instruction_attr.bp_addr != regs->pc) { - // first hit - bool should_toggle = true; - hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); - if (!hwbp_handle_info->is_32bit_task) { - if (arm64_move_bp_to_next_instruction(bp, regs->pc + 4, - &hwbp_handle_info->original_attr, - &hwbp_handle_info->next_instruction_attr)) { - should_toggle = false; - } - } - if (should_toggle) { - toggle_bp_registers_directly(&hwbp_handle_info->original_attr, - hwbp_handle_info->is_32bit_task, 0); - } - } else { - // second hit - if (!arm64_recovery_bp_to_original(bp, &hwbp_handle_info->original_attr, - &hwbp_handle_info->next_instruction_attr)) { - toggle_bp_registers_directly(&hwbp_handle_info->next_instruction_attr, - hwbp_handle_info->is_32bit_task, 0); - } - } -#else - hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); - toggle_bp_registers_directly(&hwbp_handle_info->original_attr, - hwbp_handle_info->is_32bit_task, 0); -#endif - } - mutex_unlock(&g_hwbp_handle_info_mutex); -} - -////////////////////////////////////////////////////////////////// -// 命令处理函数 -static ssize_t OnCmdOpenProcess(struct ioctl_request *hdr, char __user* buf) { - uint64_t pid = hdr->param1, handle = 0; - struct pid *proc_pid_struct = NULL; - printk_debug(KERN_INFO "CMD_OPEN_PROCESS\n"); - printk_debug(KERN_INFO "pid:%llu,size:%ld\n", pid, sizeof(pid)); - - proc_pid_struct = get_proc_pid_struct(pid); - printk_debug(KERN_INFO "proc_pid_struct *:0x%p\n", (void*)proc_pid_struct); - if (!proc_pid_struct) { - return -EINVAL; - } - handle = (uint64_t)proc_pid_struct; - - printk_debug(KERN_INFO "handle:%llu,size:%ld\n", handle, sizeof(handle)); - if (x_copy_to_user((void*)buf, (void*)&handle, sizeof(handle))) { - return -EINVAL; - } - return 0; -} - -static ssize_t OnCmdCloseProcess(struct ioctl_request *hdr, char __user* buf) { - struct pid *proc_pid_struct = (struct pid *)hdr->param1; - printk_debug(KERN_INFO "CMD_CLOSE_PROCESS\n"); - printk_debug(KERN_INFO "proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - release_proc_pid_struct(proc_pid_struct); - return 0; -} - -static ssize_t OnCmdGetCpuNumBrps(struct ioctl_request *hdr, char __user* buf) { - printk_debug(KERN_INFO "CMD_GET_NUM_BRPS\n"); - return getCpuNumBrps(); -} - -static ssize_t OnCmdGetCpuNumWrps(struct ioctl_request *hdr, char __user* buf) { - printk_debug(KERN_INFO "CMD_GET_NUM_WRPS\n"); - return getCpuNumWrps(); -} - -static ssize_t OnCmdInstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { - struct pid *proc_pid_struct = (struct pid *)hdr->param1; - uint64_t proc_virt_addr = hdr->param2; - char hwbp_len = hdr->param3 & 0xFF; - char hwbp_type = (hdr->param3 >> 8) & 0xFF; - - pid_t pid_val; - struct task_struct *task; - struct HWBP_HANDLE_INFO hwbp_handle_info = { 0 }; - printk_debug(KERN_INFO "CMD_INST_PROCESS_HWBP\n"); - printk_debug(KERN_INFO "proc_pid_struct *:%px\n", proc_pid_struct); - printk_debug(KERN_INFO "proc_virt_addr :%px\n", proc_virt_addr); - printk_debug(KERN_INFO "hwbp_len:%zu\n", hwbp_len); - printk_debug(KERN_INFO "hwbp_type:%d\n", hwbp_type); - - pid_val = pid_nr(proc_pid_struct); - printk_debug(KERN_INFO "pid_val:%d\n", pid_val); - - if (!pid_val) { - printk_debug(KERN_INFO "pid_nr failed.\n"); - return -EINVAL; - } - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - printk_debug(KERN_INFO "get_pid_task failed.\n"); - return -EINVAL; - } - - hwbp_handle_info.task_id = pid_val; - hwbp_handle_info.is_32bit_task = is_compat_thread(task_thread_info(task)); - - // 初始化断点属性 - memset(&hwbp_handle_info.original_attr, 0, sizeof(struct perf_event_attr)); - hwbp_handle_info.original_attr.bp_addr = proc_virt_addr; - hwbp_handle_info.original_attr.bp_len = hwbp_len; - hwbp_handle_info.original_attr.bp_type = hwbp_type; - hwbp_handle_info.original_attr.disabled = 0; - hwbp_handle_info.original_attr.size = sizeof(struct perf_event_attr); - - hwbp_handle_info.sample_hbp = x_register_user_hw_breakpoint(&hwbp_handle_info.original_attr, - hwbp_handler, NULL, task); - printk_debug(KERN_INFO "register_user_hw_breakpoint return: %px\n", hwbp_handle_info.sample_hbp); - - if (IS_ERR((void __force *)hwbp_handle_info.sample_hbp)) { - int ret = PTR_ERR((void __force *)hwbp_handle_info.sample_hbp); - printk_debug(KERN_INFO "register_user_hw_breakpoint failed: %d\n", ret); - return ret; - } - - hwbp_handle_info.hit_item_arr = cvector_create(sizeof(struct HWBP_HIT_ITEM)); - mutex_lock(&g_hwbp_handle_info_mutex); - cvector_pushback((cvector)g_hwbp_handle_info_arr, &hwbp_handle_info); - mutex_unlock(&g_hwbp_handle_info_mutex); - - if (x_copy_to_user((void*)buf, &hwbp_handle_info.sample_hbp, sizeof(uint64_t))) { - return -EINVAL; - } - return 0; -} - -static ssize_t OnCmdUninstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { - struct perf_event *sample_hbp = (struct perf_event *)hdr->param1; - citerator iter; - bool found = false; - printk_debug(KERN_INFO "CMD_UNINST_PROCESS_HWBP\n"); - printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); - - if (!sample_hbp) { - return -EFAULT; - } - - mutex_lock(&g_hwbp_handle_info_mutex); - cvector cv = (cvector)g_hwbp_handle_info_arr; - - for (iter = cvector_begin(cv); iter != cvector_end(cv); iter = cvector_next(cv, iter)) { - struct HWBP_HANDLE_INFO *hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if (hwbp_handle_info->sample_hbp == sample_hbp) { - if (hwbp_handle_info->hit_item_arr) { - cvector_destroy((cvector)hwbp_handle_info->hit_item_arr); - hwbp_handle_info->hit_item_arr = NULL; - } - cvector_rm(cv, iter); - found = true; - break; - } - } - mutex_unlock(&g_hwbp_handle_info_mutex); - - if (found) { - x_unregister_hw_breakpoint(sample_hbp); - } - return 0; -} - -// 其他命令处理函数(简化实现) -static ssize_t OnCmdSuspendProcessHwbp(struct ioctl_request *hdr, char __user* buf) { - // 简化实现 - return 0; -} - -static ssize_t OnCmdResumeProcessHwbp(struct ioctl_request *hdr, char __user* buf) { - // 简化实现 - return 0; -} - -static ssize_t OnCmdGetHwbpHitCount(struct ioctl_request *hdr, char __user* buf) { - // 简化实现 - return 0; -} - -static ssize_t OnCmdGetHwbpHitDetail(struct ioctl_request *hdr, char __user* buf) { - // 简化实现 - return 0; -} - -static ssize_t OnCmdSetHookPc(struct ioctl_request *hdr, char __user* buf) { - uint64_t pc = hdr->param1; - printk_debug(KERN_INFO "CMD_SET_HOOK_PC\n"); - printk_debug(KERN_INFO "pc:%px\n", pc); - atomic64_set(&g_hook_pc, pc); - return 0; -} - -static ssize_t OnCmdHideKernelModule(struct ioctl_request *hdr, char __user* buf) { - printk_debug(KERN_INFO "CMD_HIDE_KERNEL_MODULE\n"); - if (g_hwBreakpointProc_devp->is_hidden_module == false) { - g_hwBreakpointProc_devp->is_hidden_module = true; - list_del_init(&THIS_MODULE->list); - kobject_del(&THIS_MODULE->mkobj.kobj); - } - return 0; -} - -static inline ssize_t DispatchCommand(struct ioctl_request *hdr, char __user* buf) { - switch (hdr->cmd) { - case CMD_OPEN_PROCESS: - return OnCmdOpenProcess(hdr, buf); - case CMD_CLOSE_PROCESS: - return OnCmdCloseProcess(hdr, buf); - case CMD_GET_NUM_BRPS: - return OnCmdGetCpuNumBrps(hdr, buf); - case CMD_GET_NUM_WRPS: - return OnCmdGetCpuNumWrps(hdr, buf); - case CMD_INST_PROCESS_HWBP: - return OnCmdInstProcessHwbp(hdr, buf); - case CMD_UNINST_PROCESS_HWBP: - return OnCmdUninstProcessHwbp(hdr, buf); - case CMD_SUSPEND_PROCESS_HWBP: - return OnCmdSuspendProcessHwbp(hdr, buf); - case CMD_RESUME_PROCESS_HWBP: - return OnCmdResumeProcessHwbp(hdr, buf); - case CMD_GET_HWBP_HIT_COUNT: - return OnCmdGetHwbpHitCount(hdr, buf); - case CMD_GET_HWBP_HIT_DETAIL: - return OnCmdGetHwbpHitDetail(hdr, buf); - case CMD_SET_HOOK_PC: - return OnCmdSetHookPc(hdr, buf); - case CMD_HIDE_KERNEL_MODULE: - return OnCmdHideKernelModule(hdr, buf); - default: - return -EINVAL; - } -} - -////////////////////////////////////////////////////////////////// -// 文件操作函数 -static ssize_t hwBreakpointProc_read(struct file* filp, - char __user* buf, - size_t size, - loff_t* ppos) { - struct ioctl_request hdr = {0}; - size_t header_size = sizeof(hdr); - - if (size < header_size) { - return -EINVAL; - } - - if (x_copy_from_user(&hdr, buf, header_size)) { - return -EFAULT; - } - - if (size < header_size + hdr.buf_size) { - return -EINVAL; - } - - return DispatchCommand(&hdr, buf + header_size); -} - -static void clean_hwbp(void) { - citerator iter; - cvector wait_unregister_bp_arr = cvector_create(sizeof(struct perf_event *)); - if (!wait_unregister_bp_arr || !g_hwbp_handle_info_arr) { - return; - } - - mutex_lock(&g_hwbp_handle_info_mutex); - cvector cv = (cvector)g_hwbp_handle_info_arr; - - for (iter = cvector_begin(cv); iter != cvector_end(cv); iter = cvector_next(cv, iter)) { - struct HWBP_HANDLE_INFO *hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if (hwbp_handle_info->sample_hbp) { - cvector_pushback(wait_unregister_bp_arr, &hwbp_handle_info->sample_hbp); - hwbp_handle_info->sample_hbp = NULL; - } - if (hwbp_handle_info->hit_item_arr) { - cvector_destroy((cvector)hwbp_handle_info->hit_item_arr); - hwbp_handle_info->hit_item_arr = NULL; - } - } - cvector_destroy(cv); - g_hwbp_handle_info_arr = NULL; - mutex_unlock(&g_hwbp_handle_info_mutex); - - for (iter = cvector_begin(wait_unregister_bp_arr); - iter != cvector_end(wait_unregister_bp_arr); - iter = cvector_next(wait_unregister_bp_arr, iter)) { - struct perf_event *bp = *(struct perf_event **)iter; - x_unregister_hw_breakpoint(bp); - } - cvector_destroy(wait_unregister_bp_arr); -} - -static int hwBreakpointProc_release(struct inode *inode, struct file *filp) { - clean_hwbp(); - mutex_lock(&g_hwbp_handle_info_mutex); - g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); - mutex_unlock(&g_hwbp_handle_info_mutex); - return 0; -} - -#ifdef CONFIG_USE_PROC_FILE_NODE -static const struct proc_ops hwBreakpointProc_proc_ops = { - .proc_read = hwBreakpointProc_read, - .proc_release = hwBreakpointProc_release, -}; -#endif - -////////////////////////////////////////////////////////////////// -// hide_procfs_dir 实现(修复了 filldir_t 问题) -static char g_hide_dir_name[256] = {0}; - -// 关键修复:统一使用 int 返回类型 -static int my_filldir(struct dir_context *ctx, - const char *name, - int namelen, - loff_t offset, - u64 ino, - unsigned int d_type) { - if (namelen == strlen(g_hide_dir_name) && - !strncmp(name, g_hide_dir_name, namelen)) { - return 0; // 跳过隐藏的目录 - } - // 注意:原始 filldir 函数需要传递 - return 0; // 简化实现 -} - -static int handler_pre(struct kprobe *kp, struct pt_regs *regs) { - // 简化实现 - return 0; -} - -static struct kprobe kp_hide_procfs_dir = { - .symbol_name = "proc_root_readdir", - .pre_handler = handler_pre, -}; - -static bool start_hide_procfs_dir(const char* hide_dir_name) { - int ret; - strlcpy(g_hide_dir_name, hide_dir_name, sizeof(g_hide_dir_name)); - ret = register_kprobe(&kp_hide_procfs_dir); - if (ret) { - printk_debug("[hide_procfs_dir] register_kprobe failed: %d\n", ret); - return false; - } - printk_debug("[hide_procfs_dir] kprobe installed, hiding \"%s\"\n", g_hide_dir_name); - return true; -} - -static void stop_hide_procfs_dir(void) { - unregister_kprobe(&kp_hide_procfs_dir); - printk_debug("[hide_procfs_dir] kprobe removed\n"); -} - -////////////////////////////////////////////////////////////////// -// 模块初始化和退出 -static int hwBreakpointProc_dev_init(void) { - g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); - mutex_init(&g_hwbp_handle_info_mutex); - - g_hwBreakpointProc_devp = kmalloc(sizeof(struct hwBreakpointProcDev), GFP_KERNEL); - if (!g_hwBreakpointProc_devp) { - return -ENOMEM; - } - memset(g_hwBreakpointProc_devp, 0, sizeof(struct hwBreakpointProcDev)); - -#ifdef CONFIG_USE_PROC_FILE_NODE - g_hwBreakpointProc_devp->proc_parent = proc_mkdir(CONFIG_PROC_NODE_AUTH_KEY, NULL); - if (g_hwBreakpointProc_devp->proc_parent) { - g_hwBreakpointProc_devp->proc_entry = proc_create(CONFIG_PROC_NODE_AUTH_KEY, - S_IRUGO | S_IWUGO, - g_hwBreakpointProc_devp->proc_parent, - &hwBreakpointProc_proc_ops); - start_hide_procfs_dir(CONFIG_PROC_NODE_AUTH_KEY); - } -#endif - - printk(KERN_EMERG "Hello, hwBreakpointProc module loaded\n"); - return 0; -} - -static void hwBreakpointProc_dev_exit(void) { - clean_hwbp(); - mutex_destroy(&g_hwbp_handle_info_mutex); - -#ifdef CONFIG_USE_PROC_FILE_NODE - if (g_hwBreakpointProc_devp->proc_entry) { - proc_remove(g_hwBreakpointProc_devp->proc_entry); - g_hwBreakpointProc_devp->proc_entry = NULL; - } - - if (g_hwBreakpointProc_devp->proc_parent) { - proc_remove(g_hwBreakpointProc_devp->proc_parent); - g_hwBreakpointProc_devp->proc_parent = NULL; - } - stop_hide_procfs_dir(); -#endif - - kfree(g_hwBreakpointProc_devp); - printk(KERN_EMERG "Goodbye, hwBreakpointProc module unloaded\n"); -} - -////////////////////////////////////////////////////////////////// -// 模块入口 -int __init init_module(void) { - return hwBreakpointProc_dev_init(); -} - -void __exit cleanup_module(void) { - hwBreakpointProc_dev_exit(); -} - -////////////////////////////////////////////////////////////////// -// 模块信息 -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Linux"); -MODULE_DESCRIPTION("Hardware Breakpoint Process Module"); \ No newline at end of file From 1d9e12b94f53bddf0eb9556976b3b310231955b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:21:54 +0800 Subject: [PATCH 17/35] Delete code/hwBreakpointProc_module.h --- code/hwBreakpointProc_module.h | 161 --------------------------------- 1 file changed, 161 deletions(-) delete mode 100644 code/hwBreakpointProc_module.h diff --git a/code/hwBreakpointProc_module.h b/code/hwBreakpointProc_module.h deleted file mode 100644 index 3d32bf52..00000000 --- a/code/hwBreakpointProc_module.h +++ /dev/null @@ -1,161 +0,0 @@ -#ifndef _HWBP_PROC_H_ -#define _HWBP_PROC_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -////////////////////////////////////////////////////////////////// -// 版本控制宏定义 -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif - -#ifndef MY_LINUX_VERSION_CODE -#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,6,30) -#endif - -// 调试打印模式 -//#define CONFIG_DEBUG_PRINTK - -#ifdef CONFIG_DEBUG_PRINTK -#define printk_debug printk -#else -static inline void printk_debug(const char *fmt, ...) { (void)fmt; } -#endif - -// 配置选项 -#define CONFIG_MODULE_GUIDE_ENTRY -#define CONFIG_USE_PROC_FILE_NODE -#define CONFIG_PROC_NODE_AUTH_KEY "dce3771681d4c7a143d5d06b7d32548e" -#define CONFIG_KALLSYMS_LOOKUP_NAME -#define CONFIG_MODIFY_HIT_NEXT_MODE -#define CONFIG_ANTI_PTRACE_DETECTION_MODE - -////////////////////////////////////////////////////////////////// -// 命令定义 -enum { - CMD_OPEN_PROCESS, // 打开进程 - CMD_CLOSE_PROCESS, // 关闭进程 - CMD_GET_NUM_BRPS, // 获取CPU硬件执行断点支持数量 - CMD_GET_NUM_WRPS, // 获取CPU硬件访问断点支持数量 - CMD_INST_PROCESS_HWBP, // 安装进程硬件断点 - CMD_UNINST_PROCESS_HWBP, // 卸载进程硬件断点 - CMD_SUSPEND_PROCESS_HWBP, // 暂停进程硬件断点 - CMD_RESUME_PROCESS_HWBP, // 恢复进程硬件断点 - CMD_GET_HWBP_HIT_COUNT, // 获取硬件断点命中地址数量 - CMD_GET_HWBP_HIT_DETAIL, // 获取硬件断点命中详细信息 - CMD_SET_HOOK_PC, // 设置无条件Hook跳转 - CMD_HIDE_KERNEL_MODULE, // 隐藏驱动 -}; - -////////////////////////////////////////////////////////////////// -// 结构体定义 -#pragma pack(push,1) -struct my_user_pt_regs { - uint64_t regs[31]; - uint64_t sp; - uint64_t pc; - uint64_t pstate; - uint64_t orig_x0; - uint64_t syscallno; -}; - -struct HWBP_HIT_ITEM { - uint64_t task_id; - uint64_t hit_addr; - uint64_t hit_time; - struct my_user_pt_regs regs_info; -}; - -struct ioctl_request { - char cmd; /* 1 字节命令 */ - uint64_t param1; /* 参数1 */ - uint64_t param2; /* 参数2 */ - uint64_t param3; /* 参数3 */ - uint64_t buf_size; /* 紧随其后的动态数据长度 */ -}; -#pragma pack(pop) - -struct HWBP_HANDLE_INFO { - uint64_t task_id; - struct perf_event * sample_hbp; - struct perf_event_attr original_attr; - bool is_32bit_task; -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE - struct perf_event_attr next_instruction_attr; -#endif - size_t hit_total_count; - void* hit_item_arr; // cvector 类型 -}; - -struct hwBreakpointProcDev { -#ifdef CONFIG_USE_PROC_FILE_NODE - struct proc_dir_entry *proc_parent; - struct proc_dir_entry *proc_entry; -#endif - bool is_hidden_module; //是否已经隐藏过驱动列表了 -}; - -////////////////////////////////////////////////////////////////// -// 全局变量声明 -extern struct hwBreakpointProcDev *g_hwBreakpointProc_devp; -extern struct mutex g_hwbp_handle_info_mutex; -extern void* g_hwbp_handle_info_arr; // cvector 类型 - -////////////////////////////////////////////////////////////////// -// 函数声明 -// 设备操作函数 -ssize_t hwBreakpointProc_read(struct file* filp, char __user* buf, size_t size, loff_t* ppos); -int hwBreakpointProc_release(struct inode *inode, struct file *filp); - -// proc文件操作 -#ifdef CONFIG_USE_PROC_FILE_NODE -extern const struct proc_ops hwBreakpointProc_proc_ops; -#endif - -// 硬件断点处理函数 -void hwbp_handler(struct perf_event *bp, struct perf_sample_data *data, struct pt_regs *regs); - -// 辅助函数 -int getCpuNumBrps(void); -int getCpuNumWrps(void); -bool toggle_bp_registers_directly(const struct perf_event_attr * attr, bool is_32bit_task, int enable); - -// 进程管理函数 -void* get_proc_pid_struct(uint64_t pid); -void release_proc_pid_struct(void* proc_pid_struct); - -// 其他功能 -bool start_anti_ptrace_detection(struct mutex *p_mutex, void* p_vector); -void stop_anti_ptrace_detection(void); -bool start_hide_procfs_dir(const char* hide_dir_name); -void stop_hide_procfs_dir(void); - -#endif /* _HWBP_PROC_H_ */ \ No newline at end of file From db48fc8075e734bc9f41db770543e6a00b1c4701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:22:32 +0800 Subject: [PATCH 18/35] Add files via upload --- code/Makefile | 2 +- code/arm64_hw_bp.c | 1186 ++++++++++++++++++++++++++++++++++++++++++++ code/arm64_hw_bp.h | 46 ++ 3 files changed, 1233 insertions(+), 1 deletion(-) create mode 100644 code/arm64_hw_bp.c create mode 100644 code/arm64_hw_bp.h diff --git a/code/Makefile b/code/Makefile index 20d191c4..213da72a 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1 +1 @@ -obj-m += hwBreakpointProc_module.o +obj-m += arm64_hw_bp.o diff --git a/code/arm64_hw_bp.c b/code/arm64_hw_bp.c new file mode 100644 index 00000000..01d81f12 --- /dev/null +++ b/code/arm64_hw_bp.c @@ -0,0 +1,1186 @@ +/* + * ARM64硬件断点内核模块 - 修复hw_breakpoint_slots问题 + * 适配Linux 5.10内核 + */ + +#include "arm64_hw_bp.h" + +// 断点数据结构 +typedef struct _HW_BREAKPOINT_INFO { + pid_t pid; + uintptr_t addr; + uint32_t type; // 断点类型 + bool active; + struct perf_event *pe; // perf事件 +} HW_BREAKPOINT_INFO, *PHW_BREAKPOINT_INFO; + +typedef struct _BREAKPOINT_OPERATION { + pid_t pid; + uintptr_t addr; + uint32_t type; +} BREAKPOINT_OPERATION, *PBREAKPOINT_OPERATION; + +typedef struct _COPY_MEMORY { + pid_t pid; + uintptr_t addr; + void __user *buffer; + size_t size; +} COPY_MEMORY, *PCOPY_MEMORY; + +typedef struct _MODULE_BASE { + pid_t pid; + char __user *name; + uintptr_t base; +} MODULE_BASE, *PMODULE_BASE; + +// ARM64寄存器结构 +typedef struct _ARM64_REGISTERS { + uint64_t x[31]; // 通用寄存器 X0-X30 + uint64_t fp; // 帧指针 + uint64_t lr; // 链接寄存器 + uint64_t sp; // 栈指针 + uint64_t pc; // 程序计数器 + uint64_t pstate; // 处理器状态 + uint64_t v[32]; // 向量寄存器 (可选) +} ARM64_REGISTERS, *PARM64_REGISTERS; + +typedef struct _REGISTER_OPERATION { + pid_t pid; + ARM64_REGISTERS __user *regs; + bool read; // true: 读取寄存器, false: 写入寄存器 +} REGISTER_OPERATION, *PREGISTER_OPERATION; + +typedef struct _PROCESS_CONTROL { + pid_t pid; + bool suspend; // true: 暂停, false: 恢复 +} PROCESS_CONTROL, *PPROCESS_CONTROL; + +// IOCTL操作码 +enum HW_BREAKPOINT_OPERATIONS { + OP_INIT_KEY = 0x800, + OP_READ_MEM = 0x801, + OP_WRITE_MEM = 0x802, + OP_MODULE_BASE = 0x803, + OP_SET_BREAKPOINT = 0x804, + OP_CLEAR_BREAKPOINT = 0x805, + OP_LIST_BREAKPOINTS = 0x806, + OP_CLEAR_ALL_BREAKPOINTS = 0x807, + OP_GET_REGISTERS = 0x808, + OP_SET_REGISTERS = 0x809, + OP_SUSPEND_PROCESS = 0x80A, + OP_RESUME_PROCESS = 0x80B, + OP_SINGLE_STEP = 0x80C, +}; + +// 暂停进程信息结构 +struct suspended_process { + pid_t pid; + struct task_struct *task; + struct list_head list; + bool stepping; // 单步执行模式 +}; + +// 全局变量 +static DEFINE_MUTEX(bp_mutex); +static LIST_HEAD(bp_list); +static LIST_HEAD(suspended_list); +static int bp_count = 0; +#define MAX_BREAKPOINTS 16 + +// 函数声明 +static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va); +static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size); +static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size); +static bool read_process_memory(pid_t pid, uintptr_t addr, void __user *buffer, size_t size); +static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user *buffer, size_t size); +static uintptr_t get_module_base(pid_t pid, const char *name); +static void hw_breakpoint_handler(struct perf_event *bp, struct perf_sample_data *data, struct pt_regs *regs); +static int set_hw_breakpoint(pid_t pid, uintptr_t addr, uint32_t type); +static int clear_hw_breakpoint(pid_t pid, uintptr_t addr); +static void clear_all_breakpoints(void); +static int get_process_registers(pid_t pid, ARM64_REGISTERS __user *regs); +static int set_process_registers(pid_t pid, ARM64_REGISTERS __user *regs); +static int suspend_process(pid_t pid); +static int resume_process(pid_t pid); +static int single_step_process(pid_t pid); +static struct suspended_process *find_suspended_process(pid_t pid); + +// 内部断点结构 +struct hw_breakpoint_entry { + HW_BREAKPOINT_INFO info; + struct list_head list; +}; + +// 物理地址翻译函数 +static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + pud_t *pud; + phys_addr_t page_addr; + uintptr_t page_offset; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) + p4d_t *p4d; + + pgd = pgd_offset(mm, va); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return 0; + + p4d = p4d_offset(pgd, va); + if (p4d_none(*p4d) || p4d_bad(*p4d)) + return 0; + + pud = pud_offset(p4d, va); +#else + pgd = pgd_offset(mm, va); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return 0; + + pud = pud_offset(pgd, va); +#endif + + if (pud_none(*pud) || pud_bad(*pud)) + return 0; + + pmd = pmd_offset(pud, va); + if (pmd_none(*pmd)) + return 0; + + pte = pte_offset_kernel(pmd, va); + if (pte_none(*pte) || !pte_present(*pte)) + return 0; + + page_addr = (phys_addr_t)(pte_pfn(*pte) << PAGE_SHIFT); + page_offset = va & (PAGE_SIZE - 1); + + return page_addr + page_offset; +} + +// 检查物理地址范围 +static inline bool is_valid_phys_addr_range(phys_addr_t addr, size_t size) +{ + return (addr + size <= virt_to_phys(high_memory)); +} + +// 读取物理地址 +static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size) +{ + void *mapped; + + if (!pfn_valid(__phys_to_pfn(pa))) + return false; + + if (!is_valid_phys_addr_range(pa, size)) + return false; + + mapped = ioremap_cache(pa, size); + if (!mapped) + return false; + + if (copy_to_user(buffer, mapped, size)) { + iounmap(mapped); + return false; + } + + iounmap(mapped); + return true; +} + +// 写入物理地址 +static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size) +{ + void *mapped; + + if (!pfn_valid(__phys_to_pfn(pa))) + return false; + + if (!is_valid_phys_addr_range(pa, size)) + return false; + + mapped = ioremap_cache(pa, size); + if (!mapped) + return false; + + if (copy_from_user(mapped, buffer, size)) { + iounmap(mapped); + return false; + } + + iounmap(mapped); + return true; +} + +// 读取进程内存 +static bool read_process_memory(pid_t pid, uintptr_t addr, + void __user *buffer, size_t size) +{ + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + phys_addr_t pa; + bool result = false; + struct vm_area_struct *vma; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return false; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return false; + } + + mm = get_task_mm(task); + put_pid(pid_struct); + + if (!mm) { + put_task_struct(task); + return false; + } + + // Linux 5.10使用mmap_lock而不是mmap_sem +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) + mmap_read_lock(mm); +#else + down_read(&mm->mmap_sem); +#endif + + pa = translate_linear_address(mm, addr); + + if (pa) { + result = read_physical_address(pa, buffer, size); + } else { + vma = find_vma(mm, addr); + if (vma) { + if (clear_user(buffer, size) == 0) { + result = true; + } + } + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) + mmap_read_unlock(mm); +#else + up_read(&mm->mmap_sem); +#endif + + mmput(mm); + put_task_struct(task); + return result; +} + +// 写入进程内存 +static bool write_process_memory(pid_t pid, uintptr_t addr, + const void __user *buffer, size_t size) +{ + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + phys_addr_t pa; + bool result = false; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return false; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return false; + } + + mm = get_task_mm(task); + put_pid(pid_struct); + + if (!mm) { + put_task_struct(task); + return false; + } + + // Linux 5.10使用mmap_lock而不是mmap_sem +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) + mmap_read_lock(mm); +#else + down_read(&mm->mmap_sem); +#endif + + pa = translate_linear_address(mm, addr); + + if (pa) { + result = write_physical_address(pa, buffer, size); + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) + mmap_read_unlock(mm); +#else + up_read(&mm->mmap_sem); +#endif + + mmput(mm); + put_task_struct(task); + return result; +} + +// 获取模块基址 +#define ARC_PATH_MAX 256 +static uintptr_t get_module_base(pid_t pid, const char *name) +{ + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + struct vm_area_struct *vma = NULL; + uintptr_t base_addr = 0; + int path_len; + char buf[ARC_PATH_MAX]; + char *path_nm; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return 0; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return 0; + } + + mm = get_task_mm(task); + put_pid(pid_struct); + + if (!mm) { + put_task_struct(task); + return 0; + } + + // Linux 5.10使用mmap_lock而不是mmap_sem +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) + mmap_read_lock(mm); +#else + down_read(&mm->mmap_sem); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) + struct vma_iterator vmi; + vma_iter_init(&vmi, mm, 0); + for_each_vma(vmi, vma) { +#else + for (vma = mm->mmap; vma; vma = vma->vm_next) { +#endif + if (!vma->vm_file) + continue; + + path_nm = file_path(vma->vm_file, buf, ARC_PATH_MAX - 1); + if (IS_ERR(path_nm)) + continue; + + path_len = strlen(path_nm); + if (path_len <= 0) + continue; + + if (strstr(path_nm, name) != NULL) { + base_addr = vma->vm_start; + break; + } + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) + mmap_read_unlock(mm); +#else + up_read(&mm->mmap_sem); +#endif + + mmput(mm); + put_task_struct(task); + return base_addr; +} + +// 查找暂停进程 +static struct suspended_process *find_suspended_process(pid_t pid) +{ + struct suspended_process *sp; + + list_for_each_entry(sp, &suspended_list, list) { + if (sp->pid == pid) { + return sp; + } + } + + return NULL; +} + +// 硬件断点处理函数 +static void hw_breakpoint_handler(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + struct hw_breakpoint_entry *entry = bp->overflow_handler_context; + struct task_struct *task; + struct suspended_process *sp; + + if (!entry) { + printk(KERN_ERR "No breakpoint context found\n"); + return; + } + + // 获取当前进程 + task = current; + + printk(KERN_INFO "[HW_BP] Breakpoint hit!\n"); + printk(KERN_INFO " PID: %d\n", entry->info.pid); + printk(KERN_INFO " Address: 0x%016lx\n", (unsigned long)entry->info.addr); + printk(KERN_INFO " Type: %u\n", entry->info.type); + printk(KERN_INFO " PC: 0x%016lx\n", (unsigned long)instruction_pointer(regs)); + + // 检查是否是被调试的进程 + if (task->pid != entry->info.pid) { + return; + } + + // 检查是否已经暂停 + sp = find_suspended_process(entry->info.pid); + if (sp && sp->stepping) { + // 单步执行模式,恢复执行 + sp->stepping = false; + printk(KERN_INFO "[HW_BP] Single step completed for PID %d\n", entry->info.pid); + } else { + // 暂停进程 + printk(KERN_INFO "[HW_BP] Suspending process %d at breakpoint\n", entry->info.pid); + // 设置进程状态为TASK_STOPPED + __set_current_state(TASK_STOPPED); + } +} + +// 设置硬件断点 +static int set_hw_breakpoint(pid_t pid, uintptr_t addr, uint32_t type) +{ + struct task_struct *task = NULL; + struct perf_event_attr attr; + struct hw_breakpoint_entry *entry; + struct pid *pid_struct = NULL; + struct hw_breakpoint_entry *tmp; + int bp_len; + int ret = 0; + + // 检查断点数量限制 + mutex_lock(&bp_mutex); + if (bp_count >= MAX_BREAKPOINTS) { + mutex_unlock(&bp_mutex); + printk(KERN_ERR "Maximum breakpoints reached (%d)\n", MAX_BREAKPOINTS); + return -ENOSPC; + } + mutex_unlock(&bp_mutex); + + // 查找进程 + pid_struct = find_get_pid(pid); + if (!pid_struct) + return -ESRCH; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return -ESRCH; + } + + mutex_lock(&bp_mutex); + + // 检查是否已存在断点 + list_for_each_entry(tmp, &bp_list, list) { + if (tmp->info.pid == pid && tmp->info.addr == addr) { + printk(KERN_INFO "Breakpoint already exists at 0x%lx for pid %d\n", + (unsigned long)addr, pid); + ret = -EEXIST; + goto out_unlock; + } + } + + // 分配断点条目 + entry = kmalloc(sizeof(struct hw_breakpoint_entry), GFP_KERNEL); + if (!entry) { + ret = -ENOMEM; + goto out_unlock; + } + + // 设置perf事件属性 + memset(&attr, 0, sizeof(struct perf_event_attr)); + attr.type = PERF_TYPE_BREAKPOINT; + attr.size = sizeof(struct perf_event_attr); + + // 设置断点类型和大小 + bp_len = 4; // 默认4字节 + + switch (type) { + case BP_TYPE_INST: + attr.bp_type = HW_BREAKPOINT_X; + bp_len = 4; + break; + case BP_TYPE_READ: + attr.bp_type = HW_BREAKPOINT_R; + bp_len = 8; + break; + case BP_TYPE_WRITE: + attr.bp_type = HW_BREAKPOINT_W; + bp_len = 8; + break; + case BP_TYPE_RW: + attr.bp_type = HW_BREAKPOINT_RW; + bp_len = 8; + break; + default: + kfree(entry); + ret = -EINVAL; + goto out_unlock; + } + + attr.bp_addr = addr; + attr.bp_len = bp_len; + attr.sample_period = 1; + attr.sample_type = PERF_SAMPLE_IP; + attr.wakeup_events = 1; + attr.exclude_kernel = 1; + attr.exclude_hv = 1; + + // 创建perf事件 + entry->info.pe = perf_event_create_kernel_counter(&attr, -1, task, + hw_breakpoint_handler, entry); + + if (IS_ERR(entry->info.pe)) { + ret = PTR_ERR(entry->info.pe); + printk(KERN_ERR "Failed to create hardware breakpoint: %d\n", ret); + kfree(entry); + goto out_unlock; + } + + // 初始化断点信息 + entry->info.pid = pid; + entry->info.addr = addr; + entry->info.type = type; + entry->info.active = true; + INIT_LIST_HEAD(&entry->list); + + // 添加到链表 + list_add_tail(&entry->list, &bp_list); + bp_count++; + + // 启用断点 + perf_event_enable(entry->info.pe); + + printk(KERN_INFO "Hardware breakpoint set at 0x%lx for pid %d (type: %u)\n", + (unsigned long)addr, pid, type); + + ret = 0; + +out_unlock: + mutex_unlock(&bp_mutex); + if (task) + put_task_struct(task); + if (pid_struct) + put_pid(pid_struct); + return ret; +} + +// 清除硬件断点 +static int clear_hw_breakpoint(pid_t pid, uintptr_t addr) +{ + struct hw_breakpoint_entry *entry, *tmp; + int ret = -ENOENT; + + mutex_lock(&bp_mutex); + + list_for_each_entry_safe(entry, tmp, &bp_list, list) { + if (entry->info.pid == pid && entry->info.addr == addr) { + // 禁用并释放perf事件 + if (entry->info.pe) { + perf_event_disable(entry->info.pe); + perf_event_release_kernel(entry->info.pe); + } + + // 从链表删除 + list_del(&entry->list); + kfree(entry); + bp_count--; + + printk(KERN_INFO "Hardware breakpoint cleared at 0x%lx for pid %d\n", + (unsigned long)addr, pid); + ret = 0; + break; + } + } + + mutex_unlock(&bp_mutex); + return ret; +} + +// 清除所有断点 +static void clear_all_breakpoints(void) +{ + struct hw_breakpoint_entry *entry, *tmp; + + mutex_lock(&bp_mutex); + + list_for_each_entry_safe(entry, tmp, &bp_list, list) { + if (entry->info.pe) { + perf_event_disable(entry->info.pe); + perf_event_release_kernel(entry->info.pe); + } + + list_del(&entry->list); + kfree(entry); + } + + bp_count = 0; + mutex_unlock(&bp_mutex); + + printk(KERN_INFO "All hardware breakpoints cleared\n"); +} + +// 获取进程寄存器 +static int get_process_registers(pid_t pid, ARM64_REGISTERS __user *regs) +{ + struct task_struct *task = NULL; + struct pid *pid_struct = NULL; + struct pt_regs *task_regs; + ARM64_REGISTERS kernel_regs; + int i, ret = 0; + + if (!regs) + return -EFAULT; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return -ESRCH; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return -ESRCH; + } + + // 获取进程的寄存器 + task_regs = task_pt_regs(task); + + if (!task_regs) { + ret = -EFAULT; + goto out; + } + + // 填充寄存器结构 + memset(&kernel_regs, 0, sizeof(kernel_regs)); + + // 复制通用寄存器 X0-X30 + for (i = 0; i < 31; i++) { + kernel_regs.x[i] = task_regs->regs[i]; + } + + // 复制特殊寄存器 + kernel_regs.fp = task_regs->regs[29]; // X29作为帧指针 + kernel_regs.lr = task_regs->regs[30]; // X30作为链接寄存器 + kernel_regs.sp = task_regs->sp; + kernel_regs.pc = task_regs->pc; + kernel_regs.pstate = task_regs->pstate; + + // 复制到用户空间 + if (copy_to_user(regs, &kernel_regs, sizeof(kernel_regs))) { + ret = -EFAULT; + goto out; + } + + printk(KERN_INFO "Registers read for PID %d, PC=0x%016lx\n", + pid, (unsigned long)kernel_regs.pc); + +out: + put_pid(pid_struct); + if (task) + put_task_struct(task); + return ret; +} + +// 设置进程寄存器 +static int set_process_registers(pid_t pid, ARM64_REGISTERS __user *regs) +{ + struct task_struct *task = NULL; + struct pid *pid_struct = NULL; + struct pt_regs *task_regs; + ARM64_REGISTERS kernel_regs; + int i, ret = 0; + + if (!regs) + return -EFAULT; + + // 从用户空间复制寄存器数据 + if (copy_from_user(&kernel_regs, regs, sizeof(kernel_regs))) { + return -EFAULT; + } + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return -ESRCH; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return -ESRCH; + } + + // 获取进程的寄存器 + task_regs = task_pt_regs(task); + + if (!task_regs) { + ret = -EFAULT; + goto out; + } + + // 设置通用寄存器 X0-X30 + for (i = 0; i < 31; i++) { + task_regs->regs[i] = kernel_regs.x[i]; + } + + // 设置特殊寄存器 + task_regs->regs[29] = kernel_regs.fp; // 帧指针 + task_regs->regs[30] = kernel_regs.lr; // 链接寄存器 + task_regs->sp = kernel_regs.sp; + task_regs->pc = kernel_regs.pc; + task_regs->pstate = kernel_regs.pstate; + + printk(KERN_INFO "Registers set for PID %d, PC=0x%016lx\n", + pid, (unsigned long)kernel_regs.pc); + +out: + put_pid(pid_struct); + if (task) + put_task_struct(task); + return ret; +} + +// 暂停进程 +static int suspend_process(pid_t pid) +{ + struct task_struct *task = NULL; + struct pid *pid_struct = NULL; + struct suspended_process *sp; + int ret = 0; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return -ESRCH; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return -ESRCH; + } + + // 检查是否已经暂停 + sp = find_suspended_process(pid); + if (sp) { + printk(KERN_INFO "Process %d is already suspended\n", pid); + ret = -EALREADY; + goto out; + } + + // 分配暂停进程结构 + sp = kmalloc(sizeof(struct suspended_process), GFP_KERNEL); + if (!sp) { + ret = -ENOMEM; + goto out; + } + + // 初始化暂停进程信息 + sp->pid = pid; + sp->task = task; + sp->stepping = false; + INIT_LIST_HEAD(&sp->list); + + // 添加到暂停列表 + list_add_tail(&sp->list, &suspended_list); + + // 发送SIGSTOP信号暂停进程 + ret = send_sig(SIGSTOP, task, 1); + if (ret) { + list_del(&sp->list); + kfree(sp); + goto out; + } + + printk(KERN_INFO "Process %d suspended\n", pid); + +out: + put_pid(pid_struct); + if (ret && task) + put_task_struct(task); + return ret; +} + +// 恢复进程 +static int resume_process(pid_t pid) +{ + struct task_struct *task = NULL; + struct pid *pid_struct = NULL; + struct suspended_process *sp; + int ret = 0; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return -ESRCH; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return -ESRCH; + } + + // 查找暂停进程 + sp = find_suspended_process(pid); + if (!sp) { + printk(KERN_INFO "Process %d is not suspended\n", pid); + ret = -ENOENT; + goto out; + } + + // 发送SIGCONT信号恢复进程 + ret = send_sig(SIGCONT, task, 1); + if (ret == 0) { + // 从暂停列表中移除 + list_del(&sp->list); + kfree(sp); + put_task_struct(task); // 释放之前获取的引用 + printk(KERN_INFO "Process %d resumed\n", pid); + } + +out: + put_pid(pid_struct); + if (!sp && task) // 如果没有找到暂停项,释放task引用 + put_task_struct(task); + return ret; +} + +// 单步执行 +static int single_step_process(pid_t pid) +{ + struct suspended_process *sp; + + // 查找暂停进程 + sp = find_suspended_process(pid); + if (!sp) { + printk(KERN_INFO "Process %d is not suspended\n", pid); + return -ENOENT; + } + + // 设置单步执行标志 + sp->stepping = true; + + // 恢复进程执行一条指令 + // 注意:ARM64的单步执行通常通过设置调试寄存器实现 + // 这里简化为恢复进程,依靠断点再次捕获 + + return resume_process(pid); +} + +// IOCTL分发函数 +static int dispatch_open(struct inode *node, struct file *file) +{ + return 0; +} + +static int dispatch_close(struct inode *node, struct file *file) +{ + // 清理所有暂停进程 + struct suspended_process *sp, *tmp; + + list_for_each_entry_safe(sp, tmp, &suspended_list, list) { + // 恢复进程 + resume_process(sp->pid); + } + + return 0; +} + +static long dispatch_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + static char key[256] = {0}; + static bool is_verified = false; + long ret = 0; + + switch (cmd) { + case OP_INIT_KEY: + if (!is_verified) { + if (copy_from_user(key, (void __user *)arg, sizeof(key) - 1) == 0) { + key[sizeof(key) - 1] = '\0'; + is_verified = true; + printk(KERN_INFO "Key initialized successfully\n"); + } else { + return -EFAULT; + } + } + break; + + case OP_READ_MEM: { + COPY_MEMORY cm; + + if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) + return -EFAULT; + + if (!read_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) + return -EIO; + + break; + } + + case OP_WRITE_MEM: { + COPY_MEMORY cm; + + if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) + return -EFAULT; + + if (!write_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) + return -EIO; + + break; + } + + case OP_MODULE_BASE: { + MODULE_BASE mb; + char module_name[256]; + + if (copy_from_user(&mb, (void __user *)arg, sizeof(mb))) + return -EFAULT; + + if (!mb.name) + return -EFAULT; + + if (copy_from_user(module_name, mb.name, sizeof(module_name) - 1)) + return -EFAULT; + module_name[sizeof(module_name) - 1] = '\0'; + + mb.base = get_module_base(mb.pid, module_name); + + if (copy_to_user((void __user *)arg, &mb, sizeof(mb))) + return -EFAULT; + + break; + } + + case OP_SET_BREAKPOINT: { + BREAKPOINT_OPERATION bp_op; + + if (copy_from_user(&bp_op, (void __user *)arg, sizeof(bp_op))) + return -EFAULT; + + ret = set_hw_breakpoint(bp_op.pid, bp_op.addr, bp_op.type); + if (ret < 0) + return ret; + + break; + } + + case OP_CLEAR_BREAKPOINT: { + BREAKPOINT_OPERATION bp_op; + + if (copy_from_user(&bp_op, (void __user *)arg, sizeof(bp_op))) + return -EFAULT; + + ret = clear_hw_breakpoint(bp_op.pid, bp_op.addr); + if (ret < 0) + return ret; + + break; + } + + case OP_LIST_BREAKPOINTS: { + struct hw_breakpoint_entry *entry; + HW_BREAKPOINT_INFO info; + int idx = 0; + + mutex_lock(&bp_mutex); + + list_for_each_entry(entry, &bp_list, list) { + if (copy_to_user((void __user *)(arg + idx * sizeof(info)), + &entry->info, sizeof(info))) { + mutex_unlock(&bp_mutex); + return -EFAULT; + } + idx++; + } + + mutex_unlock(&bp_mutex); + break; + } + + case OP_CLEAR_ALL_BREAKPOINTS: + clear_all_breakpoints(); + break; + + case OP_GET_REGISTERS: { + REGISTER_OPERATION reg_op; + + if (copy_from_user(®_op, (void __user *)arg, sizeof(reg_op))) + return -EFAULT; + + if (!reg_op.regs) + return -EFAULT; + + ret = get_process_registers(reg_op.pid, reg_op.regs); + if (ret < 0) + return ret; + + break; + } + + case OP_SET_REGISTERS: { + REGISTER_OPERATION reg_op; + + if (copy_from_user(®_op, (void __user *)arg, sizeof(reg_op))) + return -EFAULT; + + if (!reg_op.regs) + return -EFAULT; + + ret = set_process_registers(reg_op.pid, reg_op.regs); + if (ret < 0) + return ret; + + break; + } + + case OP_SUSPEND_PROCESS: { + PROCESS_CONTROL pc; + + if (copy_from_user(&pc, (void __user *)arg, sizeof(pc))) + return -EFAULT; + + ret = suspend_process(pc.pid); + if (ret < 0) + return ret; + + break; + } + + case OP_RESUME_PROCESS: { + PROCESS_CONTROL pc; + + if (copy_from_user(&pc, (void __user *)arg, sizeof(pc))) + return -EFAULT; + + ret = resume_process(pc.pid); + if (ret < 0) + return ret; + + break; + } + + case OP_SINGLE_STEP: { + PROCESS_CONTROL pc; + + if (copy_from_user(&pc, (void __user *)arg, sizeof(pc))) + return -EFAULT; + + ret = single_step_process(pc.pid); + if (ret < 0) + return ret; + + break; + } + + default: + return -ENOTTY; + } + + return ret; +} + +// 文件操作结构 +static const struct file_operations dispatch_fops = { + .owner = THIS_MODULE, + .open = dispatch_open, + .release = dispatch_close, + .unlocked_ioctl = dispatch_ioctl, + .compat_ioctl = dispatch_ioctl, +}; + +// misc设备定义 +static struct miscdevice misc_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = DEVICE_NAME, + .fops = &dispatch_fops, + .mode = 0666, +}; + +// 模块初始化 +static int __init driver_entry(void) +{ + int ret; + int breakpoint_slots = 0; + + printk(KERN_INFO "ARM64 Hardware Breakpoint Module loading...\n"); + +#ifndef CONFIG_ARM64 + printk(KERN_ERR "This module is for ARM64 architecture only!\n"); + return -ENODEV; +#endif + + // 检查是否支持硬件断点 + // 注意:hw_breakpoint_slots函数可能没有导出,我们使用保守的默认值 +#ifdef CONFIG_HAVE_HW_BREAKPOINT + printk(KERN_INFO "Hardware breakpoint support detected\n"); + + // 尝试通过配置推断断点槽数量 + // ARM64通常支持4-16个硬件断点 +#if defined(CONFIG_ARM64_HW_BREAKPOINT) + // 如果定义了ARM64_HW_BREAKPOINT,通常支持更多断点 + breakpoint_slots = 16; +#else + // 保守估计 + breakpoint_slots = 4; +#endif + + printk(KERN_INFO "Estimated hardware breakpoint slots: %d\n", breakpoint_slots); +#else + printk(KERN_ERR "Hardware breakpoints not supported on this CPU\n"); + return -ENODEV; +#endif + + // 初始化暂停进程列表 + INIT_LIST_HEAD(&suspended_list); + + ret = misc_register(&misc_dev); + if (ret) { + printk(KERN_ERR "Failed to register misc device: %d\n", ret); + return ret; + } + + printk(KERN_INFO "ARM64 Hardware Breakpoint Module loaded. Device: /dev/%s\n", DEVICE_NAME); + printk(KERN_INFO "Maximum hardware breakpoints: %d\n", MAX_BREAKPOINTS); + + return 0; +} + +// 模块卸载 +static void __exit driver_unload(void) +{ + struct suspended_process *sp, *tmp; + + printk(KERN_INFO "ARM64 Hardware Breakpoint Module unloading...\n"); + + // 恢复所有暂停进程 + list_for_each_entry_safe(sp, tmp, &suspended_list, list) { + resume_process(sp->pid); + } + + // 清除所有断点 + clear_all_breakpoints(); + + // 注销设备 + misc_deregister(&misc_dev); + + printk(KERN_INFO "ARM64 Hardware Breakpoint Module unloaded\n"); +} + +module_init(driver_entry); +module_exit(driver_unload); + +MODULE_DESCRIPTION("ARM64 Hardware Breakpoint Kernel Module with Process Control"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("陈依涵"); +MODULE_VERSION("1.0"); \ No newline at end of file diff --git a/code/arm64_hw_bp.h b/code/arm64_hw_bp.h new file mode 100644 index 00000000..2f6d4b75 --- /dev/null +++ b/code/arm64_hw_bp.h @@ -0,0 +1,46 @@ +#ifndef _ARM64_HW_BP_H +#define _ARM64_HW_BP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) +#include +#include +#endif + +// 设备名称 +#define DEVICE_NAME "YihanChan" + +// 断点类型定义 +enum BP_TYPES { + BP_TYPE_INST = 0, // 指令执行断点 + BP_TYPE_READ = 1, // 数据读断点 + BP_TYPE_WRITE = 2, // 数据写断点 + BP_TYPE_RW = 3 // 数据读写断点 +}; + +#endif /* _ARM64_HW_BP_H */ \ No newline at end of file From 51820a02a94161050f0664c947a8ddccdf75ffd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:06:05 +0800 Subject: [PATCH 19/35] Delete code/arm64_hw_bp.c --- code/arm64_hw_bp.c | 1186 -------------------------------------------- 1 file changed, 1186 deletions(-) delete mode 100644 code/arm64_hw_bp.c diff --git a/code/arm64_hw_bp.c b/code/arm64_hw_bp.c deleted file mode 100644 index 01d81f12..00000000 --- a/code/arm64_hw_bp.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* - * ARM64硬件断点内核模块 - 修复hw_breakpoint_slots问题 - * 适配Linux 5.10内核 - */ - -#include "arm64_hw_bp.h" - -// 断点数据结构 -typedef struct _HW_BREAKPOINT_INFO { - pid_t pid; - uintptr_t addr; - uint32_t type; // 断点类型 - bool active; - struct perf_event *pe; // perf事件 -} HW_BREAKPOINT_INFO, *PHW_BREAKPOINT_INFO; - -typedef struct _BREAKPOINT_OPERATION { - pid_t pid; - uintptr_t addr; - uint32_t type; -} BREAKPOINT_OPERATION, *PBREAKPOINT_OPERATION; - -typedef struct _COPY_MEMORY { - pid_t pid; - uintptr_t addr; - void __user *buffer; - size_t size; -} COPY_MEMORY, *PCOPY_MEMORY; - -typedef struct _MODULE_BASE { - pid_t pid; - char __user *name; - uintptr_t base; -} MODULE_BASE, *PMODULE_BASE; - -// ARM64寄存器结构 -typedef struct _ARM64_REGISTERS { - uint64_t x[31]; // 通用寄存器 X0-X30 - uint64_t fp; // 帧指针 - uint64_t lr; // 链接寄存器 - uint64_t sp; // 栈指针 - uint64_t pc; // 程序计数器 - uint64_t pstate; // 处理器状态 - uint64_t v[32]; // 向量寄存器 (可选) -} ARM64_REGISTERS, *PARM64_REGISTERS; - -typedef struct _REGISTER_OPERATION { - pid_t pid; - ARM64_REGISTERS __user *regs; - bool read; // true: 读取寄存器, false: 写入寄存器 -} REGISTER_OPERATION, *PREGISTER_OPERATION; - -typedef struct _PROCESS_CONTROL { - pid_t pid; - bool suspend; // true: 暂停, false: 恢复 -} PROCESS_CONTROL, *PPROCESS_CONTROL; - -// IOCTL操作码 -enum HW_BREAKPOINT_OPERATIONS { - OP_INIT_KEY = 0x800, - OP_READ_MEM = 0x801, - OP_WRITE_MEM = 0x802, - OP_MODULE_BASE = 0x803, - OP_SET_BREAKPOINT = 0x804, - OP_CLEAR_BREAKPOINT = 0x805, - OP_LIST_BREAKPOINTS = 0x806, - OP_CLEAR_ALL_BREAKPOINTS = 0x807, - OP_GET_REGISTERS = 0x808, - OP_SET_REGISTERS = 0x809, - OP_SUSPEND_PROCESS = 0x80A, - OP_RESUME_PROCESS = 0x80B, - OP_SINGLE_STEP = 0x80C, -}; - -// 暂停进程信息结构 -struct suspended_process { - pid_t pid; - struct task_struct *task; - struct list_head list; - bool stepping; // 单步执行模式 -}; - -// 全局变量 -static DEFINE_MUTEX(bp_mutex); -static LIST_HEAD(bp_list); -static LIST_HEAD(suspended_list); -static int bp_count = 0; -#define MAX_BREAKPOINTS 16 - -// 函数声明 -static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va); -static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size); -static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size); -static bool read_process_memory(pid_t pid, uintptr_t addr, void __user *buffer, size_t size); -static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user *buffer, size_t size); -static uintptr_t get_module_base(pid_t pid, const char *name); -static void hw_breakpoint_handler(struct perf_event *bp, struct perf_sample_data *data, struct pt_regs *regs); -static int set_hw_breakpoint(pid_t pid, uintptr_t addr, uint32_t type); -static int clear_hw_breakpoint(pid_t pid, uintptr_t addr); -static void clear_all_breakpoints(void); -static int get_process_registers(pid_t pid, ARM64_REGISTERS __user *regs); -static int set_process_registers(pid_t pid, ARM64_REGISTERS __user *regs); -static int suspend_process(pid_t pid); -static int resume_process(pid_t pid); -static int single_step_process(pid_t pid); -static struct suspended_process *find_suspended_process(pid_t pid); - -// 内部断点结构 -struct hw_breakpoint_entry { - HW_BREAKPOINT_INFO info; - struct list_head list; -}; - -// 物理地址翻译函数 -static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - pud_t *pud; - phys_addr_t page_addr; - uintptr_t page_offset; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) - p4d_t *p4d; - - pgd = pgd_offset(mm, va); - if (pgd_none(*pgd) || pgd_bad(*pgd)) - return 0; - - p4d = p4d_offset(pgd, va); - if (p4d_none(*p4d) || p4d_bad(*p4d)) - return 0; - - pud = pud_offset(p4d, va); -#else - pgd = pgd_offset(mm, va); - if (pgd_none(*pgd) || pgd_bad(*pgd)) - return 0; - - pud = pud_offset(pgd, va); -#endif - - if (pud_none(*pud) || pud_bad(*pud)) - return 0; - - pmd = pmd_offset(pud, va); - if (pmd_none(*pmd)) - return 0; - - pte = pte_offset_kernel(pmd, va); - if (pte_none(*pte) || !pte_present(*pte)) - return 0; - - page_addr = (phys_addr_t)(pte_pfn(*pte) << PAGE_SHIFT); - page_offset = va & (PAGE_SIZE - 1); - - return page_addr + page_offset; -} - -// 检查物理地址范围 -static inline bool is_valid_phys_addr_range(phys_addr_t addr, size_t size) -{ - return (addr + size <= virt_to_phys(high_memory)); -} - -// 读取物理地址 -static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size) -{ - void *mapped; - - if (!pfn_valid(__phys_to_pfn(pa))) - return false; - - if (!is_valid_phys_addr_range(pa, size)) - return false; - - mapped = ioremap_cache(pa, size); - if (!mapped) - return false; - - if (copy_to_user(buffer, mapped, size)) { - iounmap(mapped); - return false; - } - - iounmap(mapped); - return true; -} - -// 写入物理地址 -static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size) -{ - void *mapped; - - if (!pfn_valid(__phys_to_pfn(pa))) - return false; - - if (!is_valid_phys_addr_range(pa, size)) - return false; - - mapped = ioremap_cache(pa, size); - if (!mapped) - return false; - - if (copy_from_user(mapped, buffer, size)) { - iounmap(mapped); - return false; - } - - iounmap(mapped); - return true; -} - -// 读取进程内存 -static bool read_process_memory(pid_t pid, uintptr_t addr, - void __user *buffer, size_t size) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - phys_addr_t pa; - bool result = false; - struct vm_area_struct *vma; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return false; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return false; - } - - mm = get_task_mm(task); - put_pid(pid_struct); - - if (!mm) { - put_task_struct(task); - return false; - } - - // Linux 5.10使用mmap_lock而不是mmap_sem -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) - mmap_read_lock(mm); -#else - down_read(&mm->mmap_sem); -#endif - - pa = translate_linear_address(mm, addr); - - if (pa) { - result = read_physical_address(pa, buffer, size); - } else { - vma = find_vma(mm, addr); - if (vma) { - if (clear_user(buffer, size) == 0) { - result = true; - } - } - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) - mmap_read_unlock(mm); -#else - up_read(&mm->mmap_sem); -#endif - - mmput(mm); - put_task_struct(task); - return result; -} - -// 写入进程内存 -static bool write_process_memory(pid_t pid, uintptr_t addr, - const void __user *buffer, size_t size) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - phys_addr_t pa; - bool result = false; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return false; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return false; - } - - mm = get_task_mm(task); - put_pid(pid_struct); - - if (!mm) { - put_task_struct(task); - return false; - } - - // Linux 5.10使用mmap_lock而不是mmap_sem -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) - mmap_read_lock(mm); -#else - down_read(&mm->mmap_sem); -#endif - - pa = translate_linear_address(mm, addr); - - if (pa) { - result = write_physical_address(pa, buffer, size); - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) - mmap_read_unlock(mm); -#else - up_read(&mm->mmap_sem); -#endif - - mmput(mm); - put_task_struct(task); - return result; -} - -// 获取模块基址 -#define ARC_PATH_MAX 256 -static uintptr_t get_module_base(pid_t pid, const char *name) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - struct vm_area_struct *vma = NULL; - uintptr_t base_addr = 0; - int path_len; - char buf[ARC_PATH_MAX]; - char *path_nm; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return 0; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return 0; - } - - mm = get_task_mm(task); - put_pid(pid_struct); - - if (!mm) { - put_task_struct(task); - return 0; - } - - // Linux 5.10使用mmap_lock而不是mmap_sem -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) - mmap_read_lock(mm); -#else - down_read(&mm->mmap_sem); -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) - struct vma_iterator vmi; - vma_iter_init(&vmi, mm, 0); - for_each_vma(vmi, vma) { -#else - for (vma = mm->mmap; vma; vma = vma->vm_next) { -#endif - if (!vma->vm_file) - continue; - - path_nm = file_path(vma->vm_file, buf, ARC_PATH_MAX - 1); - if (IS_ERR(path_nm)) - continue; - - path_len = strlen(path_nm); - if (path_len <= 0) - continue; - - if (strstr(path_nm, name) != NULL) { - base_addr = vma->vm_start; - break; - } - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) - mmap_read_unlock(mm); -#else - up_read(&mm->mmap_sem); -#endif - - mmput(mm); - put_task_struct(task); - return base_addr; -} - -// 查找暂停进程 -static struct suspended_process *find_suspended_process(pid_t pid) -{ - struct suspended_process *sp; - - list_for_each_entry(sp, &suspended_list, list) { - if (sp->pid == pid) { - return sp; - } - } - - return NULL; -} - -// 硬件断点处理函数 -static void hw_breakpoint_handler(struct perf_event *bp, - struct perf_sample_data *data, - struct pt_regs *regs) -{ - struct hw_breakpoint_entry *entry = bp->overflow_handler_context; - struct task_struct *task; - struct suspended_process *sp; - - if (!entry) { - printk(KERN_ERR "No breakpoint context found\n"); - return; - } - - // 获取当前进程 - task = current; - - printk(KERN_INFO "[HW_BP] Breakpoint hit!\n"); - printk(KERN_INFO " PID: %d\n", entry->info.pid); - printk(KERN_INFO " Address: 0x%016lx\n", (unsigned long)entry->info.addr); - printk(KERN_INFO " Type: %u\n", entry->info.type); - printk(KERN_INFO " PC: 0x%016lx\n", (unsigned long)instruction_pointer(regs)); - - // 检查是否是被调试的进程 - if (task->pid != entry->info.pid) { - return; - } - - // 检查是否已经暂停 - sp = find_suspended_process(entry->info.pid); - if (sp && sp->stepping) { - // 单步执行模式,恢复执行 - sp->stepping = false; - printk(KERN_INFO "[HW_BP] Single step completed for PID %d\n", entry->info.pid); - } else { - // 暂停进程 - printk(KERN_INFO "[HW_BP] Suspending process %d at breakpoint\n", entry->info.pid); - // 设置进程状态为TASK_STOPPED - __set_current_state(TASK_STOPPED); - } -} - -// 设置硬件断点 -static int set_hw_breakpoint(pid_t pid, uintptr_t addr, uint32_t type) -{ - struct task_struct *task = NULL; - struct perf_event_attr attr; - struct hw_breakpoint_entry *entry; - struct pid *pid_struct = NULL; - struct hw_breakpoint_entry *tmp; - int bp_len; - int ret = 0; - - // 检查断点数量限制 - mutex_lock(&bp_mutex); - if (bp_count >= MAX_BREAKPOINTS) { - mutex_unlock(&bp_mutex); - printk(KERN_ERR "Maximum breakpoints reached (%d)\n", MAX_BREAKPOINTS); - return -ENOSPC; - } - mutex_unlock(&bp_mutex); - - // 查找进程 - pid_struct = find_get_pid(pid); - if (!pid_struct) - return -ESRCH; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return -ESRCH; - } - - mutex_lock(&bp_mutex); - - // 检查是否已存在断点 - list_for_each_entry(tmp, &bp_list, list) { - if (tmp->info.pid == pid && tmp->info.addr == addr) { - printk(KERN_INFO "Breakpoint already exists at 0x%lx for pid %d\n", - (unsigned long)addr, pid); - ret = -EEXIST; - goto out_unlock; - } - } - - // 分配断点条目 - entry = kmalloc(sizeof(struct hw_breakpoint_entry), GFP_KERNEL); - if (!entry) { - ret = -ENOMEM; - goto out_unlock; - } - - // 设置perf事件属性 - memset(&attr, 0, sizeof(struct perf_event_attr)); - attr.type = PERF_TYPE_BREAKPOINT; - attr.size = sizeof(struct perf_event_attr); - - // 设置断点类型和大小 - bp_len = 4; // 默认4字节 - - switch (type) { - case BP_TYPE_INST: - attr.bp_type = HW_BREAKPOINT_X; - bp_len = 4; - break; - case BP_TYPE_READ: - attr.bp_type = HW_BREAKPOINT_R; - bp_len = 8; - break; - case BP_TYPE_WRITE: - attr.bp_type = HW_BREAKPOINT_W; - bp_len = 8; - break; - case BP_TYPE_RW: - attr.bp_type = HW_BREAKPOINT_RW; - bp_len = 8; - break; - default: - kfree(entry); - ret = -EINVAL; - goto out_unlock; - } - - attr.bp_addr = addr; - attr.bp_len = bp_len; - attr.sample_period = 1; - attr.sample_type = PERF_SAMPLE_IP; - attr.wakeup_events = 1; - attr.exclude_kernel = 1; - attr.exclude_hv = 1; - - // 创建perf事件 - entry->info.pe = perf_event_create_kernel_counter(&attr, -1, task, - hw_breakpoint_handler, entry); - - if (IS_ERR(entry->info.pe)) { - ret = PTR_ERR(entry->info.pe); - printk(KERN_ERR "Failed to create hardware breakpoint: %d\n", ret); - kfree(entry); - goto out_unlock; - } - - // 初始化断点信息 - entry->info.pid = pid; - entry->info.addr = addr; - entry->info.type = type; - entry->info.active = true; - INIT_LIST_HEAD(&entry->list); - - // 添加到链表 - list_add_tail(&entry->list, &bp_list); - bp_count++; - - // 启用断点 - perf_event_enable(entry->info.pe); - - printk(KERN_INFO "Hardware breakpoint set at 0x%lx for pid %d (type: %u)\n", - (unsigned long)addr, pid, type); - - ret = 0; - -out_unlock: - mutex_unlock(&bp_mutex); - if (task) - put_task_struct(task); - if (pid_struct) - put_pid(pid_struct); - return ret; -} - -// 清除硬件断点 -static int clear_hw_breakpoint(pid_t pid, uintptr_t addr) -{ - struct hw_breakpoint_entry *entry, *tmp; - int ret = -ENOENT; - - mutex_lock(&bp_mutex); - - list_for_each_entry_safe(entry, tmp, &bp_list, list) { - if (entry->info.pid == pid && entry->info.addr == addr) { - // 禁用并释放perf事件 - if (entry->info.pe) { - perf_event_disable(entry->info.pe); - perf_event_release_kernel(entry->info.pe); - } - - // 从链表删除 - list_del(&entry->list); - kfree(entry); - bp_count--; - - printk(KERN_INFO "Hardware breakpoint cleared at 0x%lx for pid %d\n", - (unsigned long)addr, pid); - ret = 0; - break; - } - } - - mutex_unlock(&bp_mutex); - return ret; -} - -// 清除所有断点 -static void clear_all_breakpoints(void) -{ - struct hw_breakpoint_entry *entry, *tmp; - - mutex_lock(&bp_mutex); - - list_for_each_entry_safe(entry, tmp, &bp_list, list) { - if (entry->info.pe) { - perf_event_disable(entry->info.pe); - perf_event_release_kernel(entry->info.pe); - } - - list_del(&entry->list); - kfree(entry); - } - - bp_count = 0; - mutex_unlock(&bp_mutex); - - printk(KERN_INFO "All hardware breakpoints cleared\n"); -} - -// 获取进程寄存器 -static int get_process_registers(pid_t pid, ARM64_REGISTERS __user *regs) -{ - struct task_struct *task = NULL; - struct pid *pid_struct = NULL; - struct pt_regs *task_regs; - ARM64_REGISTERS kernel_regs; - int i, ret = 0; - - if (!regs) - return -EFAULT; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return -ESRCH; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return -ESRCH; - } - - // 获取进程的寄存器 - task_regs = task_pt_regs(task); - - if (!task_regs) { - ret = -EFAULT; - goto out; - } - - // 填充寄存器结构 - memset(&kernel_regs, 0, sizeof(kernel_regs)); - - // 复制通用寄存器 X0-X30 - for (i = 0; i < 31; i++) { - kernel_regs.x[i] = task_regs->regs[i]; - } - - // 复制特殊寄存器 - kernel_regs.fp = task_regs->regs[29]; // X29作为帧指针 - kernel_regs.lr = task_regs->regs[30]; // X30作为链接寄存器 - kernel_regs.sp = task_regs->sp; - kernel_regs.pc = task_regs->pc; - kernel_regs.pstate = task_regs->pstate; - - // 复制到用户空间 - if (copy_to_user(regs, &kernel_regs, sizeof(kernel_regs))) { - ret = -EFAULT; - goto out; - } - - printk(KERN_INFO "Registers read for PID %d, PC=0x%016lx\n", - pid, (unsigned long)kernel_regs.pc); - -out: - put_pid(pid_struct); - if (task) - put_task_struct(task); - return ret; -} - -// 设置进程寄存器 -static int set_process_registers(pid_t pid, ARM64_REGISTERS __user *regs) -{ - struct task_struct *task = NULL; - struct pid *pid_struct = NULL; - struct pt_regs *task_regs; - ARM64_REGISTERS kernel_regs; - int i, ret = 0; - - if (!regs) - return -EFAULT; - - // 从用户空间复制寄存器数据 - if (copy_from_user(&kernel_regs, regs, sizeof(kernel_regs))) { - return -EFAULT; - } - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return -ESRCH; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return -ESRCH; - } - - // 获取进程的寄存器 - task_regs = task_pt_regs(task); - - if (!task_regs) { - ret = -EFAULT; - goto out; - } - - // 设置通用寄存器 X0-X30 - for (i = 0; i < 31; i++) { - task_regs->regs[i] = kernel_regs.x[i]; - } - - // 设置特殊寄存器 - task_regs->regs[29] = kernel_regs.fp; // 帧指针 - task_regs->regs[30] = kernel_regs.lr; // 链接寄存器 - task_regs->sp = kernel_regs.sp; - task_regs->pc = kernel_regs.pc; - task_regs->pstate = kernel_regs.pstate; - - printk(KERN_INFO "Registers set for PID %d, PC=0x%016lx\n", - pid, (unsigned long)kernel_regs.pc); - -out: - put_pid(pid_struct); - if (task) - put_task_struct(task); - return ret; -} - -// 暂停进程 -static int suspend_process(pid_t pid) -{ - struct task_struct *task = NULL; - struct pid *pid_struct = NULL; - struct suspended_process *sp; - int ret = 0; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return -ESRCH; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return -ESRCH; - } - - // 检查是否已经暂停 - sp = find_suspended_process(pid); - if (sp) { - printk(KERN_INFO "Process %d is already suspended\n", pid); - ret = -EALREADY; - goto out; - } - - // 分配暂停进程结构 - sp = kmalloc(sizeof(struct suspended_process), GFP_KERNEL); - if (!sp) { - ret = -ENOMEM; - goto out; - } - - // 初始化暂停进程信息 - sp->pid = pid; - sp->task = task; - sp->stepping = false; - INIT_LIST_HEAD(&sp->list); - - // 添加到暂停列表 - list_add_tail(&sp->list, &suspended_list); - - // 发送SIGSTOP信号暂停进程 - ret = send_sig(SIGSTOP, task, 1); - if (ret) { - list_del(&sp->list); - kfree(sp); - goto out; - } - - printk(KERN_INFO "Process %d suspended\n", pid); - -out: - put_pid(pid_struct); - if (ret && task) - put_task_struct(task); - return ret; -} - -// 恢复进程 -static int resume_process(pid_t pid) -{ - struct task_struct *task = NULL; - struct pid *pid_struct = NULL; - struct suspended_process *sp; - int ret = 0; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return -ESRCH; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return -ESRCH; - } - - // 查找暂停进程 - sp = find_suspended_process(pid); - if (!sp) { - printk(KERN_INFO "Process %d is not suspended\n", pid); - ret = -ENOENT; - goto out; - } - - // 发送SIGCONT信号恢复进程 - ret = send_sig(SIGCONT, task, 1); - if (ret == 0) { - // 从暂停列表中移除 - list_del(&sp->list); - kfree(sp); - put_task_struct(task); // 释放之前获取的引用 - printk(KERN_INFO "Process %d resumed\n", pid); - } - -out: - put_pid(pid_struct); - if (!sp && task) // 如果没有找到暂停项,释放task引用 - put_task_struct(task); - return ret; -} - -// 单步执行 -static int single_step_process(pid_t pid) -{ - struct suspended_process *sp; - - // 查找暂停进程 - sp = find_suspended_process(pid); - if (!sp) { - printk(KERN_INFO "Process %d is not suspended\n", pid); - return -ENOENT; - } - - // 设置单步执行标志 - sp->stepping = true; - - // 恢复进程执行一条指令 - // 注意:ARM64的单步执行通常通过设置调试寄存器实现 - // 这里简化为恢复进程,依靠断点再次捕获 - - return resume_process(pid); -} - -// IOCTL分发函数 -static int dispatch_open(struct inode *node, struct file *file) -{ - return 0; -} - -static int dispatch_close(struct inode *node, struct file *file) -{ - // 清理所有暂停进程 - struct suspended_process *sp, *tmp; - - list_for_each_entry_safe(sp, tmp, &suspended_list, list) { - // 恢复进程 - resume_process(sp->pid); - } - - return 0; -} - -static long dispatch_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - static char key[256] = {0}; - static bool is_verified = false; - long ret = 0; - - switch (cmd) { - case OP_INIT_KEY: - if (!is_verified) { - if (copy_from_user(key, (void __user *)arg, sizeof(key) - 1) == 0) { - key[sizeof(key) - 1] = '\0'; - is_verified = true; - printk(KERN_INFO "Key initialized successfully\n"); - } else { - return -EFAULT; - } - } - break; - - case OP_READ_MEM: { - COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) - return -EFAULT; - - if (!read_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) - return -EIO; - - break; - } - - case OP_WRITE_MEM: { - COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) - return -EFAULT; - - if (!write_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) - return -EIO; - - break; - } - - case OP_MODULE_BASE: { - MODULE_BASE mb; - char module_name[256]; - - if (copy_from_user(&mb, (void __user *)arg, sizeof(mb))) - return -EFAULT; - - if (!mb.name) - return -EFAULT; - - if (copy_from_user(module_name, mb.name, sizeof(module_name) - 1)) - return -EFAULT; - module_name[sizeof(module_name) - 1] = '\0'; - - mb.base = get_module_base(mb.pid, module_name); - - if (copy_to_user((void __user *)arg, &mb, sizeof(mb))) - return -EFAULT; - - break; - } - - case OP_SET_BREAKPOINT: { - BREAKPOINT_OPERATION bp_op; - - if (copy_from_user(&bp_op, (void __user *)arg, sizeof(bp_op))) - return -EFAULT; - - ret = set_hw_breakpoint(bp_op.pid, bp_op.addr, bp_op.type); - if (ret < 0) - return ret; - - break; - } - - case OP_CLEAR_BREAKPOINT: { - BREAKPOINT_OPERATION bp_op; - - if (copy_from_user(&bp_op, (void __user *)arg, sizeof(bp_op))) - return -EFAULT; - - ret = clear_hw_breakpoint(bp_op.pid, bp_op.addr); - if (ret < 0) - return ret; - - break; - } - - case OP_LIST_BREAKPOINTS: { - struct hw_breakpoint_entry *entry; - HW_BREAKPOINT_INFO info; - int idx = 0; - - mutex_lock(&bp_mutex); - - list_for_each_entry(entry, &bp_list, list) { - if (copy_to_user((void __user *)(arg + idx * sizeof(info)), - &entry->info, sizeof(info))) { - mutex_unlock(&bp_mutex); - return -EFAULT; - } - idx++; - } - - mutex_unlock(&bp_mutex); - break; - } - - case OP_CLEAR_ALL_BREAKPOINTS: - clear_all_breakpoints(); - break; - - case OP_GET_REGISTERS: { - REGISTER_OPERATION reg_op; - - if (copy_from_user(®_op, (void __user *)arg, sizeof(reg_op))) - return -EFAULT; - - if (!reg_op.regs) - return -EFAULT; - - ret = get_process_registers(reg_op.pid, reg_op.regs); - if (ret < 0) - return ret; - - break; - } - - case OP_SET_REGISTERS: { - REGISTER_OPERATION reg_op; - - if (copy_from_user(®_op, (void __user *)arg, sizeof(reg_op))) - return -EFAULT; - - if (!reg_op.regs) - return -EFAULT; - - ret = set_process_registers(reg_op.pid, reg_op.regs); - if (ret < 0) - return ret; - - break; - } - - case OP_SUSPEND_PROCESS: { - PROCESS_CONTROL pc; - - if (copy_from_user(&pc, (void __user *)arg, sizeof(pc))) - return -EFAULT; - - ret = suspend_process(pc.pid); - if (ret < 0) - return ret; - - break; - } - - case OP_RESUME_PROCESS: { - PROCESS_CONTROL pc; - - if (copy_from_user(&pc, (void __user *)arg, sizeof(pc))) - return -EFAULT; - - ret = resume_process(pc.pid); - if (ret < 0) - return ret; - - break; - } - - case OP_SINGLE_STEP: { - PROCESS_CONTROL pc; - - if (copy_from_user(&pc, (void __user *)arg, sizeof(pc))) - return -EFAULT; - - ret = single_step_process(pc.pid); - if (ret < 0) - return ret; - - break; - } - - default: - return -ENOTTY; - } - - return ret; -} - -// 文件操作结构 -static const struct file_operations dispatch_fops = { - .owner = THIS_MODULE, - .open = dispatch_open, - .release = dispatch_close, - .unlocked_ioctl = dispatch_ioctl, - .compat_ioctl = dispatch_ioctl, -}; - -// misc设备定义 -static struct miscdevice misc_dev = { - .minor = MISC_DYNAMIC_MINOR, - .name = DEVICE_NAME, - .fops = &dispatch_fops, - .mode = 0666, -}; - -// 模块初始化 -static int __init driver_entry(void) -{ - int ret; - int breakpoint_slots = 0; - - printk(KERN_INFO "ARM64 Hardware Breakpoint Module loading...\n"); - -#ifndef CONFIG_ARM64 - printk(KERN_ERR "This module is for ARM64 architecture only!\n"); - return -ENODEV; -#endif - - // 检查是否支持硬件断点 - // 注意:hw_breakpoint_slots函数可能没有导出,我们使用保守的默认值 -#ifdef CONFIG_HAVE_HW_BREAKPOINT - printk(KERN_INFO "Hardware breakpoint support detected\n"); - - // 尝试通过配置推断断点槽数量 - // ARM64通常支持4-16个硬件断点 -#if defined(CONFIG_ARM64_HW_BREAKPOINT) - // 如果定义了ARM64_HW_BREAKPOINT,通常支持更多断点 - breakpoint_slots = 16; -#else - // 保守估计 - breakpoint_slots = 4; -#endif - - printk(KERN_INFO "Estimated hardware breakpoint slots: %d\n", breakpoint_slots); -#else - printk(KERN_ERR "Hardware breakpoints not supported on this CPU\n"); - return -ENODEV; -#endif - - // 初始化暂停进程列表 - INIT_LIST_HEAD(&suspended_list); - - ret = misc_register(&misc_dev); - if (ret) { - printk(KERN_ERR "Failed to register misc device: %d\n", ret); - return ret; - } - - printk(KERN_INFO "ARM64 Hardware Breakpoint Module loaded. Device: /dev/%s\n", DEVICE_NAME); - printk(KERN_INFO "Maximum hardware breakpoints: %d\n", MAX_BREAKPOINTS); - - return 0; -} - -// 模块卸载 -static void __exit driver_unload(void) -{ - struct suspended_process *sp, *tmp; - - printk(KERN_INFO "ARM64 Hardware Breakpoint Module unloading...\n"); - - // 恢复所有暂停进程 - list_for_each_entry_safe(sp, tmp, &suspended_list, list) { - resume_process(sp->pid); - } - - // 清除所有断点 - clear_all_breakpoints(); - - // 注销设备 - misc_deregister(&misc_dev); - - printk(KERN_INFO "ARM64 Hardware Breakpoint Module unloaded\n"); -} - -module_init(driver_entry); -module_exit(driver_unload); - -MODULE_DESCRIPTION("ARM64 Hardware Breakpoint Kernel Module with Process Control"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("陈依涵"); -MODULE_VERSION("1.0"); \ No newline at end of file From 08b4fb1deb778f2156aadff919e5dfbab762028c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:06:33 +0800 Subject: [PATCH 20/35] Delete code/arm64_hw_bp.h --- code/arm64_hw_bp.h | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) delete mode 100644 code/arm64_hw_bp.h diff --git a/code/arm64_hw_bp.h b/code/arm64_hw_bp.h deleted file mode 100644 index 2f6d4b75..00000000 --- a/code/arm64_hw_bp.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _ARM64_HW_BP_H -#define _ARM64_HW_BP_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) -#include -#include -#endif - -// 设备名称 -#define DEVICE_NAME "YihanChan" - -// 断点类型定义 -enum BP_TYPES { - BP_TYPE_INST = 0, // 指令执行断点 - BP_TYPE_READ = 1, // 数据读断点 - BP_TYPE_WRITE = 2, // 数据写断点 - BP_TYPE_RW = 3 // 数据读写断点 -}; - -#endif /* _ARM64_HW_BP_H */ \ No newline at end of file From ac9deb093a75f1df0e3543e29a75af2028cf01dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:10:10 +0800 Subject: [PATCH 21/35] Add files via upload --- code/Makefile | 30 +- code/ext_hw_breakpoint.h | 190 +++++++ code/hw_breakpoint.c | 1034 +++++++++++++++++++++++++++++++++++ code/hw_breakpoint_manage.c | 619 +++++++++++++++++++++ code/hw_breakpoint_proc.c | 372 +++++++++++++ code/hw_breakpoint_smp.c | 193 +++++++ code/hw_breakpoint_until.c | 139 +++++ code/hw_breakpoint_until.h | 17 + 8 files changed, 2593 insertions(+), 1 deletion(-) create mode 100644 code/ext_hw_breakpoint.h create mode 100644 code/hw_breakpoint.c create mode 100644 code/hw_breakpoint_manage.c create mode 100644 code/hw_breakpoint_proc.c create mode 100644 code/hw_breakpoint_smp.c create mode 100644 code/hw_breakpoint_until.c create mode 100644 code/hw_breakpoint_until.h diff --git a/code/Makefile b/code/Makefile index 213da72a..558a73ef 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1 +1,29 @@ -obj-m += arm64_hw_bp.o +CROSS?= aarch64-none-linux-gnu- +KERNEL_DIR?= your kernel dir +CURRENT_PATH:= $(shell pwd) +MODULE_NAME= hw_break + +src_dir?= $(shell pwd) +export src_dir + + +includedir:= -I$(src_dir)/include +EXTRA_CFLAGS+= $(includedir) -g + + +obj-m:= $(MODULE_NAME).o +$(MODULE_NAME)-objs+= hw_breakpoint.o \ + hw_breakpoint_manage.o \ + hw_breakpoint_proc.o \ + hw_breakpoint_smp.o \ + hw_breakpoint_until.o \ + + +all: ko +# 编译驱动 +ko: + make -C $(KERNEL_DIR) M=$(CURRENT_PATH) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" CROSS_COMPILE=${CROSS} ARCH=arm64 modules + + +clean: + make -C $(KERNEL_DIR) M=$(CURRENT_PATH) clean \ No newline at end of file diff --git a/code/ext_hw_breakpoint.h b/code/ext_hw_breakpoint.h new file mode 100644 index 00000000..71c4519e --- /dev/null +++ b/code/ext_hw_breakpoint.h @@ -0,0 +1,190 @@ +#ifndef __EXT_HW_BREAKPOINT_H +#define __EXT_HW_BREAKPOINT_H + +#include +#include +#include + +#define HW_SYMS_FUNC(x) g_kernel_api.fun.x +#define HW_SYMS_VAL(x) g_kernel_api.val.x + +typedef struct hw_trigger_times { + u64 read; + u64 write; + u64 exec; +} hw_trigger_times; + +typedef struct hw_bp_callback_data { + u32 type; + u64 addr; + hw_trigger_times times; +} hw_bp_callback_data; + +typedef void (*hw_bp_callback)(const hw_bp_callback_data *attr, + const struct pt_regs *regs); + +typedef struct hw_bp_attr { + u32 type; /*bp type*/ + u64 addr; /*The addr of the bp expected to be monitored*/ + u64 start_addr; /*The starting address of the actual monitoring*/ + u64 end_addr; /*The end address of the actual monitoring*/ + u64 len; /*The length of the bp expected to be monitored*/ + u64 real_len; /*LBN len*/ + u32 mask; /*addr mask*/ + hw_trigger_times times; /*trigger times*/ + hw_bp_callback handler; /*user handler*/ + u64 disabled : 1, //63bit + reserved : 63; //0~62bit +} hw_bp_attr; + +/*struct of get info*/ +typedef struct hw_bp_report { + u32 type; /*bp type*/ + u64 addr; /*The addr of the bp expected to be monitored*/ + u64 len; /*The length of the bp expected to be monitored*/ + u32 mask; + hw_trigger_times times; /*trigger times*/ +} hw_bp_report; +typedef struct hw_bp_info_list { + struct list_head list; /*list*/ + hw_bp_report *attr; /*bp attr. attr[cpu_id]*/ + int cpu_mask; /*success install of cpu*/ + int cpu_num; /*total cpu num*/ +} hw_bp_info_list; + +typedef struct hw_bp_ctrl_reg { + u32 reserved2 : 3, //29~31bit, + mask : 5, //24~28bit, addr mask,mask=0b11111: (mask2^0b11111 the low bit addr), support 8~2G range + reserved1 : 3, //21~23bit, + wt : 1, //20bit, watchpoint type, Unlinked(0)/linked(1) data address match. + lbn : 4, //16~19bit, WT is only required to be set when setting, which is related to link breakpoints + ssc : 2, //14,15bit, Security state control, which controls what state will listen for breakpoint events + hmc : 1, //13bit, Use in conjunction with the above fields + len : 8, //5~12bit, LBN of len, Each bit represents 1 byte and a maximum of 8 bytes + type : 2, //3~4bit, bp type wp/bp + privilege : 2, //1~2bit, The EL level at the time of the last breakpoint setting is used with SSC and HMC + enabled : 1; //0bit, bp enable +} hw_bp_ctrl_reg; + +typedef struct hw_bp_vc { + u64 address; + hw_bp_ctrl_reg ctrl; + u64 trigger; + u8 access_type; +} hw_bp_vc; + +struct hw_bp_info { + int cpu; + hw_bp_attr attr; + hw_bp_vc info; +}; + +struct fault_info { + int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); + int sig; + int code; + const char *name; +}; +typedef struct hw_kernel_api { + struct { + unsigned long (*kallsyms_lookup_name)( + const char *name); /*search symbols func*/ + void (*register_step_hook)(struct step_hook *hook); + void (*unregister_step_hook)(struct step_hook *hook); + void (*enable_debug_monitors)(enum dbg_active_el el); + void (*disable_debug_monitors)(enum dbg_active_el el); + int (*kernel_active_single_step)(void); + void (*kernel_enable_single_step)(struct pt_regs *regs); + void (*kernel_disable_single_step)(void); + u64 (*read_sanitised_ftr_reg)(u32 id); + void (*show_regs)(struct pt_regs *); + void (*dump_backtrace)(struct pt_regs *regs, + struct task_struct *tsk); + void (*do_bad)(unsigned long addr, unsigned int esr, + struct pt_regs *regs); + } __aligned(128) fun; + struct { +#ifdef CONFIG_CPU_PM + u64 *hw_breakpoint_restore; + u64 default_hw_breakpoint_restore; +#endif + struct fault_info *debug_fault_info; + struct fault_info default_fault_info[2]; + spinlock_t *vmap_area_lock; /*kernel vm spinlock*/ + struct list_head *vmap_area_list; /*kernel vm list*/ + } __aligned(128) val; + +} hw_kernel_api; + +extern hw_kernel_api g_kernel_api; + +/*encode reg*/ +static inline u32 hw_encode_ctrl_reg(hw_bp_ctrl_reg ctrl) +{ + u32 val = (ctrl.mask << 24) | (ctrl.len << 5) | (ctrl.type << 3) | + (ctrl.privilege << 1) | ctrl.enabled; + + if (is_kernel_in_hyp_mode() && ctrl.privilege == AARCH64_BREAKPOINT_EL1) + val |= DBG_HMC_HYP; + + return val; +} + +/*decode reg*/ +static inline void hw_decode_ctrl_reg(u32 reg, hw_bp_ctrl_reg *ctrl) +{ + ctrl->enabled = reg & 0x1; + reg >>= 1; + ctrl->privilege = reg & 0x3; + reg >>= 2; + ctrl->type = reg & 0x3; + reg >>= 2; + ctrl->len = reg & 0xff; + reg >>= 19; + ctrl->mask = reg & 0x1f; +} + +static inline hw_bp_vc *hw_get_vc(struct hw_bp_info *bp) +{ + return &bp->info; +} + +/* Determine number of BRP registers available. */ +static inline int hw_get_num_brps(void) +{ + u64 dfr0 = HW_SYMS_FUNC(read_sanitised_ftr_reg)(SYS_ID_AA64DFR0_EL1); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_BRPs_SHIFT); +#else + return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_BRPS_SHIFT); +#endif +} + +/* Determine number of WRP registers available. */ +static inline int hw_get_num_wrps(void) +{ + u64 dfr0 = HW_SYMS_FUNC(read_sanitised_ftr_reg)(SYS_ID_AA64DFR0_EL1); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_WRPs_SHIFT); +#else + return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_WRPS_SHIFT); +#endif +} + +int hw_get_bp_num(int type); +void hw_proc_exit(void); +void hw_bp_manage_deinit(void); + +/*user handler*/ +/*install/uninstall*/ +int hw_bp_install_from_addr(u64 addr, int len, int type, + hw_bp_callback handler); +void hw_bp_uninstall_from_addr(u64 addr); +int hw_bp_install_from_symbol(char *name, int len, int type, + hw_bp_callback handler); +void hw_bp_uninstall_from_symbol(char *name); +/*get install bp info*/ +hw_bp_info_list *hw_get_bp_infos(void); +void hw_free_bp_infos(hw_bp_info_list *info); + +#endif \ No newline at end of file diff --git a/code/hw_breakpoint.c b/code/hw_breakpoint.c new file mode 100644 index 00000000..0c9beac4 --- /dev/null +++ b/code/hw_breakpoint.c @@ -0,0 +1,1034 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "ext_hw_breakpoint.h" + +/*func extern*/ +extern int hw_bp_manage_init(void); +extern int hw_proc_init(void); + +enum hw_breakpoint_ops { + HW_BREAKPOINT_INSTALL, + HW_BREAKPOINT_UNINSTALL, + HW_BREAKPOINT_RESTORE +}; + +/* Breakpoint currently in use for each BRP. */ +static DEFINE_PER_CPU(struct hw_bp_info *, bp_on_reg[ARM_MAX_BRP]); + +/* Watchpoint currently in use for each WRP. */ +static DEFINE_PER_CPU(struct hw_bp_info *, wp_on_reg[ARM_MAX_WRP]); + +/* Currently stepping a per-CPU kernel breakpoint. */ +static DEFINE_PER_CPU(int, stepping_kernel_bp); + +/* Number of BRP/WRP registers on this CPU. */ +static int core_num_brps; +static int core_num_wrps; + +/*kernel vars*/ +hw_kernel_api g_kernel_api; + +/*get bp num*/ +int hw_get_bp_num(int type) +{ + switch (type) { + case TYPE_INST: + return hw_get_num_brps(); + case TYPE_DATA: + return hw_get_num_wrps(); + default: + pr_info("unknown slot type: %d\n", type); + return 0; + } +} + +#define READ_WB_REG_CASE(OFF, N, REG, VAL) \ + case ((OFF) + (N)): \ + AARCH64_DBG_READ(N, REG, VAL); \ + break + +#define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ + case ((OFF) + (N)): \ + AARCH64_DBG_WRITE(N, REG, VAL); \ + break + +#define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \ + READ_WB_REG_CASE(OFF, 0, REG, VAL); \ + READ_WB_REG_CASE(OFF, 1, REG, VAL); \ + READ_WB_REG_CASE(OFF, 2, REG, VAL); \ + READ_WB_REG_CASE(OFF, 3, REG, VAL); \ + READ_WB_REG_CASE(OFF, 4, REG, VAL); \ + READ_WB_REG_CASE(OFF, 5, REG, VAL); \ + READ_WB_REG_CASE(OFF, 6, REG, VAL); \ + READ_WB_REG_CASE(OFF, 7, REG, VAL); \ + READ_WB_REG_CASE(OFF, 8, REG, VAL); \ + READ_WB_REG_CASE(OFF, 9, REG, VAL); \ + READ_WB_REG_CASE(OFF, 10, REG, VAL); \ + READ_WB_REG_CASE(OFF, 11, REG, VAL); \ + READ_WB_REG_CASE(OFF, 12, REG, VAL); \ + READ_WB_REG_CASE(OFF, 13, REG, VAL); \ + READ_WB_REG_CASE(OFF, 14, REG, VAL); \ + READ_WB_REG_CASE(OFF, 15, REG, VAL) + +#define GEN_WRITE_WB_REG_CASES(OFF, REG, VAL) \ + WRITE_WB_REG_CASE(OFF, 0, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 15, REG, VAL) + +/*read bp reg*/ +static u64 hw_read_bp_reg(int reg, int n) +{ + u64 val = 0; + + switch (reg + n) { + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, + AARCH64_DBG_REG_NAME_BVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, + AARCH64_DBG_REG_NAME_BCR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, + AARCH64_DBG_REG_NAME_WVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, + AARCH64_DBG_REG_NAME_WCR, val); + default: + pr_info("attempt to read from unknown breakpoint register %d\n", + n); + } + + return val; +} +NOKPROBE_SYMBOL(hw_read_bp_reg); + +/*write bp reg*/ +static void hw_write_bp_reg(int reg, int n, u64 val) +{ + switch (reg + n) { + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, + AARCH64_DBG_REG_NAME_BVR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, + AARCH64_DBG_REG_NAME_BCR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WVR, + AARCH64_DBG_REG_NAME_WVR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WCR, + AARCH64_DBG_REG_NAME_WCR, val); + default: + pr_info("attempt to write to unknown breakpoint register %d\n", + n); + } + /*Clear the pipeline to ensure that all previous instructions have been completed before the new instructions are executed*/ + isb(); +} +NOKPROBE_SYMBOL(hw_write_bp_reg); + +/*get elx level*/ +static enum dbg_active_el hw_get_debug_exception_level(int privilege) +{ + switch (privilege) { + case AARCH64_BREAKPOINT_EL0: + return DBG_ACTIVE_EL0; + case AARCH64_BREAKPOINT_EL1: + return DBG_ACTIVE_EL1; + default: + pr_info("invalid breakpoint privilege level %d\n", privilege); + return -EINVAL; + } +} +NOKPROBE_SYMBOL(hw_get_debug_exception_level); + +/** + * hw_bp_slot_setup - Insert/remove bp in global variables + * + * @slots: pointer to the global variables + * @max_slots: max bp num + * @bp: bp info + * @ops: type of bp + * + * Return: + * success: return the number of bp + * -ENOSPC no space + * -EINVAL cmd ops + */ +static int hw_bp_slot_setup(struct hw_bp_info **slots, int max_slots, + struct hw_bp_info *bp, enum hw_breakpoint_ops ops) +{ + int i; + struct hw_bp_info **slot; + + for (i = 0; i < max_slots; ++i) { + slot = &slots[i]; + switch (ops) { + case HW_BREAKPOINT_INSTALL: + if (!*slot) { + *slot = bp; + return i; + } + break; + case HW_BREAKPOINT_UNINSTALL: + if (*slot == bp) { + *slot = NULL; + return i; + } + break; + case HW_BREAKPOINT_RESTORE: + if (*slot == bp) + return i; + break; + default: + pr_info("Unhandled hw breakpoint ops %d\n", ops); + return -EINVAL; + } + } + return -ENOSPC; +} + +/*bp control install/uninstall*/ +static int hw_bp_control(struct hw_bp_info *bp, enum hw_breakpoint_ops ops) +{ + hw_bp_vc *info = hw_get_vc(bp); + struct hw_bp_info **slots; + int i, max_slots, ctrl_reg, val_reg; + enum dbg_active_el dbg_el = + hw_get_debug_exception_level(info->ctrl.privilege); + u32 ctrl; + + // pr_info("the real CPU = %d\n", smp_processor_id()); + + if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { + /* Breakpoint */ + ctrl_reg = AARCH64_DBG_REG_BCR; + val_reg = AARCH64_DBG_REG_BVR; + slots = this_cpu_ptr(bp_on_reg); + max_slots = core_num_brps; + } else { + /* Watchpoint */ + ctrl_reg = AARCH64_DBG_REG_WCR; + val_reg = AARCH64_DBG_REG_WVR; + slots = this_cpu_ptr(wp_on_reg); + max_slots = core_num_wrps; + } + + i = hw_bp_slot_setup(slots, max_slots, bp, ops); + + if (WARN_ONCE(i < 0, "Can't find any breakpoint slot")) + return i; + + switch (ops) { + case HW_BREAKPOINT_INSTALL: + /*Ensure debug monitors are enabled at the correct exception level.*/ + HW_SYMS_FUNC(enable_debug_monitors)(dbg_el); + fallthrough; + /* Fall through */ + case HW_BREAKPOINT_RESTORE: + /* Setup the address register. */ + hw_write_bp_reg(val_reg, i, info->address); + + /* Setup the control register. */ + ctrl = hw_encode_ctrl_reg(info->ctrl); + // pr_info("CTRL REG = %x\n", ctrl); + hw_write_bp_reg(ctrl_reg, i, ctrl); + break; + case HW_BREAKPOINT_UNINSTALL: + /* Reset the control register. */ + hw_write_bp_reg(ctrl_reg, i, 0); + + /*Release the debug monitors for the correct exception level.*/ + HW_SYMS_FUNC(disable_debug_monitors)(dbg_el); + break; + } + + return 0; +} + +/* + * Install a breakpoint. + */ +int hw_bp_install(struct hw_bp_info *bp) +{ + return hw_bp_control(bp, HW_BREAKPOINT_INSTALL); +} + +int hw_bp_uninstall(struct hw_bp_info *bp) +{ + return hw_bp_control(bp, HW_BREAKPOINT_UNINSTALL); +} + +/*get len from LBN bit*/ +static int hw_get_hbp_Len(u8 hbp_len) +{ + int len_in_bytes = 0; + + switch (hbp_len) { + case ARM_BREAKPOINT_LEN_1: + len_in_bytes = 1; + break; + case ARM_BREAKPOINT_LEN_2: + len_in_bytes = 2; + break; + case ARM_BREAKPOINT_LEN_3: + len_in_bytes = 3; + break; + case ARM_BREAKPOINT_LEN_4: + len_in_bytes = 4; + break; + case ARM_BREAKPOINT_LEN_5: + len_in_bytes = 5; + break; + case ARM_BREAKPOINT_LEN_6: + len_in_bytes = 6; + break; + case ARM_BREAKPOINT_LEN_7: + len_in_bytes = 7; + break; + case ARM_BREAKPOINT_LEN_8: + default: + len_in_bytes = 8; + break; + } + + return len_in_bytes; +} + +/* + * Check whether bp virtual address is in kernel space. + */ +int hw_arch_check_bp_in_kspace(hw_bp_vc *hw) +{ + unsigned int len; + unsigned long va; + + va = hw->address; + len = hw_get_hbp_Len(hw->ctrl.len); + + /*get addr & len from mask*/ + if (hw->ctrl.mask) { + len = 1 << hw->ctrl.mask; + } + + return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); +} + +/* + * bp info to ctrl reg + */ +static int hw_arch_build_bp_info(struct hw_bp_info *bp, const hw_bp_attr *attr, + hw_bp_vc *hw) +{ + /* Type */ + switch (attr->type) { + case HW_BREAKPOINT_X: + hw->ctrl.type = ARM_BREAKPOINT_EXECUTE; + break; + case HW_BREAKPOINT_R: + hw->ctrl.type = ARM_BREAKPOINT_LOAD; + break; + case HW_BREAKPOINT_W: + hw->ctrl.type = ARM_BREAKPOINT_STORE; + break; + case HW_BREAKPOINT_RW: + hw->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; + break; + default: + return -EINVAL; + } + + /* Len */ + switch (attr->real_len) { + case HW_BREAKPOINT_LEN_1: + hw->ctrl.len = ARM_BREAKPOINT_LEN_1; + break; + case HW_BREAKPOINT_LEN_2: + hw->ctrl.len = ARM_BREAKPOINT_LEN_2; + break; + case HW_BREAKPOINT_LEN_3: + hw->ctrl.len = ARM_BREAKPOINT_LEN_3; + break; + case HW_BREAKPOINT_LEN_4: + hw->ctrl.len = ARM_BREAKPOINT_LEN_4; + break; + case HW_BREAKPOINT_LEN_5: + hw->ctrl.len = ARM_BREAKPOINT_LEN_5; + break; + case HW_BREAKPOINT_LEN_6: + hw->ctrl.len = ARM_BREAKPOINT_LEN_6; + break; + case HW_BREAKPOINT_LEN_7: + hw->ctrl.len = ARM_BREAKPOINT_LEN_7; + break; + case HW_BREAKPOINT_LEN_8: + hw->ctrl.len = ARM_BREAKPOINT_LEN_8; + break; + default: + return -EINVAL; + } + + /* only permit breakpoints of length 4 */ + if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE) { + hw->ctrl.len = ARM_BREAKPOINT_LEN_4; + } + + /* wp addr mask */ + hw->ctrl.mask = attr->mask; + /* Address */ + hw->address = attr->start_addr; + + /* + * Privilege + * Note that we disallow combined EL0/EL1 breakpoints because + * that would complicate the stepping code. + */ + if (hw_arch_check_bp_in_kspace(hw)) + hw->ctrl.privilege = AARCH64_BREAKPOINT_EL1; + else + hw->ctrl.privilege = AARCH64_BREAKPOINT_EL0; + + /* Enabled */ + hw->ctrl.enabled = !attr->disabled; + + return 0; +} + +/* parse bp info */ +int hw_bp_arch_parse(struct hw_bp_info *bp, const hw_bp_attr *attr, + hw_bp_vc *hw) +{ + int ret; + + /* Build the arch_hw_breakpoint. */ + ret = hw_arch_build_bp_info(bp, attr, hw); + if (ret) + return ret; + + pr_info("ctrl.len=%x,mask=%d,enabled=%d,address=%llx\n", hw->ctrl.len, + hw->ctrl.mask, hw->ctrl.enabled, hw->address); + + return 0; +} + +/* enable/disable a bp */ +static void hw_toggle_bp_registers(int reg, enum dbg_active_el el, int enable) +{ + int i, max_slots, privilege; + u32 ctrl; + struct hw_bp_info **slots; + + switch (reg) { + case AARCH64_DBG_REG_BCR: + slots = this_cpu_ptr(bp_on_reg); + max_slots = core_num_brps; + break; + case AARCH64_DBG_REG_WCR: + slots = this_cpu_ptr(wp_on_reg); + max_slots = core_num_wrps; + break; + default: + return; + } + + for (i = 0; i < max_slots; ++i) { + if (!slots[i]) + continue; + + privilege = hw_get_vc(slots[i])->ctrl.privilege; + if (hw_get_debug_exception_level(privilege) != el) + continue; + + ctrl = hw_read_bp_reg(reg, i); + if (enable) + ctrl |= 0x1; + else + ctrl &= ~0x1; + hw_write_bp_reg(reg, i, ctrl); + } +} +NOKPROBE_SYMBOL(hw_toggle_bp_registers); + +/*bp events exception handler*/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) +static int hw_bp_handler(unsigned long unused, unsigned long esr, + struct pt_regs *regs) +#else +static int hw_bp_handler(unsigned long unused, unsigned int esr, + struct pt_regs *regs) +#endif +{ + int i, *kernel_step; + u32 ctrl_reg; + u64 addr, val; + struct hw_bp_info *bp, **slots; + hw_bp_ctrl_reg ctrl; + + slots = this_cpu_ptr(bp_on_reg); + addr = instruction_pointer(regs); + + for (i = 0; i < core_num_brps; ++i) { + rcu_read_lock(); + + bp = slots[i]; + + if (bp == NULL) + goto unlock; + + /* Check if the breakpoint value matches. */ + val = hw_read_bp_reg(AARCH64_DBG_REG_BVR, i); + if (val != (addr & ~0x3)) + goto unlock; + + /* Possible match, check the byte address select to confirm. */ + ctrl_reg = hw_read_bp_reg(AARCH64_DBG_REG_BCR, i); + hw_decode_ctrl_reg(ctrl_reg, &ctrl); + if (!((1 << (addr & 0x3)) & ctrl.len)) + goto unlock; + + hw_get_vc(bp)->trigger = addr; + + unlock: + rcu_read_unlock(); + } + + hw_toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 0); + kernel_step = this_cpu_ptr(&stepping_kernel_bp); + + if (*kernel_step != ARM_KERNEL_STEP_NONE) + return 0; + + if (HW_SYMS_FUNC(kernel_active_single_step)()) { + *kernel_step = ARM_KERNEL_STEP_SUSPEND; + } else { + *kernel_step = ARM_KERNEL_STEP_ACTIVE; + HW_SYMS_FUNC(kernel_enable_single_step)(regs); + } + + return 0; +} +NOKPROBE_SYMBOL(hw_bp_handler); + +/*get dist from trigger to wp addr*/ +static u64 hw_get_distance_from_wp(unsigned long addr, u64 val, + hw_bp_ctrl_reg *ctrl) +{ + addr = untagged_addr(addr); + val = untagged_addr(val); + return addr - val; +} + +/*wp events exception handler*/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) +static int hw_wp_handler(unsigned long addr, unsigned long esr, + struct pt_regs *regs) +#else +static int hw_wp_handler(unsigned long addr, unsigned int esr, + struct pt_regs *regs) +#endif +{ + int i, *kernel_step, access, closest_match = -1; + u64 min_dist = -1, dist; + u32 ctrl_reg; + u64 val; + struct hw_bp_info *wp, **slots; + hw_bp_vc *info = NULL; + hw_bp_ctrl_reg ctrl; + + slots = this_cpu_ptr(wp_on_reg); + + /*find the nearest trigger address*/ + rcu_read_lock(); + for (i = 0; i < core_num_wrps; ++i) { + wp = slots[i]; + if (wp == NULL) + continue; + + /*check type of wp*/ + access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W : + HW_BREAKPOINT_R; + if (!(access & wp->attr.type)) + continue; + + /* Check if the watchpoint value and byte select match. */ + val = hw_read_bp_reg(AARCH64_DBG_REG_WVR, i); + ctrl_reg = hw_read_bp_reg(AARCH64_DBG_REG_WCR, i); + hw_decode_ctrl_reg(ctrl_reg, &ctrl); + dist = hw_get_distance_from_wp(addr, wp->attr.addr, &ctrl); + if (dist < min_dist) { + min_dist = dist; + closest_match = i; + } + /* Is this an exact match? */ + if (dist != 0) + continue; + info = hw_get_vc(wp); + info->trigger = addr; + info->access_type = access; + closest_match = i; + } + if (min_dist > 0 && min_dist != -1) { + /* No exact match found. */ + wp = slots[closest_match]; + info = hw_get_vc(wp); + info->trigger = addr; + info->access_type = access; + } + rcu_read_unlock(); + + /*disable all of wps*/ + hw_toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 0); + kernel_step = this_cpu_ptr(&stepping_kernel_bp); + + if (*kernel_step != ARM_KERNEL_STEP_NONE) + return 0; + + if (HW_SYMS_FUNC(kernel_active_single_step)()) { + *kernel_step = ARM_KERNEL_STEP_SUSPEND; + } else { + *kernel_step = ARM_KERNEL_STEP_ACTIVE; + /*enable ss exception in cur regs*/ + HW_SYMS_FUNC(kernel_enable_single_step)(regs); + } + + return 0; +} +NOKPROBE_SYMBOL(hw_wp_handler); + +/*resume bp states*/ +static int hw_bp_reinstall(struct pt_regs *regs) +{ + // struct debug_info *debug_info = ¤t->thread.debug; + int handled_exception = 0, *kernel_step; + + /*get step states*/ + kernel_step = this_cpu_ptr(&stepping_kernel_bp); + + if (*kernel_step != ARM_KERNEL_STEP_NONE) { + hw_toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 1); + hw_toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 1); + + if (*kernel_step != ARM_KERNEL_STEP_SUSPEND) { + HW_SYMS_FUNC(kernel_disable_single_step()); + handled_exception = 1; + } else { + handled_exception = 0; + } + + *kernel_step = ARM_KERNEL_STEP_NONE; + } + + return !handled_exception; +} +NOKPROBE_SYMBOL(hw_bp_reinstall); + +/*bp reset when cold boot*/ +static int hw_bp_reset(unsigned int cpu) +{ + int i; + struct hw_bp_info **slots; + /* + * When a CPU goes through cold-boot, it does not have any installed + * slot, so it is safe to share the same function for restoring and + * resetting breakpoints; when a CPU is hotplugged in, it goes + * through the slots, which are all empty, hence it just resets control + * and value for debug registers. + * When this function is triggered on warm-boot through a CPU PM + * notifier some slots might be initialized; if so they are + * reprogrammed according to the debug slots content. + */ + for (slots = this_cpu_ptr(bp_on_reg), i = 0; i < core_num_brps; ++i) { + if (slots[i]) { + hw_bp_control(slots[i], HW_BREAKPOINT_RESTORE); + } else { + hw_write_bp_reg(AARCH64_DBG_REG_BCR, i, 0UL); + hw_write_bp_reg(AARCH64_DBG_REG_BVR, i, 0UL); + } + } + + for (slots = this_cpu_ptr(wp_on_reg), i = 0; i < core_num_wrps; ++i) { + if (slots[i]) { + hw_bp_control(slots[i], HW_BREAKPOINT_RESTORE); + } else { + hw_write_bp_reg(AARCH64_DBG_REG_WCR, i, 0UL); + hw_write_bp_reg(AARCH64_DBG_REG_WVR, i, 0UL); + } + } + + return 0; +} + +static void hw_trigger_handler(struct pt_regs *regs) +{ + int i = 0; + struct hw_bp_info *wp, **slots; + hw_bp_callback_data report; + + rcu_read_lock(); + slots = this_cpu_ptr(bp_on_reg); + for (i = 0; i < core_num_brps; ++i) { + wp = slots[i]; + if (wp == NULL) + continue; + if (wp->info.trigger) { + wp->attr.times.exec++; + report.type = HW_BREAKPOINT_X; + report.addr = wp->info.trigger; + report.times = wp->attr.times; + report.type = wp->attr.type; + /*user handler*/ + wp->attr.handler(&report, regs); + + wp->info.trigger = 0; + } + } + slots = this_cpu_ptr(wp_on_reg); + for (i = 0; i < core_num_wrps; ++i) { + wp = slots[i]; + if (wp == NULL) + continue; + if (!wp->info.trigger) { + continue; + } + if (wp->info.trigger >= wp->attr.addr && + wp->info.trigger < wp->attr.addr + wp->attr.len) { + /*The user handler only within the range of addresses that are expected to be detected*/ + if (wp->info.access_type & HW_BREAKPOINT_R) { + wp->attr.times.read++; + } else if (wp->info.access_type & HW_BREAKPOINT_W) { + wp->attr.times.write++; + } + /*user handler*/ + report.type = wp->info.access_type; + report.addr = wp->info.trigger; + report.times = wp->attr.times; + wp->attr.handler(&report, regs); + } + wp->info.trigger = 0; + } + rcu_read_unlock(); +} + +/*ss exception handler, will run user handler*/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) +static int hw_step_brk_fn(struct pt_regs *regs, unsigned long esr) +#else +static int hw_step_brk_fn(struct pt_regs *regs, unsigned int esr) +#endif +{ + int *kernel_step; + + /*step states*/ + kernel_step = this_cpu_ptr(&stepping_kernel_bp); + + if (user_mode(regs) || !(*kernel_step)) + return DBG_HOOK_ERROR; + + hw_trigger_handler(regs); + + if (hw_bp_reinstall(regs)) { + return DBG_HOOK_ERROR; + } +#ifdef CONFIG_KGDB + kgdb_handle_exception(0, SIGTRAP, 0, regs); +#endif + + return DBG_HOOK_HANDLED; +} +NOKPROBE_SYMBOL(hw_step_brk_fn); + +#ifdef CONFIG_CPU_PM +extern void cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)); +#else +static inline void +cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)) +{ +} +#endif + +static struct step_hook ghw_step_hook = { .fn = hw_step_brk_fn }; + +/*search symbol addr*/ +unsigned long kaddr_lookup_name(const char *fname_raw) +{ + int i; + unsigned long kaddr; + char *fname_lookup, *fname; + + fname_lookup = kzalloc(NAME_MAX, GFP_KERNEL); + if (!fname_lookup) + return 0; + + fname = kzalloc(strlen(fname_raw) + 4, GFP_KERNEL); + if (!fname) + return 0; + + /* + * We have to add "+0x0" to the end of our function name + * because that's the format that sprint_symbol() returns + * to us. If we don't do this, then our search can stop + * prematurely and give us the wrong function address! + */ + strcpy(fname, fname_raw); + strcat(fname, "+0x0"); + + /*获取内核代码段基地址*/ + kaddr = (unsigned long)&sprint_symbol; + kaddr &= 0xffffffffff000000; + + /*内核符号不会超过0x100000*16的大小,所以按4字节偏移,挨个找*/ + for (i = 0x0; i < 0x400000; i++) { + /*寻找地址对应的符号名称*/ + sprint_symbol(fname_lookup, kaddr); + /*对比寻找的符号名字*/ + if (strncmp(fname_lookup, fname, strlen(fname)) == 0) { + /*找到了就返回地址*/ + kfree(fname_lookup); + kfree(fname); + return kaddr; + } + /*偏移4字节*/ + kaddr += 0x04; + } + /*没找到地址就返回0*/ + kfree(fname_lookup); + kfree(fname); + return 0; +} + +/*get kallsyms_lookup_name*/ +static int hw_get_kallsyms_lookup_name(void) +{ + HW_SYMS_FUNC(kallsyms_lookup_name) = + (void *)kaddr_lookup_name("kallsyms_lookup_name"); + if (!HW_SYMS_FUNC(kallsyms_lookup_name)) { + printk("get kallsyms_lookup_name fail \n"); + return -1; + } + return 0; +} + +/*get vars from kernel*/ +static int hw_get_kernel_api(void) +{ + memset(&g_kernel_api, 0, sizeof(g_kernel_api)); + if (hw_get_kallsyms_lookup_name()) { + return -1; + } + HW_SYMS_VAL(debug_fault_info) = + (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("debug_fault_info"); + if (!HW_SYMS_VAL(debug_fault_info)) { + pr_warn("get debug_fault_info fail\n"); + return -1; + } + // pr_warn("debug_fault_info = %llx,name = %s\n", &HW_SYMS_VAL(debug_fault_info)[0], + // HW_SYMS_VAL(debug_fault_info)[0].name); + // pr_warn("debug_fault_info = %llx,name = %s\n", &HW_SYMS_VAL(debug_fault_info)[2], + // HW_SYMS_VAL(debug_fault_info)[2].name); +#ifdef CONFIG_CPU_PM + HW_SYMS_VAL(hw_breakpoint_restore) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("hw_breakpoint_restore"); + if (!HW_SYMS_VAL(hw_breakpoint_restore)) { + pr_warn("get hw_breakpoint_restore fail\n"); + return -1; + } + // pr_warn("hw_breakpoint_restore = %llx,%llx\n", HW_SYMS_VAL(hw_breakpoint_restore), + // *HW_SYMS_VAL(hw_breakpoint_restore)); +#endif + HW_SYMS_FUNC(kernel_active_single_step) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("kernel_active_single_step"); + if (!HW_SYMS_FUNC(kernel_active_single_step)) { + pr_warn("get kernel_active_single_step fail\n"); + return -1; + } + HW_SYMS_FUNC(kernel_disable_single_step) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("kernel_disable_single_step"); + if (!HW_SYMS_FUNC(kernel_disable_single_step)) { + pr_warn("get kernel_disable_single_step fail\n"); + return -1; + } + HW_SYMS_FUNC(kernel_enable_single_step) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("kernel_enable_single_step"); + if (!HW_SYMS_FUNC(kernel_enable_single_step)) { + pr_warn("get kernel_enable_single_step fail\n"); + return -1; + } + HW_SYMS_FUNC(disable_debug_monitors) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("disable_debug_monitors"); + if (!HW_SYMS_FUNC(disable_debug_monitors)) { + pr_warn("get disable_debug_monitors fail\n"); + return -1; + } + HW_SYMS_FUNC(do_bad) = + (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("do_bad"); + if (!HW_SYMS_FUNC(do_bad)) { + pr_warn("get do_bad fail\n"); + return -1; + } + HW_SYMS_FUNC(enable_debug_monitors) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("enable_debug_monitors"); + if (!HW_SYMS_FUNC(enable_debug_monitors)) { + pr_warn("get enable_debug_monitors fail\n"); + return -1; + } + HW_SYMS_FUNC(read_sanitised_ftr_reg) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("read_sanitised_ftr_reg"); + if (!HW_SYMS_FUNC(read_sanitised_ftr_reg)) { + pr_warn("get read_sanitised_ftr_reg fail\n"); + return -1; + } + HW_SYMS_FUNC(show_regs) = + (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("show_regs"); + if (!HW_SYMS_FUNC(show_regs)) { + pr_warn("get show_regs fail\n"); + return -1; + } + HW_SYMS_FUNC(dump_backtrace) = + (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("dump_backtrace"); + if (!HW_SYMS_FUNC(dump_backtrace)) { + pr_warn("get dump_backtrace fail\n"); + return -1; + } + /*5.0以下内核用的是register_step_hook*/ + HW_SYMS_FUNC(register_step_hook) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("register_step_hook"); + if (!HW_SYMS_FUNC(register_step_hook)) { + /*5.0以上内核用的是register_kernel_step_hook*/ + HW_SYMS_FUNC(register_step_hook) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("register_kernel_step_hook"); + if (!HW_SYMS_FUNC(register_step_hook)) { + pr_warn("get register_step_hook fail\n"); + return -1; + } + } + HW_SYMS_FUNC(unregister_step_hook) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("unregister_step_hook"); + if (!HW_SYMS_FUNC(unregister_step_hook)) { + HW_SYMS_FUNC(unregister_step_hook) = (void *)HW_SYMS_FUNC( + kallsyms_lookup_name)("unregister_kernel_step_hook"); + if (!HW_SYMS_FUNC(unregister_step_hook)) { + pr_warn("get unregister_step_hook fail\n"); + return -1; + } + } + + /*以下不影响驱动使用,只影响根据io地址查询虚拟地址功能*/ + HW_SYMS_VAL(vmap_area_lock) = + (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("vmap_area_lock"); + HW_SYMS_VAL(vmap_area_lock) = + (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("vmap_area_list"); + if ((!HW_SYMS_VAL(vmap_area_lock)) || (!HW_SYMS_VAL(vmap_area_lock))) { + pr_warn("can not get virt from iophys\n"); + } + + return 0; +} + +/*hp init*/ +static int __init hw_bp_init(void) +{ + if (hw_get_kernel_api()) { + return -1; + } + + core_num_brps = hw_get_num_brps(); + core_num_wrps = hw_get_num_wrps(); + + pr_info("found %d breakpoint and %d watchpoint registers.\n", + core_num_brps, core_num_wrps); + + /* register dbg exception hook */ + /*bp*/ + /*save pre vars*/ + HW_SYMS_VAL(default_fault_info) + [0].fn = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].fn; + HW_SYMS_VAL(default_fault_info) + [0].sig = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].sig; + HW_SYMS_VAL(default_fault_info) + [0].code = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].code; + HW_SYMS_VAL(default_fault_info) + [0].name = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].name; + + /*new*/ + HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].fn = hw_bp_handler; + HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].sig = SIGTRAP; + HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].code = TRAP_HWBKPT; + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWBP].name = "hw-breakpoint handler"; + /*wp*/ + /*save pre vars*/ + HW_SYMS_VAL(default_fault_info) + [1].fn = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].fn; + HW_SYMS_VAL(default_fault_info) + [1].sig = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].sig; + HW_SYMS_VAL(default_fault_info) + [1].code = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].code; + HW_SYMS_VAL(default_fault_info) + [1].name = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].name; + /*new*/ + HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].fn = hw_wp_handler; + HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].sig = SIGTRAP; + HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].code = TRAP_HWBKPT; + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWWP].name = "hw-watchpoint handler"; + HW_SYMS_FUNC(register_step_hook)(&ghw_step_hook); +#ifdef CONFIG_CPU_PM + HW_SYMS_VAL(default_hw_breakpoint_restore) = + *HW_SYMS_VAL(hw_breakpoint_restore); + *HW_SYMS_VAL(hw_breakpoint_restore) = (u64)hw_bp_reset; +#endif + hw_bp_manage_init(); + hw_proc_init(); + + pr_info("zwf 11111111111111111111111111111 %s ok\n", __FUNCTION__); + return 0; +} + +static void __exit hw_bp_exit(void) +{ + hw_proc_exit(); + hw_bp_manage_deinit(); +#ifdef CONFIG_CPU_PM + *HW_SYMS_VAL(hw_breakpoint_restore) = + HW_SYMS_VAL(default_hw_breakpoint_restore); +#endif + HW_SYMS_FUNC(unregister_step_hook)(&ghw_step_hook); + /*wp*/ + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWWP].fn = HW_SYMS_VAL(default_fault_info)[1].fn; + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWWP].sig = HW_SYMS_VAL(default_fault_info)[1].sig; + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWWP].code = HW_SYMS_VAL(default_fault_info)[1].code; + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWWP].name = HW_SYMS_VAL(default_fault_info)[1].name; + /*bp*/ + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWBP].fn = HW_SYMS_VAL(default_fault_info)[0].fn; + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWBP].sig = HW_SYMS_VAL(default_fault_info)[0].sig; + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWBP].code = HW_SYMS_VAL(default_fault_info)[0].code; + HW_SYMS_VAL(debug_fault_info) + [DBG_ESR_EVT_HWBP].name = HW_SYMS_VAL(default_fault_info)[0].name; + printk(" hw_bp_exit\n"); +} + +module_init(hw_bp_init); +module_exit(hw_bp_exit); + +MODULE_AUTHOR("Vimoon Zheng "); +MODULE_DESCRIPTION("hardware breakpoint for SKY1 and later"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform: sky1-bp"); diff --git a/code/hw_breakpoint_manage.c b/code/hw_breakpoint_manage.c new file mode 100644 index 00000000..5b96ebeb --- /dev/null +++ b/code/hw_breakpoint_manage.c @@ -0,0 +1,619 @@ +#include +#include +#include +#include +#include +#include "ext_hw_breakpoint.h" + +/*func extern*/ +extern int hw_bp_register(struct hw_bp_info *__percpu *cpu_events, + hw_bp_attr *attr, int *state); +extern void hw_bp_unregister(struct hw_bp_info *__percpu *bp, int state); + +struct hw_bp_manage_info { + struct hw_bp_info **info; /*percpu bp info*/ + hw_bp_attr attr; /*bp attr*/ + int mask; /*bp register cpu mask*/ + char symbol_name[KSYM_SYMBOL_LEN]; /*symbol name of addr*/ +}; +struct hw_bp_manage { + struct hw_bp_manage_info wp[ARM_MAX_WRP]; /*wp*/ + struct hw_bp_manage_info bp[ARM_MAX_BRP]; /*bp*/ + int max_wp_num; /*max num of wp*/ + int max_bp_num; /*max num of bp*/ + int cpu_mask; /*cpu mask, num of cpu*/ + int cpu_num; /**/ + struct mutex lock; /*mutex lock*/ +} __aligned(512); + +static struct hw_bp_manage g_hw_manage; +const char bp_type_str[4][30] = { "HW_BREAKPOINT_R", "HW_BREAKPOINT_W", + "HW_BREAKPOINT_RW", "HW_BREAKPOINT_X" }; + +/*show info of bp*/ +static void hw_bp_show_one(struct hw_bp_manage_info *bp_info, int index) +{ + int cpu; + struct hw_bp_info *bp_percpu; + + pr_info("--------------------------------------------------\n"); + /*index of bp*/ + switch (bp_info->attr.type) { + case HW_BREAKPOINT_R: + case HW_BREAKPOINT_W: + case HW_BREAKPOINT_RW: + case HW_BREAKPOINT_X: { + pr_info("breakpoint[%d]:\n", index); + break; + } + default: { + pr_info("breakpoint[%d] type is error!\n", index); + return; + } + } + + /*bp type*/ + pr_info("\ttype: \t%s\n", bp_type_str[bp_info->attr.type - 1]); + /*symbol name of addr*/ + pr_info("\tname: \t%s\n", bp_info->symbol_name); + /*the range of detect*/ + pr_info("\tmonit: \t0x%llx--->0x%llx\n", bp_info->attr.addr, + bp_info->attr.addr + bp_info->attr.len - 1); + /*detect len*/ + pr_info("\tlen: \t%llu\n", bp_info->attr.len); + /*addr mask*/ + pr_info("\tmask: \t0x%x\n", bp_info->attr.mask); + /*the fact of detect range*/ + pr_info("\trange: \t0x%llx--->0x%llx\n", bp_info->attr.start_addr, + bp_info->attr.end_addr); + pr_info("\tsize: \t%llu\n", + bp_info->attr.end_addr - bp_info->attr.start_addr); + pr_info("\ttimes:\n"); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + cpus_read_lock(); +#else + get_online_cpus(); +#endif + for_each_possible_cpu(cpu) { + if (bp_info->mask & 1 << cpu) { + bp_percpu = per_cpu(*bp_info->info, cpu); + pr_info("\t\tcpu[%d]: \tread: %llu, write: %llu, exec: %llu\n", + cpu, bp_percpu->attr.times.read, + bp_percpu->attr.times.write, + bp_percpu->attr.times.exec); + } + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + cpus_read_unlock(); +#else + put_online_cpus(); +#endif +} + +/*show all bp info*/ +void hw_bp_show_all(void) +{ + struct hw_bp_manage_info *bp_info = NULL; + int i = 0; + + mutex_lock(&g_hw_manage.lock); + for (i = 0; i < g_hw_manage.max_bp_num; i++) { + bp_info = &g_hw_manage.bp[i]; + if (bp_info->mask & g_hw_manage.cpu_mask) { + hw_bp_show_one(bp_info, i); + } + } + + for (i = 0; i < g_hw_manage.max_wp_num; i++) { + bp_info = &g_hw_manage.wp[i]; + if (bp_info->mask & g_hw_manage.cpu_mask) { + hw_bp_show_one(bp_info, i + g_hw_manage.max_bp_num); + } + } + mutex_unlock(&g_hw_manage.lock); +} + +static void hw_bp_uninstall_all(void) +{ + struct hw_bp_manage_info *bp_info = NULL; + int i = 0; + + mutex_lock(&g_hw_manage.lock); + for (i = 0; i < g_hw_manage.max_bp_num; i++) { + bp_info = &g_hw_manage.bp[i]; + if (bp_info->mask & g_hw_manage.cpu_mask) { + hw_bp_unregister(bp_info->info, bp_info->mask); + /*clear info*/ + memset(bp_info->symbol_name, 0, + sizeof(bp_info->symbol_name)); + memset(&bp_info->attr, 0, sizeof(bp_info->attr)); + bp_info->mask = 0; + } + } + + for (i = 0; i < g_hw_manage.max_wp_num; i++) { + bp_info = &g_hw_manage.wp[i]; + if (bp_info->mask & g_hw_manage.cpu_mask) { + hw_bp_unregister(bp_info->info, bp_info->mask); + /*clear info*/ + memset(bp_info->symbol_name, 0, + sizeof(bp_info->symbol_name)); + memset(&bp_info->attr, 0, sizeof(bp_info->attr)); + bp_info->mask = 0; + } + } + mutex_unlock(&g_hw_manage.lock); +} + +static int hw_get_addr_mask(u64 addr, int len) +{ + /*end of the detect addr*/ + u64 addr_tmp = addr + len; + u64 alignment_mask = 0; + int mask, i = 0; + + /*log2(len)*/ + mask = (int)__ilog2_u64(len); + if ((1 << mask) < len) { + mask = mask + 1; + } + for (i = 0; i < mask; i++) { + alignment_mask |= (1 << i); + } + + /*Confirm that the end address is within the actual monitoring range*/ + while (1) { + if ((addr | alignment_mask) >= addr_tmp) { + break; + } + mask = mask + 1; + alignment_mask |= (1 << i); + i++; + } + + if (mask > 31) { + /*arm64 the mask is 0b11111*/ + mask = 31; + } + return mask; +} + +static void hw_bp_handler_default(const hw_bp_callback_data *info, + const struct pt_regs *regs) +{ + pr_info("bp is triger = 0x%llx, type = %s\n", info->addr, + bp_type_str[info->type - 1]); + pr_info("times: read=%llu, write=%llu, exec=%llu\n", info->times.read, + info->times.write, info->times.exec); + HW_SYMS_FUNC(show_regs)((struct pt_regs *)regs); +} + +/*install bp from addr*/ +int hw_bp_install_from_addr(u64 addr, int len, int type, hw_bp_callback handler) +{ + int state, i, max_num, ret, mask = 0; + struct hw_bp_manage_info *bp_info; + u64 start_addr, end_addr; + u64 alignment_mask = 0, real_len = len, offset; + + if ((0 == addr) || (addr < TASK_SIZE)) { + pr_info("hw_bp_install_from_addr para is error\n"); + return -1; + } + + switch (type) { + case HW_BREAKPOINT_R: + case HW_BREAKPOINT_W: + case HW_BREAKPOINT_RW: { + /*wp*/ + bp_info = g_hw_manage.wp; + max_num = g_hw_manage.max_wp_num; + if (len > 8) { + /*len>8, use mask*/ + mask = hw_get_addr_mask(addr, len); + real_len = 4; + } + if (mask != 0) { + /*get mask startaddr&endaddr*/ + for (i = 0; i < mask; i++) { + alignment_mask |= (1 << i); + } + start_addr = addr & ~(alignment_mask); + end_addr = addr | alignment_mask; + } else { + /*len<=8, use LBN*/ + alignment_mask = 0x7; + offset = addr & alignment_mask; + real_len = len << offset; + if (real_len > 8) { + real_len = 8; + } + start_addr = addr & ~(alignment_mask); + end_addr = start_addr + real_len; + } + break; + } + case HW_BREAKPOINT_X: { + /*bp*/ + real_len = 4; + bp_info = g_hw_manage.bp; + max_num = g_hw_manage.max_bp_num; + alignment_mask = 0x3; + offset = addr & alignment_mask; + real_len = len << offset; + if (real_len > 8) { + real_len = 8; + } + start_addr = addr & ~(alignment_mask); + end_addr = start_addr + real_len; + break; + } + default: { + /*bp type error*/ + pr_info("breakpoint type error\n"); + return -1; + } + } + + mutex_lock(&g_hw_manage.lock); + for (i = 0; i < max_num; i++) { + if ((bp_info[i].mask & g_hw_manage.cpu_mask) != 0) { + /*This bp has been set*/ + if (bp_info[i].attr.addr == addr) { + pr_info("[install] The addr [%llx] is already set at index %d\n", + addr, i); + mutex_unlock(&g_hw_manage.lock); + return -1; + } + } + } + + for (i = 0; i < max_num; i++) { + if ((bp_info[i].mask & g_hw_manage.cpu_mask) != 0) { + continue; + } + bp_info[i].attr.len = len; + bp_info[i].attr.real_len = real_len; + bp_info[i].attr.mask = mask; + bp_info[i].attr.type = type; + bp_info[i].attr.addr = addr; + bp_info[i].attr.start_addr = start_addr; + bp_info[i].attr.end_addr = end_addr; + bp_info[i].attr.handler = handler; + if (bp_info[i].attr.handler == NULL) { + bp_info[i].attr.handler = hw_bp_handler_default; + } + break; + } + + if (i == max_num) { + pr_info("[install] breakpoint is full type = %x\n", type); + mutex_unlock(&g_hw_manage.lock); + return -1; + } + + // pr_info("gHwManage.wp[%d].info = %lx\n", i, gHwManage.wp[i].info); + // pr_info("info = %lx,attr=%lx,state=%lx\n", bpInfo[i].info, &bpInfo[i].attr, &state); + ret = hw_bp_register(bp_info[i].info, &bp_info[i].attr, &state); + if (ret) { + goto clear; + } + /*Several CPUs are registered with the breakpoint*/ + bp_info[i].mask = state; + memset(bp_info[i].symbol_name, 0, sizeof(bp_info[i].symbol_name)); + sprint_symbol(bp_info[i].symbol_name, addr); + mutex_unlock(&g_hw_manage.lock); + hw_bp_show_one(&bp_info[i], i); + return 0; +clear: + pr_info("hw_bp_install_from_addr [%llx] error\n", addr); + /*clear bp info*/ + memset(&bp_info[i].attr, 0, sizeof(bp_info[i].attr)); + memset(bp_info[i].symbol_name, 0, sizeof(bp_info[i].symbol_name)); + bp_info[i].mask = 0; + mutex_unlock(&g_hw_manage.lock); + return -1; +} +EXPORT_SYMBOL_GPL(hw_bp_install_from_addr); + +/*从符号设置一个断点*/ +int hw_bp_install_from_symbol(char *name, int len, int type, + hw_bp_callback handler) +{ + int ret = 0; + u64 addr = 0; + + if ((NULL == name) || (HW_BREAKPOINT_INVALID == type)) { + pr_info("HW_breakpointInstallFromSymbol para is error\n"); + return -1; + } + + addr = HW_SYMS_FUNC(kallsyms_lookup_name)(name); + if (0 == addr) { + /*the symbol is invalid*/ + pr_info("Can not find the symbol, name: %s\n", name); + return -1; + } + + ret = hw_bp_install_from_addr(addr, len, type, handler); + if (ret) { + pr_info("HW_breakpointInstallFromSymbol error [%s]\n", name); + return -1; + } + + return 0; +} +EXPORT_SYMBOL_GPL(hw_bp_install_from_symbol); + +void hw_bp_uninstall_from_addr(u64 addr) +{ + int i = 0; + struct hw_bp_manage_info *bp_info = NULL; + + /*traverse bp arrays*/ + /*find bp*/ + mutex_lock(&g_hw_manage.lock); + for (i = 0; i < g_hw_manage.max_bp_num; i++) { + if (g_hw_manage.bp[i].mask & g_hw_manage.cpu_mask) { + if (g_hw_manage.bp[i].attr.addr == addr) { + bp_info = &g_hw_manage.bp[i]; + pr_info("[uninstall] find addr: bp[%d]\n", i); + break; + } + } + } + /*find wp*/ + for (i = 0; (i < g_hw_manage.max_wp_num) && (bp_info == NULL); i++) { + if (g_hw_manage.wp[i].mask & g_hw_manage.cpu_mask) { + if (g_hw_manage.wp[i].attr.addr == addr) { + bp_info = &g_hw_manage.wp[i]; + pr_info("[uninstall] find addr: wp[%d]\n", i); + break; + } + } + } + if (NULL == bp_info) { + pr_info("HW_breakpointUnInstallFromAddr fail,can not find addr:0x%llx\n", + addr); + mutex_unlock(&g_hw_manage.lock); + return; + } + hw_bp_unregister(bp_info->info, bp_info->mask); + /*clear bp info*/ + memset(bp_info->symbol_name, 0, sizeof(bp_info->symbol_name)); + memset(&bp_info->attr, 0, sizeof(bp_info->attr)); + bp_info->mask = 0; + mutex_unlock(&g_hw_manage.lock); +} +EXPORT_SYMBOL_GPL(hw_bp_uninstall_from_addr); + +void hw_bp_uninstall_from_symbol(char *name) +{ + u64 addr = 0; + + if (NULL == name) { + pr_info("HW_breakpointUnInstallFromSymbol para is error\n"); + return; + } + + addr = HW_SYMS_FUNC(kallsyms_lookup_name)(name); + if (0 == addr) { + /*the symbol is invalid*/ + pr_info("[uninstall] Can not find the symbol, name: %s\n", + name); + return; + } + hw_bp_uninstall_from_addr(addr); +} +EXPORT_SYMBOL_GPL(hw_bp_uninstall_from_symbol); + +void hw_free_bp_infos(hw_bp_info_list *info) +{ + hw_bp_info_list *node = NULL, *next = NULL; + + if (info) { + list_for_each_entry_safe(node, next, &info->list, list) { + list_del(&node->list); + if (node->attr) { + kfree(node->attr); + } + kfree(node); + } + if (info->attr) { + kfree(info->attr); + } + kfree(info); + } +} +EXPORT_SYMBOL_GPL(hw_free_bp_infos); + +static void hw_fill_report_data(struct hw_bp_manage_info *bp_info, + hw_bp_info_list *node) +{ + struct hw_bp_info *bp = NULL; + int cpu = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + cpus_read_lock(); +#else + get_online_cpus(); +#endif + for_each_possible_cpu(cpu) { + if (bp_info->mask & 1 << cpu) { + bp = per_cpu(*bp_info->info, cpu); + /*value*/ + node->attr[cpu].type = bp->attr.type; + node->attr[cpu].addr = bp->attr.addr; + node->attr[cpu].len = bp->attr.len; + node->attr[cpu].mask = bp->attr.mask; + node->attr[cpu].times = bp->attr.times; + } + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + cpus_read_unlock(); +#else + put_online_cpus(); +#endif +} + +hw_bp_info_list *hw_get_bp_infos(void) +{ + hw_bp_info_list *head = NULL; + hw_bp_info_list *node = NULL; + struct hw_bp_manage_info *bp_info = NULL; + int i = 0; + + mutex_lock(&g_hw_manage.lock); + for (i = 0; i < g_hw_manage.max_bp_num; i++) { + bp_info = &g_hw_manage.bp[i]; + if (bp_info->mask & g_hw_manage.cpu_mask) { + /*bp is set*/ + if (head == NULL) { + head = kzalloc(sizeof(hw_bp_info_list), + GFP_KERNEL); + if (head == NULL) { + goto err; + } + INIT_LIST_HEAD(&head->list); + head->attr = + kzalloc(sizeof(hw_bp_report) * + g_hw_manage.cpu_num, + GFP_KERNEL); + if (head->attr == NULL) { + goto err; + } + head->cpu_mask = bp_info->mask; + head->cpu_num = g_hw_manage.cpu_num; + hw_fill_report_data(bp_info, head); + } + node = kzalloc(sizeof(hw_bp_info_list), GFP_KERNEL); + if (node == NULL) { + goto err; + } + INIT_LIST_HEAD(&node->list); + list_add_tail(&node->list, &head->list); + node->attr = kzalloc(sizeof(hw_bp_report) * + g_hw_manage.cpu_num, + GFP_KERNEL); + if (node->attr == NULL) { + goto err; + } + node->cpu_mask = bp_info->mask; + node->cpu_num = g_hw_manage.cpu_num; + hw_fill_report_data(bp_info, node); + } + } + + for (i = 0; i < g_hw_manage.max_wp_num; i++) { + bp_info = &g_hw_manage.wp[i]; + if (bp_info->mask & g_hw_manage.cpu_mask) { + /*bp is set*/ + if (head == NULL) { + head = kzalloc(sizeof(hw_bp_info_list), + GFP_KERNEL); + if (head == NULL) { + goto err; + } + INIT_LIST_HEAD(&head->list); + head->attr = + kzalloc(sizeof(hw_bp_report) * + g_hw_manage.cpu_num, + GFP_KERNEL); + if (head->attr == NULL) { + goto err; + } + head->cpu_mask = bp_info->mask; + head->cpu_num = g_hw_manage.cpu_num; + hw_fill_report_data(bp_info, head); + } + node = kzalloc(sizeof(hw_bp_info_list), GFP_KERNEL); + if (node == NULL) { + goto err; + } + INIT_LIST_HEAD(&node->list); + list_add_tail(&node->list, &head->list); + node->attr = kzalloc(sizeof(hw_bp_report) * + g_hw_manage.cpu_num, + GFP_KERNEL); + if (node->attr == NULL) { + goto err; + } + node->cpu_mask = bp_info->mask; + node->cpu_num = g_hw_manage.cpu_num; + hw_fill_report_data(bp_info, node); + } + } + mutex_unlock(&g_hw_manage.lock); + + return head; + +err: + mutex_unlock(&g_hw_manage.lock); + hw_free_bp_infos(head); + return NULL; +} +EXPORT_SYMBOL_GPL(hw_get_bp_infos); + +/*release bp*/ +void hw_bp_manage_deinit(void) +{ + int i = 0; + + hw_bp_uninstall_all(); + + for (i = 0; i < g_hw_manage.max_wp_num; i++) { + free_percpu(g_hw_manage.wp[i].info); + } + + for (i = 0; i < g_hw_manage.max_bp_num; i++) { + free_percpu(g_hw_manage.bp[i].info); + } + mutex_destroy(&g_hw_manage.lock); +} + +/*bp arch init*/ +int hw_bp_manage_init(void) +{ + int cpu = -1, i = 0; + struct hw_bp_info *__percpu *bp = NULL; + + /*get bp&wp num*/ + g_hw_manage.max_bp_num = hw_get_bp_num(TYPE_INST); + g_hw_manage.max_wp_num = hw_get_bp_num(TYPE_DATA); + + /*get CPU num*/ + g_hw_manage.cpu_num = 0; + for_each_online_cpu(cpu) { + g_hw_manage.cpu_mask |= 1 << cpu; + g_hw_manage.cpu_num++; + } + pr_info("CPU MASK = %x\n", g_hw_manage.cpu_mask); + + /*mange mem of bp*/ + for (i = 0; i < g_hw_manage.max_wp_num; i++) { + bp = alloc_percpu(typeof(*bp)); + if (!bp) { + pr_info("wp alloc_percpu fail\n"); + goto free; + } + g_hw_manage.wp[i].info = bp; + bp = NULL; + } + for (i = 0; i < g_hw_manage.max_bp_num; i++) { + bp = alloc_percpu(typeof(*bp)); + if (!bp) { + pr_info("wp alloc_percpu fail\n"); + goto free; + } + g_hw_manage.bp[i].info = bp; + bp = NULL; + } + + mutex_init(&g_hw_manage.lock); + + return 0; + +free: + hw_bp_manage_deinit(); + return -1; +} diff --git a/code/hw_breakpoint_proc.c b/code/hw_breakpoint_proc.c new file mode 100644 index 00000000..05fc6bf9 --- /dev/null +++ b/code/hw_breakpoint_proc.c @@ -0,0 +1,372 @@ +#include +#include +#include +#include +#include +#include +#include +#include "linux/printk.h" +#include +#include "ext_hw_breakpoint.h" +#include "hw_breakpoint_until.h" + +#define PROC_FILE_DEBUG "breakpoint" + +/*func extern*/ +extern void hw_bp_show_all(void); + +/*proc_file handle*/ +static struct proc_dir_entry *proc_file = NULL; + +/*help*/ +char *hw_proc_write_usag = { + "Usage:\n" + "\thw_break support cmd type: \n" + "\t\t1: echo add / > /proc/breakpoint, add a breakpoint\n" + "\t\t\t[type]:\n" + "\t\t\t\t[wp1]: HW_BREAKPOINT_R\n" + "\t\t\t\t[wp2]: HW_BREAKPOINT_W\n" + "\t\t\t\t[wp3]: HW_BREAKPOINT_R|HW_BREAKPOINT_W\n" + "\t\t\t\t[bp]: HW_BREAKPOINT_X\n" + "\t\t\t[len]:[0,8] (2^3,2^31]\n" + "\t\t2: echo del > /proc/breakpoint, del a breakpoint\n" + "\t\t3: echo get ptr/val > /proc/breakpoint, search &symbol/*(&symbol)\n" + "\t\t4: echo iophy > /proc/breakpoint, search all of ioaddr map virt\n" +}; +/*example*/ +char *hw_proc_write_example = { + "Example:\n" + "\tThe first step:\n" + "\t\techo add wp3 4 hw_test_value0 > /proc/breakpoint, add a watchpoint at " + "&hw_test_value0\n" + "\tThe second step:\n" + "\t\techo write 0 0 > /proc/breakpoint, write hw_test_value0\n" + "\tThe third step:\n" + "\t\techo read 0 0 > /proc/breakpoint, read hw_test_value0\n" + "\tThe forth step:\n" + "\t\techo del hw_test_value0 > /proc/breakpoint, del wawtchpoint at " + "&hw_test_value0\n" +}; + +/*seq show*/ +static int hw_proc_show(struct seq_file *m, void *v) +{ + hw_bp_info_list *info = NULL, *node = NULL; + int i = 0, index = 0; + + /*get info*/ + info = hw_get_bp_infos(); + if (info) { + list_for_each_entry(node, &info->list, list) { + for (i = 0; i < node->cpu_num; i++) { + if (node->cpu_mask & (1 << i)) { + break; + } + } + seq_printf(m, "----------------[%d]----------------\n", + index++); + seq_printf(m, "type: \t0x%x\n", node->attr[i].type); + seq_printf(m, "addr: \t0x%llx\n", node->attr[i].addr); + seq_printf(m, "len: \t0x%llx\n", node->attr[i].len); + seq_printf(m, "mask: \t0x%x\n", node->attr[i].mask); + for (i = 0; i < node->cpu_num; i++) { + if (!(node->cpu_mask & (1 << i))) { + continue; + } + seq_printf(m, "cpu[%d] trigger times:\n", i); + seq_printf( + m, + "\tread: %llu, write: %llu, exec: %llu\n", + node->attr[i].times.read, + node->attr[i].times.write, + node->attr[i].times.exec); + } + } + hw_free_bp_infos(info); + } + return 0; +} + +static int hw_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, hw_proc_show, inode->i_private); +} + +u32 hw_test_value3[32] = { 0 }; +u32 hw_test_value2[32] = { 0 }; +u32 hw_test_value1[32] = { 0 }; +u32 hw_test_value0[32] = { 0 }; + +/*show vm info*/ +static void hw_show_vm(struct vm_struct *area, u64 phy_addr) +{ + pr_info("--------------------------------------------------\n"); + if (area->phys_addr) { + pr_info("\tphy addr:\t0x%llx\n", area->phys_addr); + } + if (area->addr) { + pr_info("\tvirt addr:\t0x%llx\n", (u64)area->addr); + } + if (area->size) { + pr_info("\tsize:\t\t0x%lx\n", area->size); + } + if (area->addr && area->phys_addr) { + pr_info("0x%llx to virt: 0x%llx\n", phy_addr, + (u64)area->addr + phy_addr - area->phys_addr); + } + pr_info("\n"); +} + +/*proc get virt of iophys*/ +static void hw_iophy_to_virt(char *addr_buf) +{ + u64 io_addr = 0; + iophys_info *iophys = NULL, *node = NULL; + + io_addr = simple_strtol(addr_buf, NULL, 0); + iophys = get_iophys_info(io_addr); + + if (iophys) { + list_for_each_entry(node, &iophys->list, list) { + hw_show_vm(&node->area, io_addr); + } + } + free_iophys_info(iophys); +} + +/*proc get handler*/ +static int hw_proc_get(char *type_buf, char *name_buf) +{ + u64 addr = 0; + + /*get symbol addr*/ + addr = HW_SYMS_FUNC(kallsyms_lookup_name)(name_buf); + if (!addr || addr < TASK_SIZE) { + pr_info("can not find symbol %s\n", name_buf); + return -1; + } + if (strcmp("ptr", type_buf) == 0) { + pr_info("&%s = 0x%llx\n", name_buf, addr); + } else if (strcmp("val", type_buf) == 0) { + pr_info("*(%s) = 0x%llx\n", name_buf, *((u64 *)addr)); + } else { + return -1; + } + return 0; +} + +/*proc del bp*/ +static void hw_proc_del(char *name_buf) +{ + u64 uninstall_addr = 0; + + if (name_buf[0] == '0' && name_buf[1] == 'x') { + uninstall_addr = simple_strtol(name_buf, 0, 0); + } + if (uninstall_addr) { + pr_info("will uninstall at 0x%llx\n", uninstall_addr); + hw_bp_uninstall_from_addr(uninstall_addr); + } else { + pr_info("will uninstall at &%s\n", name_buf); + hw_bp_uninstall_from_symbol(name_buf); + } +} + +/*proc add bp*/ +static int hw_proc_add(char *type_buf, char *len_buf, char *name_buf) +{ + char *name = NULL; + int len = HW_BREAKPOINT_LEN_4, type = 0; + u64 install_addr = 0; + + /*check bp type*/ + switch (strlen(type_buf)) { + /*The length is 2 for the bp*/ + case 2: { + type = HW_BREAKPOINT_X; + name = name_buf; + break; + } + /*The length is 3 for the wp, and the third character is the breakpoint type*/ + case 3: { + type = type_buf[2] - '0'; + len = (int)simple_strtoul(len_buf, NULL, 0); + name = name_buf; + break; + } + default: { + return -1; + } + } + /*check type if valid*/ + if (type < 1 || type > 4) { + return -1; + } + + if (name_buf[0] == '0' && name_buf[1] == 'x') { + install_addr = simple_strtol(name_buf, 0, 0); + } + if (install_addr) { + pr_info("will install at 0x%llx\n", install_addr); + hw_bp_install_from_addr(install_addr, len, type, NULL); + } else { + pr_info("will install at &%s\n", name); + hw_bp_install_from_symbol(name, len, type, NULL); + } + return 0; +} + +/*test write*/ +static void hw_proc_rw_test(char *cmd, char *index_of_buf, char *index_in_buf) +{ + int index = (int)simple_strtol(index_of_buf, NULL, 0); + int index1 = (int)simple_strtol(index_in_buf, NULL, 0); + u32 *tmpbuf; + switch (index) { + case 0: { + tmpbuf = hw_test_value0; + break; + } + case 1: { + tmpbuf = hw_test_value1; + break; + } + case 2: { + tmpbuf = hw_test_value2; + break; + } + case 3: + default: { + tmpbuf = hw_test_value3; + break; + } + } + if (strcmp("write", cmd) == 0) { + pr_info("will write hw_test_value%d[%d], addr = %llx\n", index, + index1, (u64)&tmpbuf[index1]); + tmpbuf[index1] = get_random_u32(); + } else if (strcmp("read", cmd) == 0) { + pr_info("will read hw_test_value%d[%d], addr = %llx\n", index, + index1, (u64)&tmpbuf[index1]); + pr_info("hw_test_value%d[%d] = %d\n", index, index1, + tmpbuf[index1]); + } +} + +static ssize_t hw_proc_write(struct file *file, const char __user *p_buf, + size_t count, loff_t *pPos) +{ + size_t ret; + char cmd_buf[128] = { 0 }; + int argc = 0; + char *argv[10] = { NULL }; + + // pr_info("hw_proc_write\n"); + + if ((count > sizeof(cmd_buf)) || (count == 0)) { + pr_info("test proc write, count is error!\n"); + return (ssize_t)count; + } + + memset(cmd_buf, 0, sizeof(cmd_buf)); + ret = copy_from_user(cmd_buf, p_buf, count); + if (0 != ret) { + pr_info("fail to copy data from user!\n"); + return (ssize_t)count; + } + + cmd_buf[count - 1] = '\0'; + memset(argv, 0, sizeof(argv)); + process_cmd_string(cmd_buf, &argc, argv); + + if (strcmp("write", argv[0]) == 0 || strcmp("read", argv[0]) == 0) { + if (argc != 3) { + goto cmdErr; + } + hw_proc_rw_test(argv[0], argv[1], argv[2]); + return (ssize_t)count; + } else if (strcmp("show", argv[0]) == 0) { + hw_bp_show_all(); + return (ssize_t)count; + } else if (strcmp("help", argv[0]) == 0) { + pr_info("%s", hw_proc_write_usag); + pr_info("%s", hw_proc_write_example); + return (ssize_t)count; + } + + if (strcmp("add", argv[0]) == 0) { + if (argc != 4) { + // pr_info("argc = %d\n",argc); + goto cmdErr; + } + if (hw_proc_add(argv[1], argv[2], argv[3])) { + goto cmdErr; + } + } else if (strcmp("del", argv[0]) == 0) { + if (argc != 2) { + // pr_info("argc = %d\n",argc); + goto cmdErr; + } + hw_proc_del(argv[1]); + } else if (strcmp("get", argv[0]) == 0) { + if (argc != 3) { + // pr_info("argc = %d\n",argc); + goto cmdErr; + } + if (hw_proc_get(argv[1], argv[2])) { + goto cmdErr; + } + } else if (strcmp("iophy", argv[0]) == 0) { + if (argc != 2) { + // pr_info("argc = %d\n",argc); + goto cmdErr; + } + hw_iophy_to_virt(argv[1]); + } else { + goto cmdErr; + } + + return (ssize_t)count; +cmdErr: + pr_info("cmd error, echo help > /proc/breakpoint\n"); + return (ssize_t)count; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 1, 10) +static const struct proc_ops hw_proc_fops = { + .proc_open = hw_proc_open, + .proc_write = hw_proc_write, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; +#else +static const struct file_operations hw_proc_fops = { + .proc_open = hw_proc_open, + .proc_write = hw_proc_write, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; +#endif + +int hw_proc_init(void) +{ + proc_file = proc_create(PROC_FILE_DEBUG, S_IRUGO | S_IWUGO, NULL, + &hw_proc_fops); + if (NULL == proc_file) { + pr_info("hw proc init, Create %s proc file failed!\n", + PROC_FILE_DEBUG); + return -ENOMEM; + } + // pr_info(hw_proc_write_usag); + // pr_info(hw_proc_write_example); + return 0; +} + +void hw_proc_exit(void) +{ + if (NULL != proc_file) { + remove_proc_entry(PROC_FILE_DEBUG, NULL); + } +} diff --git a/code/hw_breakpoint_smp.c b/code/hw_breakpoint_smp.c new file mode 100644 index 00000000..f75e4cf0 --- /dev/null +++ b/code/hw_breakpoint_smp.c @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include "ext_hw_breakpoint.h" + +typedef int (*hw_remote_func_f)(void *); + +/*func extern*/ +extern int hw_bp_arch_parse(struct hw_bp_info *bp, const hw_bp_attr *attr, + hw_bp_vc *hw); +extern int hw_bp_install(struct hw_bp_info *bp); +extern int hw_bp_uninstall(struct hw_bp_info *bp); +extern int hw_arch_check_bp_in_kspace(hw_bp_vc *hw); + +struct hw_remote_func_call { + struct hw_bp_info *p; + hw_remote_func_f func; + void *info; + int ret; +}; + +static void hw_remote_func(void *data) +{ + struct hw_remote_func_call *tfc = data; + + /*callback*/ + tfc->ret = tfc->func(tfc->info); +} + +static int hw_cpu_func_call(int cpu, hw_remote_func_f func, void *info) +{ + struct hw_remote_func_call data = { + .p = NULL, + .func = func, + .info = info, + .ret = -ENXIO, /* No such CPU */ + }; + + preempt_disable(); + if (cpu != smp_processor_id()) { + smp_call_function_single(cpu, hw_remote_func, &data, 1); + goto out; + } + + data.ret = func(info); + +out: + preempt_enable(); + return data.ret; +} + +static int hw_bp_parse(struct hw_bp_info *bp, const hw_bp_attr *attr, + hw_bp_vc *hw) +{ + int err; + + err = hw_bp_arch_parse(bp, attr, hw); + if (err) + return err; + + if (hw_arch_check_bp_in_kspace(hw)) { + /*Don't let unprivileged users set a breakpoint in the trappath to avoid trap recursion attacks.*/ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + } + + return 0; +} + +static int hw_bp_info_del(void *p) +{ + struct hw_bp_info *bp = (struct hw_bp_info *)p; + return hw_bp_uninstall(bp); +} + +static int hw_bp_info_add(void *p) +{ + struct hw_bp_info *bp = (struct hw_bp_info *)p; + return hw_bp_install(bp); +} + +static int hw_bp_info_init(struct hw_bp_info *bp) +{ + int err; + hw_bp_vc hw = {}; + + /*parse*/ + err = hw_bp_parse(bp, &bp->attr, &hw); + if (err) + return err; + + bp->info = hw; + + return 0; +} + +static struct hw_bp_info *hw_bp_info_alloc(const hw_bp_attr *attr, int cpu) +{ + struct hw_bp_info *bp = NULL; + int err; + + bp = kzalloc(sizeof(*bp), GFP_KERNEL); + if (!bp) { + pr_info("bp alloc fail\n"); + return ERR_PTR(-ENOMEM); + } + + bp->cpu = cpu; + bp->attr = *attr; + + /*bp info init*/ + err = hw_bp_info_init(bp); + if (err) { + pr_info("hw_bp_info_init fail\n"); + return ERR_PTR(err); + } + /*smp_call_function_single in kgdb is error?*/ + err = hw_cpu_func_call(cpu, hw_bp_info_add, bp); + if (err) { + pr_info("hw_bp_info_add fail\n"); + return ERR_PTR(err); + } + + return bp; +} + +static void hw_bp_info_free(struct hw_bp_info *bp, int cpu) +{ + hw_cpu_func_call(cpu, hw_bp_info_del, bp); + kfree(bp); +} + +void hw_bp_unregister(struct hw_bp_info *__percpu *bp, int state) +{ + int cpu; + + if (bp == NULL) { + return; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + cpus_read_lock(); +#else + get_online_cpus(); +#endif + for_each_possible_cpu(cpu) { + if (state & 1 << cpu) { + hw_bp_info_free(per_cpu(*bp, cpu), cpu); + } + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + cpus_read_unlock(); +#else + put_online_cpus(); +#endif +} + +int hw_bp_register(struct hw_bp_info *__percpu *cpu_events, hw_bp_attr *attr, + int *state) +{ + struct hw_bp_info *bp; + int cpu; + + if (cpu_events == NULL || attr == NULL || state == NULL) { + pr_info("hw_bp_register para is NULL\n"); + return -1; + } + + *state = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + cpus_read_lock(); +#else + get_online_cpus(); +#endif + for_each_online_cpu(cpu) { + bp = hw_bp_info_alloc(attr, cpu); + if (IS_ERR(bp)) { + pr_info("hw_bp_info_alloc error at CPU[%d]\n", cpu); + } + /*cpu success mask*/ + *state |= 1 << cpu; + /*percpu bp*/ + per_cpu(*cpu_events, cpu) = bp; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + cpus_read_unlock(); +#else + put_online_cpus(); +#endif + + return 0; +} diff --git a/code/hw_breakpoint_until.c b/code/hw_breakpoint_until.c new file mode 100644 index 00000000..d57bec65 --- /dev/null +++ b/code/hw_breakpoint_until.c @@ -0,0 +1,139 @@ +#include +#include "ext_hw_breakpoint.h" +#include "hw_breakpoint_until.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 72) +#define VM_LAZY_FREE 0x02 +#define VM_VM_AREA 0x04 +#endif + +#ifdef HW_PROC_CMD_DEBUG +static void print_cmd_params(int argc, char *argv[]) +{ + int loop = 0; + + for (loop = 0; loop < argc; loop++) { + pr_info("loop:%d, %s\n", loop, argv[loop]); + } +} +#endif + +void process_cmd_string(char *p_buf, int *p_argc, char *p_argv[]) +{ + int i_argc; + char *p_tmp = p_buf; + + p_argv[0] = p_buf; + i_argc = 1; + + while (*p_tmp) { + if (' ' == *p_tmp) { + *p_tmp = '\0'; + p_argv[i_argc++] = p_tmp + 1; + } + + p_tmp++; + } + *p_argc = i_argc; +#ifdef HW_PROC_CMD_DEBUG + print_cmd_params(*pArgc, pArgv); +#endif +} + +void free_iophys_info(iophys_info *info) +{ + iophys_info *node = NULL, *next = NULL; + + if (info) { + list_for_each_entry_safe (node, next, &info->list, list) { + list_del(&node->list); + kfree(node); + } + kfree(info); + } +} +EXPORT_SYMBOL_GPL(free_iophys_info); + +iophys_info *get_iophys_info(u64 addr) +{ + struct vmap_area *va = NULL; + struct vm_struct *area = NULL; + struct vm_struct *next = NULL; + iophys_info *head = NULL; + iophys_info *node = NULL; + + if (!HW_SYMS_VAL(vmap_area_lock) || !HW_SYMS_VAL(vmap_area_lock)) { + pr_info("vmap_area_list or vmap_area_lock is NULL, can not get virt"); + return head; + } + + spin_lock(HW_SYMS_VAL(vmap_area_lock)); + list_for_each_entry (va, HW_SYMS_VAL(vmap_area_list), list) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 72) + if (!(va->flags & VM_VM_AREA)) { + continue; + } +#endif + if (!va) { + continue; + } + area = va->vm; + if (!area) { + continue; + } + if (!(area->flags & VM_IOREMAP) || + area->flags & VM_UNINITIALIZED) { + continue; + } + smp_rmb(); + /*If you find the I/O address, check whether the I/O address you want to query is within the I/O address range*/ + next = area; + while (next) { + if (next->phys_addr && next->size) { + /*The IO address to be queried is within its range*/ + if (addr >= next->phys_addr && + addr < next->phys_addr + next->size) { + /*find it*/ + if (head == NULL) { + head = kzalloc( + sizeof(iophys_info), + GFP_KERNEL); + if (head == NULL) { + goto err; + } + INIT_LIST_HEAD(&head->list); + head->area = *next; + head->virt_addr = + (u64)next->addr + addr - + next->phys_addr; + } + node = kzalloc(sizeof(iophys_info), + GFP_KERNEL); + if (node == NULL) { + goto free; + } + INIT_LIST_HEAD(&node->list); + node->area = *next; + node->virt_addr = (u64)next->addr + + addr - + next->phys_addr; + list_add_tail(&node->list, &head->list); + } + } + next = next->next; + if (next == area) { + break; + } + } + } + spin_unlock(HW_SYMS_VAL(vmap_area_lock)); + + return head; + +free: + free_iophys_info(head); +err: + spin_unlock(HW_SYMS_VAL(vmap_area_lock)); + return NULL; +} +EXPORT_SYMBOL_GPL(get_iophys_info); diff --git a/code/hw_breakpoint_until.h b/code/hw_breakpoint_until.h new file mode 100644 index 00000000..3f054ffa --- /dev/null +++ b/code/hw_breakpoint_until.h @@ -0,0 +1,17 @@ +#ifndef __HW_BREAKPOINT_UNTIL_H +#define __HW_BREAKPOINT_UNTIL_H + +#include + +typedef struct iophys_info { + struct list_head list; + struct vm_struct area; + u64 virt_addr; +} iophys_info; + +void process_cmd_string(char *pBuf, int *pArgc, char *pArgv[]); +/*iophy to virt func*/ +iophys_info *get_iophys_info(u64 addr); +void free_iophys_info(iophys_info *info); + +#endif From 6d067a62c5522bdcc1d575add3253c71e2b781bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Fri, 30 Jan 2026 11:13:47 +0800 Subject: [PATCH 22/35] Delete code directory --- code/Makefile | 29 - code/ext_hw_breakpoint.h | 190 ------- code/hw_breakpoint.c | 1034 ----------------------------------- code/hw_breakpoint_manage.c | 619 --------------------- code/hw_breakpoint_proc.c | 372 ------------- code/hw_breakpoint_smp.c | 193 ------- code/hw_breakpoint_until.c | 139 ----- code/hw_breakpoint_until.h | 17 - 8 files changed, 2593 deletions(-) delete mode 100644 code/Makefile delete mode 100644 code/ext_hw_breakpoint.h delete mode 100644 code/hw_breakpoint.c delete mode 100644 code/hw_breakpoint_manage.c delete mode 100644 code/hw_breakpoint_proc.c delete mode 100644 code/hw_breakpoint_smp.c delete mode 100644 code/hw_breakpoint_until.c delete mode 100644 code/hw_breakpoint_until.h diff --git a/code/Makefile b/code/Makefile deleted file mode 100644 index 558a73ef..00000000 --- a/code/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -CROSS?= aarch64-none-linux-gnu- -KERNEL_DIR?= your kernel dir -CURRENT_PATH:= $(shell pwd) -MODULE_NAME= hw_break - -src_dir?= $(shell pwd) -export src_dir - - -includedir:= -I$(src_dir)/include -EXTRA_CFLAGS+= $(includedir) -g - - -obj-m:= $(MODULE_NAME).o -$(MODULE_NAME)-objs+= hw_breakpoint.o \ - hw_breakpoint_manage.o \ - hw_breakpoint_proc.o \ - hw_breakpoint_smp.o \ - hw_breakpoint_until.o \ - - -all: ko -# 编译驱动 -ko: - make -C $(KERNEL_DIR) M=$(CURRENT_PATH) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" CROSS_COMPILE=${CROSS} ARCH=arm64 modules - - -clean: - make -C $(KERNEL_DIR) M=$(CURRENT_PATH) clean \ No newline at end of file diff --git a/code/ext_hw_breakpoint.h b/code/ext_hw_breakpoint.h deleted file mode 100644 index 71c4519e..00000000 --- a/code/ext_hw_breakpoint.h +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef __EXT_HW_BREAKPOINT_H -#define __EXT_HW_BREAKPOINT_H - -#include -#include -#include - -#define HW_SYMS_FUNC(x) g_kernel_api.fun.x -#define HW_SYMS_VAL(x) g_kernel_api.val.x - -typedef struct hw_trigger_times { - u64 read; - u64 write; - u64 exec; -} hw_trigger_times; - -typedef struct hw_bp_callback_data { - u32 type; - u64 addr; - hw_trigger_times times; -} hw_bp_callback_data; - -typedef void (*hw_bp_callback)(const hw_bp_callback_data *attr, - const struct pt_regs *regs); - -typedef struct hw_bp_attr { - u32 type; /*bp type*/ - u64 addr; /*The addr of the bp expected to be monitored*/ - u64 start_addr; /*The starting address of the actual monitoring*/ - u64 end_addr; /*The end address of the actual monitoring*/ - u64 len; /*The length of the bp expected to be monitored*/ - u64 real_len; /*LBN len*/ - u32 mask; /*addr mask*/ - hw_trigger_times times; /*trigger times*/ - hw_bp_callback handler; /*user handler*/ - u64 disabled : 1, //63bit - reserved : 63; //0~62bit -} hw_bp_attr; - -/*struct of get info*/ -typedef struct hw_bp_report { - u32 type; /*bp type*/ - u64 addr; /*The addr of the bp expected to be monitored*/ - u64 len; /*The length of the bp expected to be monitored*/ - u32 mask; - hw_trigger_times times; /*trigger times*/ -} hw_bp_report; -typedef struct hw_bp_info_list { - struct list_head list; /*list*/ - hw_bp_report *attr; /*bp attr. attr[cpu_id]*/ - int cpu_mask; /*success install of cpu*/ - int cpu_num; /*total cpu num*/ -} hw_bp_info_list; - -typedef struct hw_bp_ctrl_reg { - u32 reserved2 : 3, //29~31bit, - mask : 5, //24~28bit, addr mask,mask=0b11111: (mask2^0b11111 the low bit addr), support 8~2G range - reserved1 : 3, //21~23bit, - wt : 1, //20bit, watchpoint type, Unlinked(0)/linked(1) data address match. - lbn : 4, //16~19bit, WT is only required to be set when setting, which is related to link breakpoints - ssc : 2, //14,15bit, Security state control, which controls what state will listen for breakpoint events - hmc : 1, //13bit, Use in conjunction with the above fields - len : 8, //5~12bit, LBN of len, Each bit represents 1 byte and a maximum of 8 bytes - type : 2, //3~4bit, bp type wp/bp - privilege : 2, //1~2bit, The EL level at the time of the last breakpoint setting is used with SSC and HMC - enabled : 1; //0bit, bp enable -} hw_bp_ctrl_reg; - -typedef struct hw_bp_vc { - u64 address; - hw_bp_ctrl_reg ctrl; - u64 trigger; - u8 access_type; -} hw_bp_vc; - -struct hw_bp_info { - int cpu; - hw_bp_attr attr; - hw_bp_vc info; -}; - -struct fault_info { - int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); - int sig; - int code; - const char *name; -}; -typedef struct hw_kernel_api { - struct { - unsigned long (*kallsyms_lookup_name)( - const char *name); /*search symbols func*/ - void (*register_step_hook)(struct step_hook *hook); - void (*unregister_step_hook)(struct step_hook *hook); - void (*enable_debug_monitors)(enum dbg_active_el el); - void (*disable_debug_monitors)(enum dbg_active_el el); - int (*kernel_active_single_step)(void); - void (*kernel_enable_single_step)(struct pt_regs *regs); - void (*kernel_disable_single_step)(void); - u64 (*read_sanitised_ftr_reg)(u32 id); - void (*show_regs)(struct pt_regs *); - void (*dump_backtrace)(struct pt_regs *regs, - struct task_struct *tsk); - void (*do_bad)(unsigned long addr, unsigned int esr, - struct pt_regs *regs); - } __aligned(128) fun; - struct { -#ifdef CONFIG_CPU_PM - u64 *hw_breakpoint_restore; - u64 default_hw_breakpoint_restore; -#endif - struct fault_info *debug_fault_info; - struct fault_info default_fault_info[2]; - spinlock_t *vmap_area_lock; /*kernel vm spinlock*/ - struct list_head *vmap_area_list; /*kernel vm list*/ - } __aligned(128) val; - -} hw_kernel_api; - -extern hw_kernel_api g_kernel_api; - -/*encode reg*/ -static inline u32 hw_encode_ctrl_reg(hw_bp_ctrl_reg ctrl) -{ - u32 val = (ctrl.mask << 24) | (ctrl.len << 5) | (ctrl.type << 3) | - (ctrl.privilege << 1) | ctrl.enabled; - - if (is_kernel_in_hyp_mode() && ctrl.privilege == AARCH64_BREAKPOINT_EL1) - val |= DBG_HMC_HYP; - - return val; -} - -/*decode reg*/ -static inline void hw_decode_ctrl_reg(u32 reg, hw_bp_ctrl_reg *ctrl) -{ - ctrl->enabled = reg & 0x1; - reg >>= 1; - ctrl->privilege = reg & 0x3; - reg >>= 2; - ctrl->type = reg & 0x3; - reg >>= 2; - ctrl->len = reg & 0xff; - reg >>= 19; - ctrl->mask = reg & 0x1f; -} - -static inline hw_bp_vc *hw_get_vc(struct hw_bp_info *bp) -{ - return &bp->info; -} - -/* Determine number of BRP registers available. */ -static inline int hw_get_num_brps(void) -{ - u64 dfr0 = HW_SYMS_FUNC(read_sanitised_ftr_reg)(SYS_ID_AA64DFR0_EL1); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_BRPs_SHIFT); -#else - return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_BRPS_SHIFT); -#endif -} - -/* Determine number of WRP registers available. */ -static inline int hw_get_num_wrps(void) -{ - u64 dfr0 = HW_SYMS_FUNC(read_sanitised_ftr_reg)(SYS_ID_AA64DFR0_EL1); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_WRPs_SHIFT); -#else - return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_WRPS_SHIFT); -#endif -} - -int hw_get_bp_num(int type); -void hw_proc_exit(void); -void hw_bp_manage_deinit(void); - -/*user handler*/ -/*install/uninstall*/ -int hw_bp_install_from_addr(u64 addr, int len, int type, - hw_bp_callback handler); -void hw_bp_uninstall_from_addr(u64 addr); -int hw_bp_install_from_symbol(char *name, int len, int type, - hw_bp_callback handler); -void hw_bp_uninstall_from_symbol(char *name); -/*get install bp info*/ -hw_bp_info_list *hw_get_bp_infos(void); -void hw_free_bp_infos(hw_bp_info_list *info); - -#endif \ No newline at end of file diff --git a/code/hw_breakpoint.c b/code/hw_breakpoint.c deleted file mode 100644 index 0c9beac4..00000000 --- a/code/hw_breakpoint.c +++ /dev/null @@ -1,1034 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "ext_hw_breakpoint.h" - -/*func extern*/ -extern int hw_bp_manage_init(void); -extern int hw_proc_init(void); - -enum hw_breakpoint_ops { - HW_BREAKPOINT_INSTALL, - HW_BREAKPOINT_UNINSTALL, - HW_BREAKPOINT_RESTORE -}; - -/* Breakpoint currently in use for each BRP. */ -static DEFINE_PER_CPU(struct hw_bp_info *, bp_on_reg[ARM_MAX_BRP]); - -/* Watchpoint currently in use for each WRP. */ -static DEFINE_PER_CPU(struct hw_bp_info *, wp_on_reg[ARM_MAX_WRP]); - -/* Currently stepping a per-CPU kernel breakpoint. */ -static DEFINE_PER_CPU(int, stepping_kernel_bp); - -/* Number of BRP/WRP registers on this CPU. */ -static int core_num_brps; -static int core_num_wrps; - -/*kernel vars*/ -hw_kernel_api g_kernel_api; - -/*get bp num*/ -int hw_get_bp_num(int type) -{ - switch (type) { - case TYPE_INST: - return hw_get_num_brps(); - case TYPE_DATA: - return hw_get_num_wrps(); - default: - pr_info("unknown slot type: %d\n", type); - return 0; - } -} - -#define READ_WB_REG_CASE(OFF, N, REG, VAL) \ - case ((OFF) + (N)): \ - AARCH64_DBG_READ(N, REG, VAL); \ - break - -#define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ - case ((OFF) + (N)): \ - AARCH64_DBG_WRITE(N, REG, VAL); \ - break - -#define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \ - READ_WB_REG_CASE(OFF, 0, REG, VAL); \ - READ_WB_REG_CASE(OFF, 1, REG, VAL); \ - READ_WB_REG_CASE(OFF, 2, REG, VAL); \ - READ_WB_REG_CASE(OFF, 3, REG, VAL); \ - READ_WB_REG_CASE(OFF, 4, REG, VAL); \ - READ_WB_REG_CASE(OFF, 5, REG, VAL); \ - READ_WB_REG_CASE(OFF, 6, REG, VAL); \ - READ_WB_REG_CASE(OFF, 7, REG, VAL); \ - READ_WB_REG_CASE(OFF, 8, REG, VAL); \ - READ_WB_REG_CASE(OFF, 9, REG, VAL); \ - READ_WB_REG_CASE(OFF, 10, REG, VAL); \ - READ_WB_REG_CASE(OFF, 11, REG, VAL); \ - READ_WB_REG_CASE(OFF, 12, REG, VAL); \ - READ_WB_REG_CASE(OFF, 13, REG, VAL); \ - READ_WB_REG_CASE(OFF, 14, REG, VAL); \ - READ_WB_REG_CASE(OFF, 15, REG, VAL) - -#define GEN_WRITE_WB_REG_CASES(OFF, REG, VAL) \ - WRITE_WB_REG_CASE(OFF, 0, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 15, REG, VAL) - -/*read bp reg*/ -static u64 hw_read_bp_reg(int reg, int n) -{ - u64 val = 0; - - switch (reg + n) { - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, - AARCH64_DBG_REG_NAME_BVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, - AARCH64_DBG_REG_NAME_BCR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, - AARCH64_DBG_REG_NAME_WVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, - AARCH64_DBG_REG_NAME_WCR, val); - default: - pr_info("attempt to read from unknown breakpoint register %d\n", - n); - } - - return val; -} -NOKPROBE_SYMBOL(hw_read_bp_reg); - -/*write bp reg*/ -static void hw_write_bp_reg(int reg, int n, u64 val) -{ - switch (reg + n) { - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, - AARCH64_DBG_REG_NAME_BVR, val); - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, - AARCH64_DBG_REG_NAME_BCR, val); - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WVR, - AARCH64_DBG_REG_NAME_WVR, val); - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WCR, - AARCH64_DBG_REG_NAME_WCR, val); - default: - pr_info("attempt to write to unknown breakpoint register %d\n", - n); - } - /*Clear the pipeline to ensure that all previous instructions have been completed before the new instructions are executed*/ - isb(); -} -NOKPROBE_SYMBOL(hw_write_bp_reg); - -/*get elx level*/ -static enum dbg_active_el hw_get_debug_exception_level(int privilege) -{ - switch (privilege) { - case AARCH64_BREAKPOINT_EL0: - return DBG_ACTIVE_EL0; - case AARCH64_BREAKPOINT_EL1: - return DBG_ACTIVE_EL1; - default: - pr_info("invalid breakpoint privilege level %d\n", privilege); - return -EINVAL; - } -} -NOKPROBE_SYMBOL(hw_get_debug_exception_level); - -/** - * hw_bp_slot_setup - Insert/remove bp in global variables - * - * @slots: pointer to the global variables - * @max_slots: max bp num - * @bp: bp info - * @ops: type of bp - * - * Return: - * success: return the number of bp - * -ENOSPC no space - * -EINVAL cmd ops - */ -static int hw_bp_slot_setup(struct hw_bp_info **slots, int max_slots, - struct hw_bp_info *bp, enum hw_breakpoint_ops ops) -{ - int i; - struct hw_bp_info **slot; - - for (i = 0; i < max_slots; ++i) { - slot = &slots[i]; - switch (ops) { - case HW_BREAKPOINT_INSTALL: - if (!*slot) { - *slot = bp; - return i; - } - break; - case HW_BREAKPOINT_UNINSTALL: - if (*slot == bp) { - *slot = NULL; - return i; - } - break; - case HW_BREAKPOINT_RESTORE: - if (*slot == bp) - return i; - break; - default: - pr_info("Unhandled hw breakpoint ops %d\n", ops); - return -EINVAL; - } - } - return -ENOSPC; -} - -/*bp control install/uninstall*/ -static int hw_bp_control(struct hw_bp_info *bp, enum hw_breakpoint_ops ops) -{ - hw_bp_vc *info = hw_get_vc(bp); - struct hw_bp_info **slots; - int i, max_slots, ctrl_reg, val_reg; - enum dbg_active_el dbg_el = - hw_get_debug_exception_level(info->ctrl.privilege); - u32 ctrl; - - // pr_info("the real CPU = %d\n", smp_processor_id()); - - if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { - /* Breakpoint */ - ctrl_reg = AARCH64_DBG_REG_BCR; - val_reg = AARCH64_DBG_REG_BVR; - slots = this_cpu_ptr(bp_on_reg); - max_slots = core_num_brps; - } else { - /* Watchpoint */ - ctrl_reg = AARCH64_DBG_REG_WCR; - val_reg = AARCH64_DBG_REG_WVR; - slots = this_cpu_ptr(wp_on_reg); - max_slots = core_num_wrps; - } - - i = hw_bp_slot_setup(slots, max_slots, bp, ops); - - if (WARN_ONCE(i < 0, "Can't find any breakpoint slot")) - return i; - - switch (ops) { - case HW_BREAKPOINT_INSTALL: - /*Ensure debug monitors are enabled at the correct exception level.*/ - HW_SYMS_FUNC(enable_debug_monitors)(dbg_el); - fallthrough; - /* Fall through */ - case HW_BREAKPOINT_RESTORE: - /* Setup the address register. */ - hw_write_bp_reg(val_reg, i, info->address); - - /* Setup the control register. */ - ctrl = hw_encode_ctrl_reg(info->ctrl); - // pr_info("CTRL REG = %x\n", ctrl); - hw_write_bp_reg(ctrl_reg, i, ctrl); - break; - case HW_BREAKPOINT_UNINSTALL: - /* Reset the control register. */ - hw_write_bp_reg(ctrl_reg, i, 0); - - /*Release the debug monitors for the correct exception level.*/ - HW_SYMS_FUNC(disable_debug_monitors)(dbg_el); - break; - } - - return 0; -} - -/* - * Install a breakpoint. - */ -int hw_bp_install(struct hw_bp_info *bp) -{ - return hw_bp_control(bp, HW_BREAKPOINT_INSTALL); -} - -int hw_bp_uninstall(struct hw_bp_info *bp) -{ - return hw_bp_control(bp, HW_BREAKPOINT_UNINSTALL); -} - -/*get len from LBN bit*/ -static int hw_get_hbp_Len(u8 hbp_len) -{ - int len_in_bytes = 0; - - switch (hbp_len) { - case ARM_BREAKPOINT_LEN_1: - len_in_bytes = 1; - break; - case ARM_BREAKPOINT_LEN_2: - len_in_bytes = 2; - break; - case ARM_BREAKPOINT_LEN_3: - len_in_bytes = 3; - break; - case ARM_BREAKPOINT_LEN_4: - len_in_bytes = 4; - break; - case ARM_BREAKPOINT_LEN_5: - len_in_bytes = 5; - break; - case ARM_BREAKPOINT_LEN_6: - len_in_bytes = 6; - break; - case ARM_BREAKPOINT_LEN_7: - len_in_bytes = 7; - break; - case ARM_BREAKPOINT_LEN_8: - default: - len_in_bytes = 8; - break; - } - - return len_in_bytes; -} - -/* - * Check whether bp virtual address is in kernel space. - */ -int hw_arch_check_bp_in_kspace(hw_bp_vc *hw) -{ - unsigned int len; - unsigned long va; - - va = hw->address; - len = hw_get_hbp_Len(hw->ctrl.len); - - /*get addr & len from mask*/ - if (hw->ctrl.mask) { - len = 1 << hw->ctrl.mask; - } - - return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); -} - -/* - * bp info to ctrl reg - */ -static int hw_arch_build_bp_info(struct hw_bp_info *bp, const hw_bp_attr *attr, - hw_bp_vc *hw) -{ - /* Type */ - switch (attr->type) { - case HW_BREAKPOINT_X: - hw->ctrl.type = ARM_BREAKPOINT_EXECUTE; - break; - case HW_BREAKPOINT_R: - hw->ctrl.type = ARM_BREAKPOINT_LOAD; - break; - case HW_BREAKPOINT_W: - hw->ctrl.type = ARM_BREAKPOINT_STORE; - break; - case HW_BREAKPOINT_RW: - hw->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; - break; - default: - return -EINVAL; - } - - /* Len */ - switch (attr->real_len) { - case HW_BREAKPOINT_LEN_1: - hw->ctrl.len = ARM_BREAKPOINT_LEN_1; - break; - case HW_BREAKPOINT_LEN_2: - hw->ctrl.len = ARM_BREAKPOINT_LEN_2; - break; - case HW_BREAKPOINT_LEN_3: - hw->ctrl.len = ARM_BREAKPOINT_LEN_3; - break; - case HW_BREAKPOINT_LEN_4: - hw->ctrl.len = ARM_BREAKPOINT_LEN_4; - break; - case HW_BREAKPOINT_LEN_5: - hw->ctrl.len = ARM_BREAKPOINT_LEN_5; - break; - case HW_BREAKPOINT_LEN_6: - hw->ctrl.len = ARM_BREAKPOINT_LEN_6; - break; - case HW_BREAKPOINT_LEN_7: - hw->ctrl.len = ARM_BREAKPOINT_LEN_7; - break; - case HW_BREAKPOINT_LEN_8: - hw->ctrl.len = ARM_BREAKPOINT_LEN_8; - break; - default: - return -EINVAL; - } - - /* only permit breakpoints of length 4 */ - if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE) { - hw->ctrl.len = ARM_BREAKPOINT_LEN_4; - } - - /* wp addr mask */ - hw->ctrl.mask = attr->mask; - /* Address */ - hw->address = attr->start_addr; - - /* - * Privilege - * Note that we disallow combined EL0/EL1 breakpoints because - * that would complicate the stepping code. - */ - if (hw_arch_check_bp_in_kspace(hw)) - hw->ctrl.privilege = AARCH64_BREAKPOINT_EL1; - else - hw->ctrl.privilege = AARCH64_BREAKPOINT_EL0; - - /* Enabled */ - hw->ctrl.enabled = !attr->disabled; - - return 0; -} - -/* parse bp info */ -int hw_bp_arch_parse(struct hw_bp_info *bp, const hw_bp_attr *attr, - hw_bp_vc *hw) -{ - int ret; - - /* Build the arch_hw_breakpoint. */ - ret = hw_arch_build_bp_info(bp, attr, hw); - if (ret) - return ret; - - pr_info("ctrl.len=%x,mask=%d,enabled=%d,address=%llx\n", hw->ctrl.len, - hw->ctrl.mask, hw->ctrl.enabled, hw->address); - - return 0; -} - -/* enable/disable a bp */ -static void hw_toggle_bp_registers(int reg, enum dbg_active_el el, int enable) -{ - int i, max_slots, privilege; - u32 ctrl; - struct hw_bp_info **slots; - - switch (reg) { - case AARCH64_DBG_REG_BCR: - slots = this_cpu_ptr(bp_on_reg); - max_slots = core_num_brps; - break; - case AARCH64_DBG_REG_WCR: - slots = this_cpu_ptr(wp_on_reg); - max_slots = core_num_wrps; - break; - default: - return; - } - - for (i = 0; i < max_slots; ++i) { - if (!slots[i]) - continue; - - privilege = hw_get_vc(slots[i])->ctrl.privilege; - if (hw_get_debug_exception_level(privilege) != el) - continue; - - ctrl = hw_read_bp_reg(reg, i); - if (enable) - ctrl |= 0x1; - else - ctrl &= ~0x1; - hw_write_bp_reg(reg, i, ctrl); - } -} -NOKPROBE_SYMBOL(hw_toggle_bp_registers); - -/*bp events exception handler*/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) -static int hw_bp_handler(unsigned long unused, unsigned long esr, - struct pt_regs *regs) -#else -static int hw_bp_handler(unsigned long unused, unsigned int esr, - struct pt_regs *regs) -#endif -{ - int i, *kernel_step; - u32 ctrl_reg; - u64 addr, val; - struct hw_bp_info *bp, **slots; - hw_bp_ctrl_reg ctrl; - - slots = this_cpu_ptr(bp_on_reg); - addr = instruction_pointer(regs); - - for (i = 0; i < core_num_brps; ++i) { - rcu_read_lock(); - - bp = slots[i]; - - if (bp == NULL) - goto unlock; - - /* Check if the breakpoint value matches. */ - val = hw_read_bp_reg(AARCH64_DBG_REG_BVR, i); - if (val != (addr & ~0x3)) - goto unlock; - - /* Possible match, check the byte address select to confirm. */ - ctrl_reg = hw_read_bp_reg(AARCH64_DBG_REG_BCR, i); - hw_decode_ctrl_reg(ctrl_reg, &ctrl); - if (!((1 << (addr & 0x3)) & ctrl.len)) - goto unlock; - - hw_get_vc(bp)->trigger = addr; - - unlock: - rcu_read_unlock(); - } - - hw_toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 0); - kernel_step = this_cpu_ptr(&stepping_kernel_bp); - - if (*kernel_step != ARM_KERNEL_STEP_NONE) - return 0; - - if (HW_SYMS_FUNC(kernel_active_single_step)()) { - *kernel_step = ARM_KERNEL_STEP_SUSPEND; - } else { - *kernel_step = ARM_KERNEL_STEP_ACTIVE; - HW_SYMS_FUNC(kernel_enable_single_step)(regs); - } - - return 0; -} -NOKPROBE_SYMBOL(hw_bp_handler); - -/*get dist from trigger to wp addr*/ -static u64 hw_get_distance_from_wp(unsigned long addr, u64 val, - hw_bp_ctrl_reg *ctrl) -{ - addr = untagged_addr(addr); - val = untagged_addr(val); - return addr - val; -} - -/*wp events exception handler*/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) -static int hw_wp_handler(unsigned long addr, unsigned long esr, - struct pt_regs *regs) -#else -static int hw_wp_handler(unsigned long addr, unsigned int esr, - struct pt_regs *regs) -#endif -{ - int i, *kernel_step, access, closest_match = -1; - u64 min_dist = -1, dist; - u32 ctrl_reg; - u64 val; - struct hw_bp_info *wp, **slots; - hw_bp_vc *info = NULL; - hw_bp_ctrl_reg ctrl; - - slots = this_cpu_ptr(wp_on_reg); - - /*find the nearest trigger address*/ - rcu_read_lock(); - for (i = 0; i < core_num_wrps; ++i) { - wp = slots[i]; - if (wp == NULL) - continue; - - /*check type of wp*/ - access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W : - HW_BREAKPOINT_R; - if (!(access & wp->attr.type)) - continue; - - /* Check if the watchpoint value and byte select match. */ - val = hw_read_bp_reg(AARCH64_DBG_REG_WVR, i); - ctrl_reg = hw_read_bp_reg(AARCH64_DBG_REG_WCR, i); - hw_decode_ctrl_reg(ctrl_reg, &ctrl); - dist = hw_get_distance_from_wp(addr, wp->attr.addr, &ctrl); - if (dist < min_dist) { - min_dist = dist; - closest_match = i; - } - /* Is this an exact match? */ - if (dist != 0) - continue; - info = hw_get_vc(wp); - info->trigger = addr; - info->access_type = access; - closest_match = i; - } - if (min_dist > 0 && min_dist != -1) { - /* No exact match found. */ - wp = slots[closest_match]; - info = hw_get_vc(wp); - info->trigger = addr; - info->access_type = access; - } - rcu_read_unlock(); - - /*disable all of wps*/ - hw_toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 0); - kernel_step = this_cpu_ptr(&stepping_kernel_bp); - - if (*kernel_step != ARM_KERNEL_STEP_NONE) - return 0; - - if (HW_SYMS_FUNC(kernel_active_single_step)()) { - *kernel_step = ARM_KERNEL_STEP_SUSPEND; - } else { - *kernel_step = ARM_KERNEL_STEP_ACTIVE; - /*enable ss exception in cur regs*/ - HW_SYMS_FUNC(kernel_enable_single_step)(regs); - } - - return 0; -} -NOKPROBE_SYMBOL(hw_wp_handler); - -/*resume bp states*/ -static int hw_bp_reinstall(struct pt_regs *regs) -{ - // struct debug_info *debug_info = ¤t->thread.debug; - int handled_exception = 0, *kernel_step; - - /*get step states*/ - kernel_step = this_cpu_ptr(&stepping_kernel_bp); - - if (*kernel_step != ARM_KERNEL_STEP_NONE) { - hw_toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 1); - hw_toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 1); - - if (*kernel_step != ARM_KERNEL_STEP_SUSPEND) { - HW_SYMS_FUNC(kernel_disable_single_step()); - handled_exception = 1; - } else { - handled_exception = 0; - } - - *kernel_step = ARM_KERNEL_STEP_NONE; - } - - return !handled_exception; -} -NOKPROBE_SYMBOL(hw_bp_reinstall); - -/*bp reset when cold boot*/ -static int hw_bp_reset(unsigned int cpu) -{ - int i; - struct hw_bp_info **slots; - /* - * When a CPU goes through cold-boot, it does not have any installed - * slot, so it is safe to share the same function for restoring and - * resetting breakpoints; when a CPU is hotplugged in, it goes - * through the slots, which are all empty, hence it just resets control - * and value for debug registers. - * When this function is triggered on warm-boot through a CPU PM - * notifier some slots might be initialized; if so they are - * reprogrammed according to the debug slots content. - */ - for (slots = this_cpu_ptr(bp_on_reg), i = 0; i < core_num_brps; ++i) { - if (slots[i]) { - hw_bp_control(slots[i], HW_BREAKPOINT_RESTORE); - } else { - hw_write_bp_reg(AARCH64_DBG_REG_BCR, i, 0UL); - hw_write_bp_reg(AARCH64_DBG_REG_BVR, i, 0UL); - } - } - - for (slots = this_cpu_ptr(wp_on_reg), i = 0; i < core_num_wrps; ++i) { - if (slots[i]) { - hw_bp_control(slots[i], HW_BREAKPOINT_RESTORE); - } else { - hw_write_bp_reg(AARCH64_DBG_REG_WCR, i, 0UL); - hw_write_bp_reg(AARCH64_DBG_REG_WVR, i, 0UL); - } - } - - return 0; -} - -static void hw_trigger_handler(struct pt_regs *regs) -{ - int i = 0; - struct hw_bp_info *wp, **slots; - hw_bp_callback_data report; - - rcu_read_lock(); - slots = this_cpu_ptr(bp_on_reg); - for (i = 0; i < core_num_brps; ++i) { - wp = slots[i]; - if (wp == NULL) - continue; - if (wp->info.trigger) { - wp->attr.times.exec++; - report.type = HW_BREAKPOINT_X; - report.addr = wp->info.trigger; - report.times = wp->attr.times; - report.type = wp->attr.type; - /*user handler*/ - wp->attr.handler(&report, regs); - - wp->info.trigger = 0; - } - } - slots = this_cpu_ptr(wp_on_reg); - for (i = 0; i < core_num_wrps; ++i) { - wp = slots[i]; - if (wp == NULL) - continue; - if (!wp->info.trigger) { - continue; - } - if (wp->info.trigger >= wp->attr.addr && - wp->info.trigger < wp->attr.addr + wp->attr.len) { - /*The user handler only within the range of addresses that are expected to be detected*/ - if (wp->info.access_type & HW_BREAKPOINT_R) { - wp->attr.times.read++; - } else if (wp->info.access_type & HW_BREAKPOINT_W) { - wp->attr.times.write++; - } - /*user handler*/ - report.type = wp->info.access_type; - report.addr = wp->info.trigger; - report.times = wp->attr.times; - wp->attr.handler(&report, regs); - } - wp->info.trigger = 0; - } - rcu_read_unlock(); -} - -/*ss exception handler, will run user handler*/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) -static int hw_step_brk_fn(struct pt_regs *regs, unsigned long esr) -#else -static int hw_step_brk_fn(struct pt_regs *regs, unsigned int esr) -#endif -{ - int *kernel_step; - - /*step states*/ - kernel_step = this_cpu_ptr(&stepping_kernel_bp); - - if (user_mode(regs) || !(*kernel_step)) - return DBG_HOOK_ERROR; - - hw_trigger_handler(regs); - - if (hw_bp_reinstall(regs)) { - return DBG_HOOK_ERROR; - } -#ifdef CONFIG_KGDB - kgdb_handle_exception(0, SIGTRAP, 0, regs); -#endif - - return DBG_HOOK_HANDLED; -} -NOKPROBE_SYMBOL(hw_step_brk_fn); - -#ifdef CONFIG_CPU_PM -extern void cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)); -#else -static inline void -cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)) -{ -} -#endif - -static struct step_hook ghw_step_hook = { .fn = hw_step_brk_fn }; - -/*search symbol addr*/ -unsigned long kaddr_lookup_name(const char *fname_raw) -{ - int i; - unsigned long kaddr; - char *fname_lookup, *fname; - - fname_lookup = kzalloc(NAME_MAX, GFP_KERNEL); - if (!fname_lookup) - return 0; - - fname = kzalloc(strlen(fname_raw) + 4, GFP_KERNEL); - if (!fname) - return 0; - - /* - * We have to add "+0x0" to the end of our function name - * because that's the format that sprint_symbol() returns - * to us. If we don't do this, then our search can stop - * prematurely and give us the wrong function address! - */ - strcpy(fname, fname_raw); - strcat(fname, "+0x0"); - - /*获取内核代码段基地址*/ - kaddr = (unsigned long)&sprint_symbol; - kaddr &= 0xffffffffff000000; - - /*内核符号不会超过0x100000*16的大小,所以按4字节偏移,挨个找*/ - for (i = 0x0; i < 0x400000; i++) { - /*寻找地址对应的符号名称*/ - sprint_symbol(fname_lookup, kaddr); - /*对比寻找的符号名字*/ - if (strncmp(fname_lookup, fname, strlen(fname)) == 0) { - /*找到了就返回地址*/ - kfree(fname_lookup); - kfree(fname); - return kaddr; - } - /*偏移4字节*/ - kaddr += 0x04; - } - /*没找到地址就返回0*/ - kfree(fname_lookup); - kfree(fname); - return 0; -} - -/*get kallsyms_lookup_name*/ -static int hw_get_kallsyms_lookup_name(void) -{ - HW_SYMS_FUNC(kallsyms_lookup_name) = - (void *)kaddr_lookup_name("kallsyms_lookup_name"); - if (!HW_SYMS_FUNC(kallsyms_lookup_name)) { - printk("get kallsyms_lookup_name fail \n"); - return -1; - } - return 0; -} - -/*get vars from kernel*/ -static int hw_get_kernel_api(void) -{ - memset(&g_kernel_api, 0, sizeof(g_kernel_api)); - if (hw_get_kallsyms_lookup_name()) { - return -1; - } - HW_SYMS_VAL(debug_fault_info) = - (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("debug_fault_info"); - if (!HW_SYMS_VAL(debug_fault_info)) { - pr_warn("get debug_fault_info fail\n"); - return -1; - } - // pr_warn("debug_fault_info = %llx,name = %s\n", &HW_SYMS_VAL(debug_fault_info)[0], - // HW_SYMS_VAL(debug_fault_info)[0].name); - // pr_warn("debug_fault_info = %llx,name = %s\n", &HW_SYMS_VAL(debug_fault_info)[2], - // HW_SYMS_VAL(debug_fault_info)[2].name); -#ifdef CONFIG_CPU_PM - HW_SYMS_VAL(hw_breakpoint_restore) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("hw_breakpoint_restore"); - if (!HW_SYMS_VAL(hw_breakpoint_restore)) { - pr_warn("get hw_breakpoint_restore fail\n"); - return -1; - } - // pr_warn("hw_breakpoint_restore = %llx,%llx\n", HW_SYMS_VAL(hw_breakpoint_restore), - // *HW_SYMS_VAL(hw_breakpoint_restore)); -#endif - HW_SYMS_FUNC(kernel_active_single_step) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("kernel_active_single_step"); - if (!HW_SYMS_FUNC(kernel_active_single_step)) { - pr_warn("get kernel_active_single_step fail\n"); - return -1; - } - HW_SYMS_FUNC(kernel_disable_single_step) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("kernel_disable_single_step"); - if (!HW_SYMS_FUNC(kernel_disable_single_step)) { - pr_warn("get kernel_disable_single_step fail\n"); - return -1; - } - HW_SYMS_FUNC(kernel_enable_single_step) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("kernel_enable_single_step"); - if (!HW_SYMS_FUNC(kernel_enable_single_step)) { - pr_warn("get kernel_enable_single_step fail\n"); - return -1; - } - HW_SYMS_FUNC(disable_debug_monitors) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("disable_debug_monitors"); - if (!HW_SYMS_FUNC(disable_debug_monitors)) { - pr_warn("get disable_debug_monitors fail\n"); - return -1; - } - HW_SYMS_FUNC(do_bad) = - (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("do_bad"); - if (!HW_SYMS_FUNC(do_bad)) { - pr_warn("get do_bad fail\n"); - return -1; - } - HW_SYMS_FUNC(enable_debug_monitors) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("enable_debug_monitors"); - if (!HW_SYMS_FUNC(enable_debug_monitors)) { - pr_warn("get enable_debug_monitors fail\n"); - return -1; - } - HW_SYMS_FUNC(read_sanitised_ftr_reg) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("read_sanitised_ftr_reg"); - if (!HW_SYMS_FUNC(read_sanitised_ftr_reg)) { - pr_warn("get read_sanitised_ftr_reg fail\n"); - return -1; - } - HW_SYMS_FUNC(show_regs) = - (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("show_regs"); - if (!HW_SYMS_FUNC(show_regs)) { - pr_warn("get show_regs fail\n"); - return -1; - } - HW_SYMS_FUNC(dump_backtrace) = - (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("dump_backtrace"); - if (!HW_SYMS_FUNC(dump_backtrace)) { - pr_warn("get dump_backtrace fail\n"); - return -1; - } - /*5.0以下内核用的是register_step_hook*/ - HW_SYMS_FUNC(register_step_hook) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("register_step_hook"); - if (!HW_SYMS_FUNC(register_step_hook)) { - /*5.0以上内核用的是register_kernel_step_hook*/ - HW_SYMS_FUNC(register_step_hook) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("register_kernel_step_hook"); - if (!HW_SYMS_FUNC(register_step_hook)) { - pr_warn("get register_step_hook fail\n"); - return -1; - } - } - HW_SYMS_FUNC(unregister_step_hook) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("unregister_step_hook"); - if (!HW_SYMS_FUNC(unregister_step_hook)) { - HW_SYMS_FUNC(unregister_step_hook) = (void *)HW_SYMS_FUNC( - kallsyms_lookup_name)("unregister_kernel_step_hook"); - if (!HW_SYMS_FUNC(unregister_step_hook)) { - pr_warn("get unregister_step_hook fail\n"); - return -1; - } - } - - /*以下不影响驱动使用,只影响根据io地址查询虚拟地址功能*/ - HW_SYMS_VAL(vmap_area_lock) = - (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("vmap_area_lock"); - HW_SYMS_VAL(vmap_area_lock) = - (void *)HW_SYMS_FUNC(kallsyms_lookup_name)("vmap_area_list"); - if ((!HW_SYMS_VAL(vmap_area_lock)) || (!HW_SYMS_VAL(vmap_area_lock))) { - pr_warn("can not get virt from iophys\n"); - } - - return 0; -} - -/*hp init*/ -static int __init hw_bp_init(void) -{ - if (hw_get_kernel_api()) { - return -1; - } - - core_num_brps = hw_get_num_brps(); - core_num_wrps = hw_get_num_wrps(); - - pr_info("found %d breakpoint and %d watchpoint registers.\n", - core_num_brps, core_num_wrps); - - /* register dbg exception hook */ - /*bp*/ - /*save pre vars*/ - HW_SYMS_VAL(default_fault_info) - [0].fn = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].fn; - HW_SYMS_VAL(default_fault_info) - [0].sig = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].sig; - HW_SYMS_VAL(default_fault_info) - [0].code = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].code; - HW_SYMS_VAL(default_fault_info) - [0].name = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].name; - - /*new*/ - HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].fn = hw_bp_handler; - HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].sig = SIGTRAP; - HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWBP].code = TRAP_HWBKPT; - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWBP].name = "hw-breakpoint handler"; - /*wp*/ - /*save pre vars*/ - HW_SYMS_VAL(default_fault_info) - [1].fn = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].fn; - HW_SYMS_VAL(default_fault_info) - [1].sig = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].sig; - HW_SYMS_VAL(default_fault_info) - [1].code = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].code; - HW_SYMS_VAL(default_fault_info) - [1].name = HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].name; - /*new*/ - HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].fn = hw_wp_handler; - HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].sig = SIGTRAP; - HW_SYMS_VAL(debug_fault_info)[DBG_ESR_EVT_HWWP].code = TRAP_HWBKPT; - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWWP].name = "hw-watchpoint handler"; - HW_SYMS_FUNC(register_step_hook)(&ghw_step_hook); -#ifdef CONFIG_CPU_PM - HW_SYMS_VAL(default_hw_breakpoint_restore) = - *HW_SYMS_VAL(hw_breakpoint_restore); - *HW_SYMS_VAL(hw_breakpoint_restore) = (u64)hw_bp_reset; -#endif - hw_bp_manage_init(); - hw_proc_init(); - - pr_info("zwf 11111111111111111111111111111 %s ok\n", __FUNCTION__); - return 0; -} - -static void __exit hw_bp_exit(void) -{ - hw_proc_exit(); - hw_bp_manage_deinit(); -#ifdef CONFIG_CPU_PM - *HW_SYMS_VAL(hw_breakpoint_restore) = - HW_SYMS_VAL(default_hw_breakpoint_restore); -#endif - HW_SYMS_FUNC(unregister_step_hook)(&ghw_step_hook); - /*wp*/ - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWWP].fn = HW_SYMS_VAL(default_fault_info)[1].fn; - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWWP].sig = HW_SYMS_VAL(default_fault_info)[1].sig; - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWWP].code = HW_SYMS_VAL(default_fault_info)[1].code; - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWWP].name = HW_SYMS_VAL(default_fault_info)[1].name; - /*bp*/ - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWBP].fn = HW_SYMS_VAL(default_fault_info)[0].fn; - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWBP].sig = HW_SYMS_VAL(default_fault_info)[0].sig; - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWBP].code = HW_SYMS_VAL(default_fault_info)[0].code; - HW_SYMS_VAL(debug_fault_info) - [DBG_ESR_EVT_HWBP].name = HW_SYMS_VAL(default_fault_info)[0].name; - printk(" hw_bp_exit\n"); -} - -module_init(hw_bp_init); -module_exit(hw_bp_exit); - -MODULE_AUTHOR("Vimoon Zheng "); -MODULE_DESCRIPTION("hardware breakpoint for SKY1 and later"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform: sky1-bp"); diff --git a/code/hw_breakpoint_manage.c b/code/hw_breakpoint_manage.c deleted file mode 100644 index 5b96ebeb..00000000 --- a/code/hw_breakpoint_manage.c +++ /dev/null @@ -1,619 +0,0 @@ -#include -#include -#include -#include -#include -#include "ext_hw_breakpoint.h" - -/*func extern*/ -extern int hw_bp_register(struct hw_bp_info *__percpu *cpu_events, - hw_bp_attr *attr, int *state); -extern void hw_bp_unregister(struct hw_bp_info *__percpu *bp, int state); - -struct hw_bp_manage_info { - struct hw_bp_info **info; /*percpu bp info*/ - hw_bp_attr attr; /*bp attr*/ - int mask; /*bp register cpu mask*/ - char symbol_name[KSYM_SYMBOL_LEN]; /*symbol name of addr*/ -}; -struct hw_bp_manage { - struct hw_bp_manage_info wp[ARM_MAX_WRP]; /*wp*/ - struct hw_bp_manage_info bp[ARM_MAX_BRP]; /*bp*/ - int max_wp_num; /*max num of wp*/ - int max_bp_num; /*max num of bp*/ - int cpu_mask; /*cpu mask, num of cpu*/ - int cpu_num; /**/ - struct mutex lock; /*mutex lock*/ -} __aligned(512); - -static struct hw_bp_manage g_hw_manage; -const char bp_type_str[4][30] = { "HW_BREAKPOINT_R", "HW_BREAKPOINT_W", - "HW_BREAKPOINT_RW", "HW_BREAKPOINT_X" }; - -/*show info of bp*/ -static void hw_bp_show_one(struct hw_bp_manage_info *bp_info, int index) -{ - int cpu; - struct hw_bp_info *bp_percpu; - - pr_info("--------------------------------------------------\n"); - /*index of bp*/ - switch (bp_info->attr.type) { - case HW_BREAKPOINT_R: - case HW_BREAKPOINT_W: - case HW_BREAKPOINT_RW: - case HW_BREAKPOINT_X: { - pr_info("breakpoint[%d]:\n", index); - break; - } - default: { - pr_info("breakpoint[%d] type is error!\n", index); - return; - } - } - - /*bp type*/ - pr_info("\ttype: \t%s\n", bp_type_str[bp_info->attr.type - 1]); - /*symbol name of addr*/ - pr_info("\tname: \t%s\n", bp_info->symbol_name); - /*the range of detect*/ - pr_info("\tmonit: \t0x%llx--->0x%llx\n", bp_info->attr.addr, - bp_info->attr.addr + bp_info->attr.len - 1); - /*detect len*/ - pr_info("\tlen: \t%llu\n", bp_info->attr.len); - /*addr mask*/ - pr_info("\tmask: \t0x%x\n", bp_info->attr.mask); - /*the fact of detect range*/ - pr_info("\trange: \t0x%llx--->0x%llx\n", bp_info->attr.start_addr, - bp_info->attr.end_addr); - pr_info("\tsize: \t%llu\n", - bp_info->attr.end_addr - bp_info->attr.start_addr); - pr_info("\ttimes:\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - cpus_read_lock(); -#else - get_online_cpus(); -#endif - for_each_possible_cpu(cpu) { - if (bp_info->mask & 1 << cpu) { - bp_percpu = per_cpu(*bp_info->info, cpu); - pr_info("\t\tcpu[%d]: \tread: %llu, write: %llu, exec: %llu\n", - cpu, bp_percpu->attr.times.read, - bp_percpu->attr.times.write, - bp_percpu->attr.times.exec); - } - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - cpus_read_unlock(); -#else - put_online_cpus(); -#endif -} - -/*show all bp info*/ -void hw_bp_show_all(void) -{ - struct hw_bp_manage_info *bp_info = NULL; - int i = 0; - - mutex_lock(&g_hw_manage.lock); - for (i = 0; i < g_hw_manage.max_bp_num; i++) { - bp_info = &g_hw_manage.bp[i]; - if (bp_info->mask & g_hw_manage.cpu_mask) { - hw_bp_show_one(bp_info, i); - } - } - - for (i = 0; i < g_hw_manage.max_wp_num; i++) { - bp_info = &g_hw_manage.wp[i]; - if (bp_info->mask & g_hw_manage.cpu_mask) { - hw_bp_show_one(bp_info, i + g_hw_manage.max_bp_num); - } - } - mutex_unlock(&g_hw_manage.lock); -} - -static void hw_bp_uninstall_all(void) -{ - struct hw_bp_manage_info *bp_info = NULL; - int i = 0; - - mutex_lock(&g_hw_manage.lock); - for (i = 0; i < g_hw_manage.max_bp_num; i++) { - bp_info = &g_hw_manage.bp[i]; - if (bp_info->mask & g_hw_manage.cpu_mask) { - hw_bp_unregister(bp_info->info, bp_info->mask); - /*clear info*/ - memset(bp_info->symbol_name, 0, - sizeof(bp_info->symbol_name)); - memset(&bp_info->attr, 0, sizeof(bp_info->attr)); - bp_info->mask = 0; - } - } - - for (i = 0; i < g_hw_manage.max_wp_num; i++) { - bp_info = &g_hw_manage.wp[i]; - if (bp_info->mask & g_hw_manage.cpu_mask) { - hw_bp_unregister(bp_info->info, bp_info->mask); - /*clear info*/ - memset(bp_info->symbol_name, 0, - sizeof(bp_info->symbol_name)); - memset(&bp_info->attr, 0, sizeof(bp_info->attr)); - bp_info->mask = 0; - } - } - mutex_unlock(&g_hw_manage.lock); -} - -static int hw_get_addr_mask(u64 addr, int len) -{ - /*end of the detect addr*/ - u64 addr_tmp = addr + len; - u64 alignment_mask = 0; - int mask, i = 0; - - /*log2(len)*/ - mask = (int)__ilog2_u64(len); - if ((1 << mask) < len) { - mask = mask + 1; - } - for (i = 0; i < mask; i++) { - alignment_mask |= (1 << i); - } - - /*Confirm that the end address is within the actual monitoring range*/ - while (1) { - if ((addr | alignment_mask) >= addr_tmp) { - break; - } - mask = mask + 1; - alignment_mask |= (1 << i); - i++; - } - - if (mask > 31) { - /*arm64 the mask is 0b11111*/ - mask = 31; - } - return mask; -} - -static void hw_bp_handler_default(const hw_bp_callback_data *info, - const struct pt_regs *regs) -{ - pr_info("bp is triger = 0x%llx, type = %s\n", info->addr, - bp_type_str[info->type - 1]); - pr_info("times: read=%llu, write=%llu, exec=%llu\n", info->times.read, - info->times.write, info->times.exec); - HW_SYMS_FUNC(show_regs)((struct pt_regs *)regs); -} - -/*install bp from addr*/ -int hw_bp_install_from_addr(u64 addr, int len, int type, hw_bp_callback handler) -{ - int state, i, max_num, ret, mask = 0; - struct hw_bp_manage_info *bp_info; - u64 start_addr, end_addr; - u64 alignment_mask = 0, real_len = len, offset; - - if ((0 == addr) || (addr < TASK_SIZE)) { - pr_info("hw_bp_install_from_addr para is error\n"); - return -1; - } - - switch (type) { - case HW_BREAKPOINT_R: - case HW_BREAKPOINT_W: - case HW_BREAKPOINT_RW: { - /*wp*/ - bp_info = g_hw_manage.wp; - max_num = g_hw_manage.max_wp_num; - if (len > 8) { - /*len>8, use mask*/ - mask = hw_get_addr_mask(addr, len); - real_len = 4; - } - if (mask != 0) { - /*get mask startaddr&endaddr*/ - for (i = 0; i < mask; i++) { - alignment_mask |= (1 << i); - } - start_addr = addr & ~(alignment_mask); - end_addr = addr | alignment_mask; - } else { - /*len<=8, use LBN*/ - alignment_mask = 0x7; - offset = addr & alignment_mask; - real_len = len << offset; - if (real_len > 8) { - real_len = 8; - } - start_addr = addr & ~(alignment_mask); - end_addr = start_addr + real_len; - } - break; - } - case HW_BREAKPOINT_X: { - /*bp*/ - real_len = 4; - bp_info = g_hw_manage.bp; - max_num = g_hw_manage.max_bp_num; - alignment_mask = 0x3; - offset = addr & alignment_mask; - real_len = len << offset; - if (real_len > 8) { - real_len = 8; - } - start_addr = addr & ~(alignment_mask); - end_addr = start_addr + real_len; - break; - } - default: { - /*bp type error*/ - pr_info("breakpoint type error\n"); - return -1; - } - } - - mutex_lock(&g_hw_manage.lock); - for (i = 0; i < max_num; i++) { - if ((bp_info[i].mask & g_hw_manage.cpu_mask) != 0) { - /*This bp has been set*/ - if (bp_info[i].attr.addr == addr) { - pr_info("[install] The addr [%llx] is already set at index %d\n", - addr, i); - mutex_unlock(&g_hw_manage.lock); - return -1; - } - } - } - - for (i = 0; i < max_num; i++) { - if ((bp_info[i].mask & g_hw_manage.cpu_mask) != 0) { - continue; - } - bp_info[i].attr.len = len; - bp_info[i].attr.real_len = real_len; - bp_info[i].attr.mask = mask; - bp_info[i].attr.type = type; - bp_info[i].attr.addr = addr; - bp_info[i].attr.start_addr = start_addr; - bp_info[i].attr.end_addr = end_addr; - bp_info[i].attr.handler = handler; - if (bp_info[i].attr.handler == NULL) { - bp_info[i].attr.handler = hw_bp_handler_default; - } - break; - } - - if (i == max_num) { - pr_info("[install] breakpoint is full type = %x\n", type); - mutex_unlock(&g_hw_manage.lock); - return -1; - } - - // pr_info("gHwManage.wp[%d].info = %lx\n", i, gHwManage.wp[i].info); - // pr_info("info = %lx,attr=%lx,state=%lx\n", bpInfo[i].info, &bpInfo[i].attr, &state); - ret = hw_bp_register(bp_info[i].info, &bp_info[i].attr, &state); - if (ret) { - goto clear; - } - /*Several CPUs are registered with the breakpoint*/ - bp_info[i].mask = state; - memset(bp_info[i].symbol_name, 0, sizeof(bp_info[i].symbol_name)); - sprint_symbol(bp_info[i].symbol_name, addr); - mutex_unlock(&g_hw_manage.lock); - hw_bp_show_one(&bp_info[i], i); - return 0; -clear: - pr_info("hw_bp_install_from_addr [%llx] error\n", addr); - /*clear bp info*/ - memset(&bp_info[i].attr, 0, sizeof(bp_info[i].attr)); - memset(bp_info[i].symbol_name, 0, sizeof(bp_info[i].symbol_name)); - bp_info[i].mask = 0; - mutex_unlock(&g_hw_manage.lock); - return -1; -} -EXPORT_SYMBOL_GPL(hw_bp_install_from_addr); - -/*从符号设置一个断点*/ -int hw_bp_install_from_symbol(char *name, int len, int type, - hw_bp_callback handler) -{ - int ret = 0; - u64 addr = 0; - - if ((NULL == name) || (HW_BREAKPOINT_INVALID == type)) { - pr_info("HW_breakpointInstallFromSymbol para is error\n"); - return -1; - } - - addr = HW_SYMS_FUNC(kallsyms_lookup_name)(name); - if (0 == addr) { - /*the symbol is invalid*/ - pr_info("Can not find the symbol, name: %s\n", name); - return -1; - } - - ret = hw_bp_install_from_addr(addr, len, type, handler); - if (ret) { - pr_info("HW_breakpointInstallFromSymbol error [%s]\n", name); - return -1; - } - - return 0; -} -EXPORT_SYMBOL_GPL(hw_bp_install_from_symbol); - -void hw_bp_uninstall_from_addr(u64 addr) -{ - int i = 0; - struct hw_bp_manage_info *bp_info = NULL; - - /*traverse bp arrays*/ - /*find bp*/ - mutex_lock(&g_hw_manage.lock); - for (i = 0; i < g_hw_manage.max_bp_num; i++) { - if (g_hw_manage.bp[i].mask & g_hw_manage.cpu_mask) { - if (g_hw_manage.bp[i].attr.addr == addr) { - bp_info = &g_hw_manage.bp[i]; - pr_info("[uninstall] find addr: bp[%d]\n", i); - break; - } - } - } - /*find wp*/ - for (i = 0; (i < g_hw_manage.max_wp_num) && (bp_info == NULL); i++) { - if (g_hw_manage.wp[i].mask & g_hw_manage.cpu_mask) { - if (g_hw_manage.wp[i].attr.addr == addr) { - bp_info = &g_hw_manage.wp[i]; - pr_info("[uninstall] find addr: wp[%d]\n", i); - break; - } - } - } - if (NULL == bp_info) { - pr_info("HW_breakpointUnInstallFromAddr fail,can not find addr:0x%llx\n", - addr); - mutex_unlock(&g_hw_manage.lock); - return; - } - hw_bp_unregister(bp_info->info, bp_info->mask); - /*clear bp info*/ - memset(bp_info->symbol_name, 0, sizeof(bp_info->symbol_name)); - memset(&bp_info->attr, 0, sizeof(bp_info->attr)); - bp_info->mask = 0; - mutex_unlock(&g_hw_manage.lock); -} -EXPORT_SYMBOL_GPL(hw_bp_uninstall_from_addr); - -void hw_bp_uninstall_from_symbol(char *name) -{ - u64 addr = 0; - - if (NULL == name) { - pr_info("HW_breakpointUnInstallFromSymbol para is error\n"); - return; - } - - addr = HW_SYMS_FUNC(kallsyms_lookup_name)(name); - if (0 == addr) { - /*the symbol is invalid*/ - pr_info("[uninstall] Can not find the symbol, name: %s\n", - name); - return; - } - hw_bp_uninstall_from_addr(addr); -} -EXPORT_SYMBOL_GPL(hw_bp_uninstall_from_symbol); - -void hw_free_bp_infos(hw_bp_info_list *info) -{ - hw_bp_info_list *node = NULL, *next = NULL; - - if (info) { - list_for_each_entry_safe(node, next, &info->list, list) { - list_del(&node->list); - if (node->attr) { - kfree(node->attr); - } - kfree(node); - } - if (info->attr) { - kfree(info->attr); - } - kfree(info); - } -} -EXPORT_SYMBOL_GPL(hw_free_bp_infos); - -static void hw_fill_report_data(struct hw_bp_manage_info *bp_info, - hw_bp_info_list *node) -{ - struct hw_bp_info *bp = NULL; - int cpu = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - cpus_read_lock(); -#else - get_online_cpus(); -#endif - for_each_possible_cpu(cpu) { - if (bp_info->mask & 1 << cpu) { - bp = per_cpu(*bp_info->info, cpu); - /*value*/ - node->attr[cpu].type = bp->attr.type; - node->attr[cpu].addr = bp->attr.addr; - node->attr[cpu].len = bp->attr.len; - node->attr[cpu].mask = bp->attr.mask; - node->attr[cpu].times = bp->attr.times; - } - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - cpus_read_unlock(); -#else - put_online_cpus(); -#endif -} - -hw_bp_info_list *hw_get_bp_infos(void) -{ - hw_bp_info_list *head = NULL; - hw_bp_info_list *node = NULL; - struct hw_bp_manage_info *bp_info = NULL; - int i = 0; - - mutex_lock(&g_hw_manage.lock); - for (i = 0; i < g_hw_manage.max_bp_num; i++) { - bp_info = &g_hw_manage.bp[i]; - if (bp_info->mask & g_hw_manage.cpu_mask) { - /*bp is set*/ - if (head == NULL) { - head = kzalloc(sizeof(hw_bp_info_list), - GFP_KERNEL); - if (head == NULL) { - goto err; - } - INIT_LIST_HEAD(&head->list); - head->attr = - kzalloc(sizeof(hw_bp_report) * - g_hw_manage.cpu_num, - GFP_KERNEL); - if (head->attr == NULL) { - goto err; - } - head->cpu_mask = bp_info->mask; - head->cpu_num = g_hw_manage.cpu_num; - hw_fill_report_data(bp_info, head); - } - node = kzalloc(sizeof(hw_bp_info_list), GFP_KERNEL); - if (node == NULL) { - goto err; - } - INIT_LIST_HEAD(&node->list); - list_add_tail(&node->list, &head->list); - node->attr = kzalloc(sizeof(hw_bp_report) * - g_hw_manage.cpu_num, - GFP_KERNEL); - if (node->attr == NULL) { - goto err; - } - node->cpu_mask = bp_info->mask; - node->cpu_num = g_hw_manage.cpu_num; - hw_fill_report_data(bp_info, node); - } - } - - for (i = 0; i < g_hw_manage.max_wp_num; i++) { - bp_info = &g_hw_manage.wp[i]; - if (bp_info->mask & g_hw_manage.cpu_mask) { - /*bp is set*/ - if (head == NULL) { - head = kzalloc(sizeof(hw_bp_info_list), - GFP_KERNEL); - if (head == NULL) { - goto err; - } - INIT_LIST_HEAD(&head->list); - head->attr = - kzalloc(sizeof(hw_bp_report) * - g_hw_manage.cpu_num, - GFP_KERNEL); - if (head->attr == NULL) { - goto err; - } - head->cpu_mask = bp_info->mask; - head->cpu_num = g_hw_manage.cpu_num; - hw_fill_report_data(bp_info, head); - } - node = kzalloc(sizeof(hw_bp_info_list), GFP_KERNEL); - if (node == NULL) { - goto err; - } - INIT_LIST_HEAD(&node->list); - list_add_tail(&node->list, &head->list); - node->attr = kzalloc(sizeof(hw_bp_report) * - g_hw_manage.cpu_num, - GFP_KERNEL); - if (node->attr == NULL) { - goto err; - } - node->cpu_mask = bp_info->mask; - node->cpu_num = g_hw_manage.cpu_num; - hw_fill_report_data(bp_info, node); - } - } - mutex_unlock(&g_hw_manage.lock); - - return head; - -err: - mutex_unlock(&g_hw_manage.lock); - hw_free_bp_infos(head); - return NULL; -} -EXPORT_SYMBOL_GPL(hw_get_bp_infos); - -/*release bp*/ -void hw_bp_manage_deinit(void) -{ - int i = 0; - - hw_bp_uninstall_all(); - - for (i = 0; i < g_hw_manage.max_wp_num; i++) { - free_percpu(g_hw_manage.wp[i].info); - } - - for (i = 0; i < g_hw_manage.max_bp_num; i++) { - free_percpu(g_hw_manage.bp[i].info); - } - mutex_destroy(&g_hw_manage.lock); -} - -/*bp arch init*/ -int hw_bp_manage_init(void) -{ - int cpu = -1, i = 0; - struct hw_bp_info *__percpu *bp = NULL; - - /*get bp&wp num*/ - g_hw_manage.max_bp_num = hw_get_bp_num(TYPE_INST); - g_hw_manage.max_wp_num = hw_get_bp_num(TYPE_DATA); - - /*get CPU num*/ - g_hw_manage.cpu_num = 0; - for_each_online_cpu(cpu) { - g_hw_manage.cpu_mask |= 1 << cpu; - g_hw_manage.cpu_num++; - } - pr_info("CPU MASK = %x\n", g_hw_manage.cpu_mask); - - /*mange mem of bp*/ - for (i = 0; i < g_hw_manage.max_wp_num; i++) { - bp = alloc_percpu(typeof(*bp)); - if (!bp) { - pr_info("wp alloc_percpu fail\n"); - goto free; - } - g_hw_manage.wp[i].info = bp; - bp = NULL; - } - for (i = 0; i < g_hw_manage.max_bp_num; i++) { - bp = alloc_percpu(typeof(*bp)); - if (!bp) { - pr_info("wp alloc_percpu fail\n"); - goto free; - } - g_hw_manage.bp[i].info = bp; - bp = NULL; - } - - mutex_init(&g_hw_manage.lock); - - return 0; - -free: - hw_bp_manage_deinit(); - return -1; -} diff --git a/code/hw_breakpoint_proc.c b/code/hw_breakpoint_proc.c deleted file mode 100644 index 05fc6bf9..00000000 --- a/code/hw_breakpoint_proc.c +++ /dev/null @@ -1,372 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "linux/printk.h" -#include -#include "ext_hw_breakpoint.h" -#include "hw_breakpoint_until.h" - -#define PROC_FILE_DEBUG "breakpoint" - -/*func extern*/ -extern void hw_bp_show_all(void); - -/*proc_file handle*/ -static struct proc_dir_entry *proc_file = NULL; - -/*help*/ -char *hw_proc_write_usag = { - "Usage:\n" - "\thw_break support cmd type: \n" - "\t\t1: echo add / > /proc/breakpoint, add a breakpoint\n" - "\t\t\t[type]:\n" - "\t\t\t\t[wp1]: HW_BREAKPOINT_R\n" - "\t\t\t\t[wp2]: HW_BREAKPOINT_W\n" - "\t\t\t\t[wp3]: HW_BREAKPOINT_R|HW_BREAKPOINT_W\n" - "\t\t\t\t[bp]: HW_BREAKPOINT_X\n" - "\t\t\t[len]:[0,8] (2^3,2^31]\n" - "\t\t2: echo del > /proc/breakpoint, del a breakpoint\n" - "\t\t3: echo get ptr/val > /proc/breakpoint, search &symbol/*(&symbol)\n" - "\t\t4: echo iophy > /proc/breakpoint, search all of ioaddr map virt\n" -}; -/*example*/ -char *hw_proc_write_example = { - "Example:\n" - "\tThe first step:\n" - "\t\techo add wp3 4 hw_test_value0 > /proc/breakpoint, add a watchpoint at " - "&hw_test_value0\n" - "\tThe second step:\n" - "\t\techo write 0 0 > /proc/breakpoint, write hw_test_value0\n" - "\tThe third step:\n" - "\t\techo read 0 0 > /proc/breakpoint, read hw_test_value0\n" - "\tThe forth step:\n" - "\t\techo del hw_test_value0 > /proc/breakpoint, del wawtchpoint at " - "&hw_test_value0\n" -}; - -/*seq show*/ -static int hw_proc_show(struct seq_file *m, void *v) -{ - hw_bp_info_list *info = NULL, *node = NULL; - int i = 0, index = 0; - - /*get info*/ - info = hw_get_bp_infos(); - if (info) { - list_for_each_entry(node, &info->list, list) { - for (i = 0; i < node->cpu_num; i++) { - if (node->cpu_mask & (1 << i)) { - break; - } - } - seq_printf(m, "----------------[%d]----------------\n", - index++); - seq_printf(m, "type: \t0x%x\n", node->attr[i].type); - seq_printf(m, "addr: \t0x%llx\n", node->attr[i].addr); - seq_printf(m, "len: \t0x%llx\n", node->attr[i].len); - seq_printf(m, "mask: \t0x%x\n", node->attr[i].mask); - for (i = 0; i < node->cpu_num; i++) { - if (!(node->cpu_mask & (1 << i))) { - continue; - } - seq_printf(m, "cpu[%d] trigger times:\n", i); - seq_printf( - m, - "\tread: %llu, write: %llu, exec: %llu\n", - node->attr[i].times.read, - node->attr[i].times.write, - node->attr[i].times.exec); - } - } - hw_free_bp_infos(info); - } - return 0; -} - -static int hw_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, hw_proc_show, inode->i_private); -} - -u32 hw_test_value3[32] = { 0 }; -u32 hw_test_value2[32] = { 0 }; -u32 hw_test_value1[32] = { 0 }; -u32 hw_test_value0[32] = { 0 }; - -/*show vm info*/ -static void hw_show_vm(struct vm_struct *area, u64 phy_addr) -{ - pr_info("--------------------------------------------------\n"); - if (area->phys_addr) { - pr_info("\tphy addr:\t0x%llx\n", area->phys_addr); - } - if (area->addr) { - pr_info("\tvirt addr:\t0x%llx\n", (u64)area->addr); - } - if (area->size) { - pr_info("\tsize:\t\t0x%lx\n", area->size); - } - if (area->addr && area->phys_addr) { - pr_info("0x%llx to virt: 0x%llx\n", phy_addr, - (u64)area->addr + phy_addr - area->phys_addr); - } - pr_info("\n"); -} - -/*proc get virt of iophys*/ -static void hw_iophy_to_virt(char *addr_buf) -{ - u64 io_addr = 0; - iophys_info *iophys = NULL, *node = NULL; - - io_addr = simple_strtol(addr_buf, NULL, 0); - iophys = get_iophys_info(io_addr); - - if (iophys) { - list_for_each_entry(node, &iophys->list, list) { - hw_show_vm(&node->area, io_addr); - } - } - free_iophys_info(iophys); -} - -/*proc get handler*/ -static int hw_proc_get(char *type_buf, char *name_buf) -{ - u64 addr = 0; - - /*get symbol addr*/ - addr = HW_SYMS_FUNC(kallsyms_lookup_name)(name_buf); - if (!addr || addr < TASK_SIZE) { - pr_info("can not find symbol %s\n", name_buf); - return -1; - } - if (strcmp("ptr", type_buf) == 0) { - pr_info("&%s = 0x%llx\n", name_buf, addr); - } else if (strcmp("val", type_buf) == 0) { - pr_info("*(%s) = 0x%llx\n", name_buf, *((u64 *)addr)); - } else { - return -1; - } - return 0; -} - -/*proc del bp*/ -static void hw_proc_del(char *name_buf) -{ - u64 uninstall_addr = 0; - - if (name_buf[0] == '0' && name_buf[1] == 'x') { - uninstall_addr = simple_strtol(name_buf, 0, 0); - } - if (uninstall_addr) { - pr_info("will uninstall at 0x%llx\n", uninstall_addr); - hw_bp_uninstall_from_addr(uninstall_addr); - } else { - pr_info("will uninstall at &%s\n", name_buf); - hw_bp_uninstall_from_symbol(name_buf); - } -} - -/*proc add bp*/ -static int hw_proc_add(char *type_buf, char *len_buf, char *name_buf) -{ - char *name = NULL; - int len = HW_BREAKPOINT_LEN_4, type = 0; - u64 install_addr = 0; - - /*check bp type*/ - switch (strlen(type_buf)) { - /*The length is 2 for the bp*/ - case 2: { - type = HW_BREAKPOINT_X; - name = name_buf; - break; - } - /*The length is 3 for the wp, and the third character is the breakpoint type*/ - case 3: { - type = type_buf[2] - '0'; - len = (int)simple_strtoul(len_buf, NULL, 0); - name = name_buf; - break; - } - default: { - return -1; - } - } - /*check type if valid*/ - if (type < 1 || type > 4) { - return -1; - } - - if (name_buf[0] == '0' && name_buf[1] == 'x') { - install_addr = simple_strtol(name_buf, 0, 0); - } - if (install_addr) { - pr_info("will install at 0x%llx\n", install_addr); - hw_bp_install_from_addr(install_addr, len, type, NULL); - } else { - pr_info("will install at &%s\n", name); - hw_bp_install_from_symbol(name, len, type, NULL); - } - return 0; -} - -/*test write*/ -static void hw_proc_rw_test(char *cmd, char *index_of_buf, char *index_in_buf) -{ - int index = (int)simple_strtol(index_of_buf, NULL, 0); - int index1 = (int)simple_strtol(index_in_buf, NULL, 0); - u32 *tmpbuf; - switch (index) { - case 0: { - tmpbuf = hw_test_value0; - break; - } - case 1: { - tmpbuf = hw_test_value1; - break; - } - case 2: { - tmpbuf = hw_test_value2; - break; - } - case 3: - default: { - tmpbuf = hw_test_value3; - break; - } - } - if (strcmp("write", cmd) == 0) { - pr_info("will write hw_test_value%d[%d], addr = %llx\n", index, - index1, (u64)&tmpbuf[index1]); - tmpbuf[index1] = get_random_u32(); - } else if (strcmp("read", cmd) == 0) { - pr_info("will read hw_test_value%d[%d], addr = %llx\n", index, - index1, (u64)&tmpbuf[index1]); - pr_info("hw_test_value%d[%d] = %d\n", index, index1, - tmpbuf[index1]); - } -} - -static ssize_t hw_proc_write(struct file *file, const char __user *p_buf, - size_t count, loff_t *pPos) -{ - size_t ret; - char cmd_buf[128] = { 0 }; - int argc = 0; - char *argv[10] = { NULL }; - - // pr_info("hw_proc_write\n"); - - if ((count > sizeof(cmd_buf)) || (count == 0)) { - pr_info("test proc write, count is error!\n"); - return (ssize_t)count; - } - - memset(cmd_buf, 0, sizeof(cmd_buf)); - ret = copy_from_user(cmd_buf, p_buf, count); - if (0 != ret) { - pr_info("fail to copy data from user!\n"); - return (ssize_t)count; - } - - cmd_buf[count - 1] = '\0'; - memset(argv, 0, sizeof(argv)); - process_cmd_string(cmd_buf, &argc, argv); - - if (strcmp("write", argv[0]) == 0 || strcmp("read", argv[0]) == 0) { - if (argc != 3) { - goto cmdErr; - } - hw_proc_rw_test(argv[0], argv[1], argv[2]); - return (ssize_t)count; - } else if (strcmp("show", argv[0]) == 0) { - hw_bp_show_all(); - return (ssize_t)count; - } else if (strcmp("help", argv[0]) == 0) { - pr_info("%s", hw_proc_write_usag); - pr_info("%s", hw_proc_write_example); - return (ssize_t)count; - } - - if (strcmp("add", argv[0]) == 0) { - if (argc != 4) { - // pr_info("argc = %d\n",argc); - goto cmdErr; - } - if (hw_proc_add(argv[1], argv[2], argv[3])) { - goto cmdErr; - } - } else if (strcmp("del", argv[0]) == 0) { - if (argc != 2) { - // pr_info("argc = %d\n",argc); - goto cmdErr; - } - hw_proc_del(argv[1]); - } else if (strcmp("get", argv[0]) == 0) { - if (argc != 3) { - // pr_info("argc = %d\n",argc); - goto cmdErr; - } - if (hw_proc_get(argv[1], argv[2])) { - goto cmdErr; - } - } else if (strcmp("iophy", argv[0]) == 0) { - if (argc != 2) { - // pr_info("argc = %d\n",argc); - goto cmdErr; - } - hw_iophy_to_virt(argv[1]); - } else { - goto cmdErr; - } - - return (ssize_t)count; -cmdErr: - pr_info("cmd error, echo help > /proc/breakpoint\n"); - return (ssize_t)count; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 1, 10) -static const struct proc_ops hw_proc_fops = { - .proc_open = hw_proc_open, - .proc_write = hw_proc_write, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release, -}; -#else -static const struct file_operations hw_proc_fops = { - .proc_open = hw_proc_open, - .proc_write = hw_proc_write, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release, -}; -#endif - -int hw_proc_init(void) -{ - proc_file = proc_create(PROC_FILE_DEBUG, S_IRUGO | S_IWUGO, NULL, - &hw_proc_fops); - if (NULL == proc_file) { - pr_info("hw proc init, Create %s proc file failed!\n", - PROC_FILE_DEBUG); - return -ENOMEM; - } - // pr_info(hw_proc_write_usag); - // pr_info(hw_proc_write_example); - return 0; -} - -void hw_proc_exit(void) -{ - if (NULL != proc_file) { - remove_proc_entry(PROC_FILE_DEBUG, NULL); - } -} diff --git a/code/hw_breakpoint_smp.c b/code/hw_breakpoint_smp.c deleted file mode 100644 index f75e4cf0..00000000 --- a/code/hw_breakpoint_smp.c +++ /dev/null @@ -1,193 +0,0 @@ -#include -#include -#include -#include -#include "ext_hw_breakpoint.h" - -typedef int (*hw_remote_func_f)(void *); - -/*func extern*/ -extern int hw_bp_arch_parse(struct hw_bp_info *bp, const hw_bp_attr *attr, - hw_bp_vc *hw); -extern int hw_bp_install(struct hw_bp_info *bp); -extern int hw_bp_uninstall(struct hw_bp_info *bp); -extern int hw_arch_check_bp_in_kspace(hw_bp_vc *hw); - -struct hw_remote_func_call { - struct hw_bp_info *p; - hw_remote_func_f func; - void *info; - int ret; -}; - -static void hw_remote_func(void *data) -{ - struct hw_remote_func_call *tfc = data; - - /*callback*/ - tfc->ret = tfc->func(tfc->info); -} - -static int hw_cpu_func_call(int cpu, hw_remote_func_f func, void *info) -{ - struct hw_remote_func_call data = { - .p = NULL, - .func = func, - .info = info, - .ret = -ENXIO, /* No such CPU */ - }; - - preempt_disable(); - if (cpu != smp_processor_id()) { - smp_call_function_single(cpu, hw_remote_func, &data, 1); - goto out; - } - - data.ret = func(info); - -out: - preempt_enable(); - return data.ret; -} - -static int hw_bp_parse(struct hw_bp_info *bp, const hw_bp_attr *attr, - hw_bp_vc *hw) -{ - int err; - - err = hw_bp_arch_parse(bp, attr, hw); - if (err) - return err; - - if (hw_arch_check_bp_in_kspace(hw)) { - /*Don't let unprivileged users set a breakpoint in the trappath to avoid trap recursion attacks.*/ - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - } - - return 0; -} - -static int hw_bp_info_del(void *p) -{ - struct hw_bp_info *bp = (struct hw_bp_info *)p; - return hw_bp_uninstall(bp); -} - -static int hw_bp_info_add(void *p) -{ - struct hw_bp_info *bp = (struct hw_bp_info *)p; - return hw_bp_install(bp); -} - -static int hw_bp_info_init(struct hw_bp_info *bp) -{ - int err; - hw_bp_vc hw = {}; - - /*parse*/ - err = hw_bp_parse(bp, &bp->attr, &hw); - if (err) - return err; - - bp->info = hw; - - return 0; -} - -static struct hw_bp_info *hw_bp_info_alloc(const hw_bp_attr *attr, int cpu) -{ - struct hw_bp_info *bp = NULL; - int err; - - bp = kzalloc(sizeof(*bp), GFP_KERNEL); - if (!bp) { - pr_info("bp alloc fail\n"); - return ERR_PTR(-ENOMEM); - } - - bp->cpu = cpu; - bp->attr = *attr; - - /*bp info init*/ - err = hw_bp_info_init(bp); - if (err) { - pr_info("hw_bp_info_init fail\n"); - return ERR_PTR(err); - } - /*smp_call_function_single in kgdb is error?*/ - err = hw_cpu_func_call(cpu, hw_bp_info_add, bp); - if (err) { - pr_info("hw_bp_info_add fail\n"); - return ERR_PTR(err); - } - - return bp; -} - -static void hw_bp_info_free(struct hw_bp_info *bp, int cpu) -{ - hw_cpu_func_call(cpu, hw_bp_info_del, bp); - kfree(bp); -} - -void hw_bp_unregister(struct hw_bp_info *__percpu *bp, int state) -{ - int cpu; - - if (bp == NULL) { - return; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - cpus_read_lock(); -#else - get_online_cpus(); -#endif - for_each_possible_cpu(cpu) { - if (state & 1 << cpu) { - hw_bp_info_free(per_cpu(*bp, cpu), cpu); - } - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - cpus_read_unlock(); -#else - put_online_cpus(); -#endif -} - -int hw_bp_register(struct hw_bp_info *__percpu *cpu_events, hw_bp_attr *attr, - int *state) -{ - struct hw_bp_info *bp; - int cpu; - - if (cpu_events == NULL || attr == NULL || state == NULL) { - pr_info("hw_bp_register para is NULL\n"); - return -1; - } - - *state = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - cpus_read_lock(); -#else - get_online_cpus(); -#endif - for_each_online_cpu(cpu) { - bp = hw_bp_info_alloc(attr, cpu); - if (IS_ERR(bp)) { - pr_info("hw_bp_info_alloc error at CPU[%d]\n", cpu); - } - /*cpu success mask*/ - *state |= 1 << cpu; - /*percpu bp*/ - per_cpu(*cpu_events, cpu) = bp; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) - cpus_read_unlock(); -#else - put_online_cpus(); -#endif - - return 0; -} diff --git a/code/hw_breakpoint_until.c b/code/hw_breakpoint_until.c deleted file mode 100644 index d57bec65..00000000 --- a/code/hw_breakpoint_until.c +++ /dev/null @@ -1,139 +0,0 @@ -#include -#include "ext_hw_breakpoint.h" -#include "hw_breakpoint_until.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 72) -#define VM_LAZY_FREE 0x02 -#define VM_VM_AREA 0x04 -#endif - -#ifdef HW_PROC_CMD_DEBUG -static void print_cmd_params(int argc, char *argv[]) -{ - int loop = 0; - - for (loop = 0; loop < argc; loop++) { - pr_info("loop:%d, %s\n", loop, argv[loop]); - } -} -#endif - -void process_cmd_string(char *p_buf, int *p_argc, char *p_argv[]) -{ - int i_argc; - char *p_tmp = p_buf; - - p_argv[0] = p_buf; - i_argc = 1; - - while (*p_tmp) { - if (' ' == *p_tmp) { - *p_tmp = '\0'; - p_argv[i_argc++] = p_tmp + 1; - } - - p_tmp++; - } - *p_argc = i_argc; -#ifdef HW_PROC_CMD_DEBUG - print_cmd_params(*pArgc, pArgv); -#endif -} - -void free_iophys_info(iophys_info *info) -{ - iophys_info *node = NULL, *next = NULL; - - if (info) { - list_for_each_entry_safe (node, next, &info->list, list) { - list_del(&node->list); - kfree(node); - } - kfree(info); - } -} -EXPORT_SYMBOL_GPL(free_iophys_info); - -iophys_info *get_iophys_info(u64 addr) -{ - struct vmap_area *va = NULL; - struct vm_struct *area = NULL; - struct vm_struct *next = NULL; - iophys_info *head = NULL; - iophys_info *node = NULL; - - if (!HW_SYMS_VAL(vmap_area_lock) || !HW_SYMS_VAL(vmap_area_lock)) { - pr_info("vmap_area_list or vmap_area_lock is NULL, can not get virt"); - return head; - } - - spin_lock(HW_SYMS_VAL(vmap_area_lock)); - list_for_each_entry (va, HW_SYMS_VAL(vmap_area_list), list) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 72) - if (!(va->flags & VM_VM_AREA)) { - continue; - } -#endif - if (!va) { - continue; - } - area = va->vm; - if (!area) { - continue; - } - if (!(area->flags & VM_IOREMAP) || - area->flags & VM_UNINITIALIZED) { - continue; - } - smp_rmb(); - /*If you find the I/O address, check whether the I/O address you want to query is within the I/O address range*/ - next = area; - while (next) { - if (next->phys_addr && next->size) { - /*The IO address to be queried is within its range*/ - if (addr >= next->phys_addr && - addr < next->phys_addr + next->size) { - /*find it*/ - if (head == NULL) { - head = kzalloc( - sizeof(iophys_info), - GFP_KERNEL); - if (head == NULL) { - goto err; - } - INIT_LIST_HEAD(&head->list); - head->area = *next; - head->virt_addr = - (u64)next->addr + addr - - next->phys_addr; - } - node = kzalloc(sizeof(iophys_info), - GFP_KERNEL); - if (node == NULL) { - goto free; - } - INIT_LIST_HEAD(&node->list); - node->area = *next; - node->virt_addr = (u64)next->addr + - addr - - next->phys_addr; - list_add_tail(&node->list, &head->list); - } - } - next = next->next; - if (next == area) { - break; - } - } - } - spin_unlock(HW_SYMS_VAL(vmap_area_lock)); - - return head; - -free: - free_iophys_info(head); -err: - spin_unlock(HW_SYMS_VAL(vmap_area_lock)); - return NULL; -} -EXPORT_SYMBOL_GPL(get_iophys_info); diff --git a/code/hw_breakpoint_until.h b/code/hw_breakpoint_until.h deleted file mode 100644 index 3f054ffa..00000000 --- a/code/hw_breakpoint_until.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __HW_BREAKPOINT_UNTIL_H -#define __HW_BREAKPOINT_UNTIL_H - -#include - -typedef struct iophys_info { - struct list_head list; - struct vm_struct area; - u64 virt_addr; -} iophys_info; - -void process_cmd_string(char *pBuf, int *pArgc, char *pArgv[]); -/*iophy to virt func*/ -iophys_info *get_iophys_info(u64 addr); -void free_iophys_info(iophys_info *info); - -#endif From a842e04fd3a3e587bcf7c5331c31f8f648739782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Fri, 30 Jan 2026 11:14:12 +0800 Subject: [PATCH 23/35] Create Makefile --- code/Makefile | 1 + 1 file changed, 1 insertion(+) create mode 100644 code/Makefile diff --git a/code/Makefile b/code/Makefile new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/code/Makefile @@ -0,0 +1 @@ + From a0f366968c04303663a9188cdc1fd773859f3502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Fri, 30 Jan 2026 11:14:42 +0800 Subject: [PATCH 24/35] Add files via upload --- code/Makefile | 2 +- code/aurora.c | 473 ++++++++++++++++++++++++++++++++++++++++++++++++++ code/aurora.h | 31 ++++ 3 files changed, 505 insertions(+), 1 deletion(-) create mode 100644 code/aurora.c create mode 100644 code/aurora.h diff --git a/code/Makefile b/code/Makefile index 8b137891..f5d1305e 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1 +1 @@ - +obj-m += aurora.o diff --git a/code/aurora.c b/code/aurora.c new file mode 100644 index 00000000..b99ba502 --- /dev/null +++ b/code/aurora.c @@ -0,0 +1,473 @@ +#include "aurora.h" +#include + +typedef struct _COPY_MEMORY { + pid_t pid; + uintptr_t addr; + void __user *buffer; + size_t size; +} COPY_MEMORY, *PCOPY_MEMORY; + +typedef struct _MODULE_BASE { + pid_t pid; + char __user *name; + uintptr_t base; +} MODULE_BASE, *PMODULE_BASE; + +enum OPERATIONS { + OP_INIT_KEY = 0x800, + OP_READ_MEM = 0x801, + OP_WRITE_MEM = 0x802, + OP_MODULE_BASE = 0x803, +}; + +// 可选的设备名池 +static const char* device_name_pool[] = { + "SynapseKernel", + "AetherBridge", + "NexusGuard", + "QuantumLink", + "VortexCore", + "PhantomNode", + "TitanShield", + "OrionDriver", + "ZenithPath", + "CelestialGate", + "NebulaCore", + "StellarLink", + "InfinityHook", + "EchoSys", + "ChronoFrame", + "PulseEngine", + "ApexBridge", + "NovaNode", + "SolarFlare", + "CosmicPath" +}; + +#define DEVICE_POOL_SIZE (sizeof(device_name_pool) / sizeof(device_name_pool[0])) +static char selected_device_name[64]; // 存储实际使用的设备名 +static struct miscdevice misc_dev; + +static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va); +static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size); +static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size); +static bool read_process_memory(pid_t pid, uintptr_t addr, void __user *buffer, size_t size); +static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user *buffer, size_t size); +static uintptr_t get_module_base(pid_t pid, const char *name); + +// 从池中随机选择一个设备名 +static void select_random_device_name(void) +{ + unsigned int rand_val; + int index; + + get_random_bytes(&rand_val, sizeof(rand_val)); + index = rand_val % DEVICE_POOL_SIZE; + + snprintf(selected_device_name, sizeof(selected_device_name), + "%s", device_name_pool[index]); + + printk(KERN_INFO "Aurora: Selected random device name: %s\n", selected_device_name); +} + +// 生成完全随机的设备名(更隐蔽) +static void generate_random_device_name(void) +{ + char random_part[12]; + int i; + + // 生成8个随机字符 + get_random_bytes(random_part, 8); + + // 转换为可打印字符(小写字母和数字) + for (i = 0; i < 8; i++) { + unsigned char c = random_part[i] % 36; + if (c < 26) + random_part[i] = 'a' + c; + else + random_part[i] = '0' + (c - 26); + } + random_part[8] = '\0'; + + // 添加前缀使其看起来像正常设备 + const char* prefixes[] = {"dev_", "sys_", "hid_", "tty", "rfcomm", "usb", "video"}; + unsigned int prefix_rand; + get_random_bytes(&prefix_rand, sizeof(prefix_rand)); + int prefix_index = prefix_rand % (sizeof(prefixes) / sizeof(prefixes[0])); + + snprintf(selected_device_name, sizeof(selected_device_name), + "%s%s", prefixes[prefix_index], random_part); + + printk(KERN_INFO "Aurora: Generated random device name: %s\n", selected_device_name); +} + +static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + pud_t *pud; + phys_addr_t page_addr; + uintptr_t page_offset; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 61) + p4d_t *p4d; + + pgd = pgd_offset(mm, va); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return 0; + + p4d = p4d_offset(pgd, va); + if (p4d_none(*p4d) || p4d_bad(*p4d)) + return 0; + + pud = pud_offset(p4d, va); +#else + pgd = pgd_offset(mm, va); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return 0; + + pud = pud_offset(pgd, va); +#endif + + if (pud_none(*pud) || pud_bad(*pud)) + return 0; + + pmd = pmd_offset(pud, va); + if (pmd_none(*pmd)) + return 0; + + pte = pte_offset_kernel(pmd, va); + if (pte_none(*pte) || !pte_present(*pte)) + return 0; + + page_addr = (phys_addr_t)(pte_pfn(*pte) << PAGE_SHIFT); + page_offset = va & (PAGE_SIZE - 1); + + return page_addr + page_offset; +} + +static inline bool is_valid_phys_addr_range(phys_addr_t addr, size_t size) +{ + return (addr + size <= virt_to_phys(high_memory)); +} + +static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size) +{ + void *mapped; + + if (!pfn_valid(__phys_to_pfn(pa))) + return false; + + if (!is_valid_phys_addr_range(pa, size)) + return false; + + mapped = ioremap_cache(pa, size); + if (!mapped) + return false; + + if (copy_to_user(buffer, mapped, size)) { + iounmap(mapped); + return false; + } + + iounmap(mapped); + return true; +} + +static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size) +{ + void *mapped; + + if (!pfn_valid(__phys_to_pfn(pa))) + return false; + + if (!is_valid_phys_addr_range(pa, size)) + return false; + + mapped = ioremap_cache(pa, size); + if (!mapped) + return false; + + if (copy_from_user(mapped, buffer, size)) { + iounmap(mapped); + return false; + } + + iounmap(mapped); + return true; +} + +static bool read_process_memory(pid_t pid, uintptr_t addr, + void __user *buffer, size_t size) +{ + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + phys_addr_t pa; + bool result = false; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return false; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return false; + } + + mm = get_task_mm(task); + put_pid(pid_struct); + + if (!mm) { + put_task_struct(task); + return false; + } + + pa = translate_linear_address(mm, addr); + if (pa) { + result = read_physical_address(pa, buffer, size); + } else { + struct vm_area_struct *vma = find_vma(mm, addr); + if (vma) { + if (clear_user(buffer, size) == 0) { + result = true; + } + } + } + + mmput(mm); + put_task_struct(task); + return result; +} + +static bool write_process_memory(pid_t pid, uintptr_t addr, + const void __user *buffer, size_t size) +{ + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + phys_addr_t pa; + bool result = false; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return false; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return false; + } + + mm = get_task_mm(task); + put_pid(pid_struct); + + if (!mm) { + put_task_struct(task); + return false; + } + + pa = translate_linear_address(mm, addr); + if (pa) { + result = write_physical_address(pa, buffer, size); + } + + mmput(mm); + put_task_struct(task); + return result; +} + +#define ARC_PATH_MAX 256 + +static uintptr_t get_module_base(pid_t pid, const char *name) +{ + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + struct pid *pid_struct = NULL; + struct vm_area_struct *vma = NULL; + uintptr_t base_addr = 0; + int path_len; + + pid_struct = find_get_pid(pid); + if (!pid_struct) + return 0; + + task = get_pid_task(pid_struct, PIDTYPE_PID); + if (!task) { + put_pid(pid_struct); + return 0; + } + + mm = get_task_mm(task); + put_pid(pid_struct); + + if (!mm) { + put_task_struct(task); + return 0; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) + struct vma_iterator vmi; + vma_iter_init(&vmi, mm, 0); + for_each_vma(vmi, vma) { +#else + for (vma = mm->mmap; vma; vma = vma->vm_next) { +#endif + char buf[ARC_PATH_MAX]; + char *path_nm; + + if (!vma->vm_file) + continue; + + path_nm = file_path(vma->vm_file, buf, ARC_PATH_MAX - 1); + if (IS_ERR(path_nm)) + continue; + + path_len = strlen(path_nm); + if (path_len <= 0) + continue; + + if (strstr(path_nm, name) != NULL) { + base_addr = vma->vm_start; + break; + } + } + + mmput(mm); + put_task_struct(task); + return base_addr; +} + +static int dispatch_open(struct inode *node, struct file *file) +{ + return 0; +} + +static int dispatch_close(struct inode *node, struct file *file) +{ + return 0; +} + +static long dispatch_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + static char key[256] = {0}; + static bool is_verified = false; + + switch (cmd) { + case OP_INIT_KEY: + if (!is_verified) { + if (copy_from_user(key, (void __user *)arg, sizeof(key) - 1) == 0) { + key[sizeof(key) - 1] = '\0'; + is_verified = true; + } else { + return -EFAULT; + } + } + break; + + case OP_READ_MEM: { + COPY_MEMORY cm; + + if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) + return -EFAULT; + + if (!read_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) + return -EIO; + + break; + } + + case OP_WRITE_MEM: { + COPY_MEMORY cm; + + if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) + return -EFAULT; + + if (!write_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) + return -EIO; + + break; + } + + case OP_MODULE_BASE: { + MODULE_BASE mb; + char module_name[256]; + + if (copy_from_user(&mb, (void __user *)arg, sizeof(mb))) + return -EFAULT; + + if (!mb.name) + return -EFAULT; + + if (copy_from_user(module_name, mb.name, sizeof(module_name) - 1)) + return -EFAULT; + module_name[sizeof(module_name) - 1] = '\0'; + + mb.base = get_module_base(mb.pid, module_name); + + if (copy_to_user((void __user *)arg, &mb, sizeof(mb))) + return -EFAULT; + + break; + } + + default: + return -ENOTTY; + } + + return 0; +} + +static const struct file_operations dispatch_fops = { + .owner = THIS_MODULE, + .open = dispatch_open, + .release = dispatch_close, + .unlocked_ioctl = dispatch_ioctl, + .compat_ioctl = dispatch_ioctl, +}; + +static int __init driver_entry(void) +{ + int ret; + + // 选择随机设备名(两种方式选其一) + // 方式1:从预选池中随机选择 + select_random_device_name(); + + // 方式2:生成完全随机的设备名(更隐蔽) + // generate_random_device_name(); + + // 注册设备 + misc_dev.minor = MISC_DYNAMIC_MINOR; + misc_dev.name = selected_device_name; + misc_dev.fops = &dispatch_fops; + misc_dev.mode = 0666; + + ret = misc_register(&misc_dev); + if (ret) { + printk(KERN_ERR "Aurora: Failed to register device %s, error %d\n", + selected_device_name, ret); + return ret; + } + + printk(KERN_INFO "Aurora: Successfully registered random device: %s\n", + selected_device_name); + return 0; +} + +static void __exit driver_unload(void) +{ + misc_deregister(&misc_dev); + printk(KERN_INFO "Aurora: Unregistered device: %s\n", selected_device_name); +} + +module_init(driver_entry); +module_exit(driver_unload); + +MODULE_DESCRIPTION("Linux Kernel Module"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("YihanChan"); +MODULE_VERSION("1.0"); diff --git a/code/aurora.h b/code/aurora.h new file mode 100644 index 00000000..6e09ba9b --- /dev/null +++ b/code/aurora.h @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) +#include +#include +#else +#include +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) +#include +#include +#endif From a5bf3237f89296cee544e23741b2f59cd9eb292b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Fri, 30 Jan 2026 11:19:10 +0800 Subject: [PATCH 25/35] Update aurora.c --- code/aurora.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/aurora.c b/code/aurora.c index b99ba502..b951e951 100644 --- a/code/aurora.c +++ b/code/aurora.c @@ -71,6 +71,7 @@ static void select_random_device_name(void) printk(KERN_INFO "Aurora: Selected random device name: %s\n", selected_device_name); } +/* // 生成完全随机的设备名(更隐蔽) static void generate_random_device_name(void) { @@ -101,6 +102,7 @@ static void generate_random_device_name(void) printk(KERN_INFO "Aurora: Generated random device name: %s\n", selected_device_name); } +*/ static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va) { From 546f17e2b8cd1e364045508c5293676969342af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Fri, 30 Jan 2026 23:22:29 +0800 Subject: [PATCH 26/35] Delete code/aurora.c --- code/aurora.c | 475 -------------------------------------------------- 1 file changed, 475 deletions(-) delete mode 100644 code/aurora.c diff --git a/code/aurora.c b/code/aurora.c deleted file mode 100644 index b951e951..00000000 --- a/code/aurora.c +++ /dev/null @@ -1,475 +0,0 @@ -#include "aurora.h" -#include - -typedef struct _COPY_MEMORY { - pid_t pid; - uintptr_t addr; - void __user *buffer; - size_t size; -} COPY_MEMORY, *PCOPY_MEMORY; - -typedef struct _MODULE_BASE { - pid_t pid; - char __user *name; - uintptr_t base; -} MODULE_BASE, *PMODULE_BASE; - -enum OPERATIONS { - OP_INIT_KEY = 0x800, - OP_READ_MEM = 0x801, - OP_WRITE_MEM = 0x802, - OP_MODULE_BASE = 0x803, -}; - -// 可选的设备名池 -static const char* device_name_pool[] = { - "SynapseKernel", - "AetherBridge", - "NexusGuard", - "QuantumLink", - "VortexCore", - "PhantomNode", - "TitanShield", - "OrionDriver", - "ZenithPath", - "CelestialGate", - "NebulaCore", - "StellarLink", - "InfinityHook", - "EchoSys", - "ChronoFrame", - "PulseEngine", - "ApexBridge", - "NovaNode", - "SolarFlare", - "CosmicPath" -}; - -#define DEVICE_POOL_SIZE (sizeof(device_name_pool) / sizeof(device_name_pool[0])) -static char selected_device_name[64]; // 存储实际使用的设备名 -static struct miscdevice misc_dev; - -static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va); -static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size); -static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size); -static bool read_process_memory(pid_t pid, uintptr_t addr, void __user *buffer, size_t size); -static bool write_process_memory(pid_t pid, uintptr_t addr, const void __user *buffer, size_t size); -static uintptr_t get_module_base(pid_t pid, const char *name); - -// 从池中随机选择一个设备名 -static void select_random_device_name(void) -{ - unsigned int rand_val; - int index; - - get_random_bytes(&rand_val, sizeof(rand_val)); - index = rand_val % DEVICE_POOL_SIZE; - - snprintf(selected_device_name, sizeof(selected_device_name), - "%s", device_name_pool[index]); - - printk(KERN_INFO "Aurora: Selected random device name: %s\n", selected_device_name); -} - -/* -// 生成完全随机的设备名(更隐蔽) -static void generate_random_device_name(void) -{ - char random_part[12]; - int i; - - // 生成8个随机字符 - get_random_bytes(random_part, 8); - - // 转换为可打印字符(小写字母和数字) - for (i = 0; i < 8; i++) { - unsigned char c = random_part[i] % 36; - if (c < 26) - random_part[i] = 'a' + c; - else - random_part[i] = '0' + (c - 26); - } - random_part[8] = '\0'; - - // 添加前缀使其看起来像正常设备 - const char* prefixes[] = {"dev_", "sys_", "hid_", "tty", "rfcomm", "usb", "video"}; - unsigned int prefix_rand; - get_random_bytes(&prefix_rand, sizeof(prefix_rand)); - int prefix_index = prefix_rand % (sizeof(prefixes) / sizeof(prefixes[0])); - - snprintf(selected_device_name, sizeof(selected_device_name), - "%s%s", prefixes[prefix_index], random_part); - - printk(KERN_INFO "Aurora: Generated random device name: %s\n", selected_device_name); -} -*/ - -static phys_addr_t translate_linear_address(struct mm_struct *mm, uintptr_t va) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - pud_t *pud; - phys_addr_t page_addr; - uintptr_t page_offset; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 61) - p4d_t *p4d; - - pgd = pgd_offset(mm, va); - if (pgd_none(*pgd) || pgd_bad(*pgd)) - return 0; - - p4d = p4d_offset(pgd, va); - if (p4d_none(*p4d) || p4d_bad(*p4d)) - return 0; - - pud = pud_offset(p4d, va); -#else - pgd = pgd_offset(mm, va); - if (pgd_none(*pgd) || pgd_bad(*pgd)) - return 0; - - pud = pud_offset(pgd, va); -#endif - - if (pud_none(*pud) || pud_bad(*pud)) - return 0; - - pmd = pmd_offset(pud, va); - if (pmd_none(*pmd)) - return 0; - - pte = pte_offset_kernel(pmd, va); - if (pte_none(*pte) || !pte_present(*pte)) - return 0; - - page_addr = (phys_addr_t)(pte_pfn(*pte) << PAGE_SHIFT); - page_offset = va & (PAGE_SIZE - 1); - - return page_addr + page_offset; -} - -static inline bool is_valid_phys_addr_range(phys_addr_t addr, size_t size) -{ - return (addr + size <= virt_to_phys(high_memory)); -} - -static bool read_physical_address(phys_addr_t pa, void __user *buffer, size_t size) -{ - void *mapped; - - if (!pfn_valid(__phys_to_pfn(pa))) - return false; - - if (!is_valid_phys_addr_range(pa, size)) - return false; - - mapped = ioremap_cache(pa, size); - if (!mapped) - return false; - - if (copy_to_user(buffer, mapped, size)) { - iounmap(mapped); - return false; - } - - iounmap(mapped); - return true; -} - -static bool write_physical_address(phys_addr_t pa, const void __user *buffer, size_t size) -{ - void *mapped; - - if (!pfn_valid(__phys_to_pfn(pa))) - return false; - - if (!is_valid_phys_addr_range(pa, size)) - return false; - - mapped = ioremap_cache(pa, size); - if (!mapped) - return false; - - if (copy_from_user(mapped, buffer, size)) { - iounmap(mapped); - return false; - } - - iounmap(mapped); - return true; -} - -static bool read_process_memory(pid_t pid, uintptr_t addr, - void __user *buffer, size_t size) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - phys_addr_t pa; - bool result = false; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return false; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return false; - } - - mm = get_task_mm(task); - put_pid(pid_struct); - - if (!mm) { - put_task_struct(task); - return false; - } - - pa = translate_linear_address(mm, addr); - if (pa) { - result = read_physical_address(pa, buffer, size); - } else { - struct vm_area_struct *vma = find_vma(mm, addr); - if (vma) { - if (clear_user(buffer, size) == 0) { - result = true; - } - } - } - - mmput(mm); - put_task_struct(task); - return result; -} - -static bool write_process_memory(pid_t pid, uintptr_t addr, - const void __user *buffer, size_t size) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - phys_addr_t pa; - bool result = false; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return false; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return false; - } - - mm = get_task_mm(task); - put_pid(pid_struct); - - if (!mm) { - put_task_struct(task); - return false; - } - - pa = translate_linear_address(mm, addr); - if (pa) { - result = write_physical_address(pa, buffer, size); - } - - mmput(mm); - put_task_struct(task); - return result; -} - -#define ARC_PATH_MAX 256 - -static uintptr_t get_module_base(pid_t pid, const char *name) -{ - struct task_struct *task = NULL; - struct mm_struct *mm = NULL; - struct pid *pid_struct = NULL; - struct vm_area_struct *vma = NULL; - uintptr_t base_addr = 0; - int path_len; - - pid_struct = find_get_pid(pid); - if (!pid_struct) - return 0; - - task = get_pid_task(pid_struct, PIDTYPE_PID); - if (!task) { - put_pid(pid_struct); - return 0; - } - - mm = get_task_mm(task); - put_pid(pid_struct); - - if (!mm) { - put_task_struct(task); - return 0; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) - struct vma_iterator vmi; - vma_iter_init(&vmi, mm, 0); - for_each_vma(vmi, vma) { -#else - for (vma = mm->mmap; vma; vma = vma->vm_next) { -#endif - char buf[ARC_PATH_MAX]; - char *path_nm; - - if (!vma->vm_file) - continue; - - path_nm = file_path(vma->vm_file, buf, ARC_PATH_MAX - 1); - if (IS_ERR(path_nm)) - continue; - - path_len = strlen(path_nm); - if (path_len <= 0) - continue; - - if (strstr(path_nm, name) != NULL) { - base_addr = vma->vm_start; - break; - } - } - - mmput(mm); - put_task_struct(task); - return base_addr; -} - -static int dispatch_open(struct inode *node, struct file *file) -{ - return 0; -} - -static int dispatch_close(struct inode *node, struct file *file) -{ - return 0; -} - -static long dispatch_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - static char key[256] = {0}; - static bool is_verified = false; - - switch (cmd) { - case OP_INIT_KEY: - if (!is_verified) { - if (copy_from_user(key, (void __user *)arg, sizeof(key) - 1) == 0) { - key[sizeof(key) - 1] = '\0'; - is_verified = true; - } else { - return -EFAULT; - } - } - break; - - case OP_READ_MEM: { - COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) - return -EFAULT; - - if (!read_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) - return -EIO; - - break; - } - - case OP_WRITE_MEM: { - COPY_MEMORY cm; - - if (copy_from_user(&cm, (void __user *)arg, sizeof(cm))) - return -EFAULT; - - if (!write_process_memory(cm.pid, cm.addr, cm.buffer, cm.size)) - return -EIO; - - break; - } - - case OP_MODULE_BASE: { - MODULE_BASE mb; - char module_name[256]; - - if (copy_from_user(&mb, (void __user *)arg, sizeof(mb))) - return -EFAULT; - - if (!mb.name) - return -EFAULT; - - if (copy_from_user(module_name, mb.name, sizeof(module_name) - 1)) - return -EFAULT; - module_name[sizeof(module_name) - 1] = '\0'; - - mb.base = get_module_base(mb.pid, module_name); - - if (copy_to_user((void __user *)arg, &mb, sizeof(mb))) - return -EFAULT; - - break; - } - - default: - return -ENOTTY; - } - - return 0; -} - -static const struct file_operations dispatch_fops = { - .owner = THIS_MODULE, - .open = dispatch_open, - .release = dispatch_close, - .unlocked_ioctl = dispatch_ioctl, - .compat_ioctl = dispatch_ioctl, -}; - -static int __init driver_entry(void) -{ - int ret; - - // 选择随机设备名(两种方式选其一) - // 方式1:从预选池中随机选择 - select_random_device_name(); - - // 方式2:生成完全随机的设备名(更隐蔽) - // generate_random_device_name(); - - // 注册设备 - misc_dev.minor = MISC_DYNAMIC_MINOR; - misc_dev.name = selected_device_name; - misc_dev.fops = &dispatch_fops; - misc_dev.mode = 0666; - - ret = misc_register(&misc_dev); - if (ret) { - printk(KERN_ERR "Aurora: Failed to register device %s, error %d\n", - selected_device_name, ret); - return ret; - } - - printk(KERN_INFO "Aurora: Successfully registered random device: %s\n", - selected_device_name); - return 0; -} - -static void __exit driver_unload(void) -{ - misc_deregister(&misc_dev); - printk(KERN_INFO "Aurora: Unregistered device: %s\n", selected_device_name); -} - -module_init(driver_entry); -module_exit(driver_unload); - -MODULE_DESCRIPTION("Linux Kernel Module"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("YihanChan"); -MODULE_VERSION("1.0"); From 30767a02884ba0e1eef0ccdd200cf89524ca4717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Fri, 30 Jan 2026 23:22:42 +0800 Subject: [PATCH 27/35] Delete code/aurora.h --- code/aurora.h | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 code/aurora.h diff --git a/code/aurora.h b/code/aurora.h deleted file mode 100644 index 6e09ba9b..00000000 --- a/code/aurora.h +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) -#include -#include -#else -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) -#include -#include -#endif From 01ddfeb6eeca3c4d442f85c0b0278e04b1d38257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Fri, 30 Jan 2026 23:24:22 +0800 Subject: [PATCH 28/35] Add files via upload --- code/Makefile | 2 +- code/anti_ptrace_detection.h | 146 ++++++++ code/api_proxy.h | 43 +++ code/arm64_register_helper.h | 160 +++++++++ code/hide_procfs_dir.h | 82 +++++ code/hwBreakpointProc_module.c | 591 +++++++++++++++++++++++++++++++++ code/hwBreakpointProc_module.h | 93 ++++++ code/hwbp_proc.h | 34 ++ code/kallsyms_lookup_api.h | 64 ++++ code/ver_control.h | 57 ++++ 10 files changed, 1271 insertions(+), 1 deletion(-) create mode 100644 code/anti_ptrace_detection.h create mode 100644 code/api_proxy.h create mode 100644 code/arm64_register_helper.h create mode 100644 code/hide_procfs_dir.h create mode 100644 code/hwBreakpointProc_module.c create mode 100644 code/hwBreakpointProc_module.h create mode 100644 code/hwbp_proc.h create mode 100644 code/kallsyms_lookup_api.h create mode 100644 code/ver_control.h diff --git a/code/Makefile b/code/Makefile index f5d1305e..20d191c4 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1 +1 @@ -obj-m += aurora.o +obj-m += hwBreakpointProc_module.o diff --git a/code/anti_ptrace_detection.h b/code/anti_ptrace_detection.h new file mode 100644 index 00000000..d3158657 --- /dev/null +++ b/code/anti_ptrace_detection.h @@ -0,0 +1,146 @@ +#ifndef _ANTI_PTRACE_DETECTION_H_ +#define _ANTI_PTRACE_DETECTION_H_ +#include +#include +#include +#include +#include +#include + +#define PTRACE_GETREGSET 0x4204 +#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ +#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ + +struct hook_ptrace_data { + struct iovec iov; +}; + +static struct mutex *g_p_hwbp_handle_info_mutex = NULL; +static cvector *g_p_hwbp_handle_info_arr = NULL; + +static bool is_my_hwbp_handle_addr(size_t addr) { + citerator iter; + bool found = false; + if(addr == 0) { + return found; + } + mutex_lock(g_p_hwbp_handle_info_mutex); + for (iter = cvector_begin(*g_p_hwbp_handle_info_arr); iter != cvector_end(*g_p_hwbp_handle_info_arr); iter = cvector_next(*g_p_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->original_attr.bp_addr == addr) { + found = true; + break; + } + } + mutex_unlock(g_p_hwbp_handle_info_mutex); + return found; +} + +static int entry_ptrace_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { + long request = regs->regs[1]; + unsigned long addr = (unsigned long)regs->regs[2]; + struct hook_ptrace_data *data = (struct hook_ptrace_data *)ri->data; + data->iov.iov_base = 0; + data->iov.iov_len = 0; + printk_debug(KERN_INFO "entry_ptrace_handler called with request: %lx, addr: %lx\n", request, addr); + if (request == PTRACE_GETREGSET && (addr == NT_ARM_HW_WATCH || addr == NT_ARM_HW_BREAK)) { + unsigned long iov_user_ptr = regs->regs[3]; + printk_debug(KERN_INFO "entry_ptrace_handler called with request: %lx, addr: %lx, iov_user_ptr: %lx\n", request, addr, iov_user_ptr); + if(!iov_user_ptr) { + return 0; + } + if (x_copy_from_user(&data->iov, (struct iovec __user *)iov_user_ptr, sizeof(struct iovec)) != 0) { + printk_debug(KERN_INFO "Failed to copy iovec from user space\n"); + return 0; + } + printk_debug(KERN_INFO "entry_ptrace_handler iov_base: %lx, iov_len %ld\n", data->iov.iov_base, data->iov.iov_len); + } + return 0; +} +static int ret_ptrace_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { + unsigned long retval = regs_return_value(regs); + struct hook_ptrace_data *data = (struct hook_ptrace_data *)ri->data; + struct user_hwdebug_state old_hw_state; + struct user_hwdebug_state new_hw_state; + size_t copy_size; + int i = 0, y = 0; + printk_debug(KERN_INFO "ret_ptrace_handler called with retval: %lx, iov_base: %lx, iov_len %ld\n", retval, data->iov.iov_base, data->iov.iov_len); + if (!data->iov.iov_base || !data->iov.iov_len) { + return 0; + } + + // Check if the buffer of the IoV is readable and writable + if (!access_ok((void __user *)data->iov.iov_base, data->iov.iov_len)) { + printk_debug(KERN_INFO "User buffer is not accessible\n"); + return 0; + } + copy_size = min(data->iov.iov_len, sizeof(struct user_hwdebug_state)); + if (x_copy_from_user(&old_hw_state, (void __user *)data->iov.iov_base, copy_size) != 0) { + printk_debug(KERN_INFO "Failed to copy old_hw_state from user buffer\n"); + return 0; + } + // After x_copy_from_user + printk_debug(KERN_INFO "Original old_hw_state.dbg_info: %u, size %ld\n", old_hw_state.dbg_info, copy_size); + for (i = 0; i < 16; i++) { + printk_debug(KERN_INFO "Reg %d: addr=%llu, ctrl=%u\n", i, old_hw_state.dbg_regs[i].addr, old_hw_state.dbg_regs[i].ctrl); + } + // Clear the dbd_regs array + memcpy(&new_hw_state, &old_hw_state, sizeof(new_hw_state)); + memset(new_hw_state.dbg_regs, 0x00, sizeof(new_hw_state.dbg_regs)); + + printk_debug(KERN_INFO "After memset:\n"); + for (i = 0; i < sizeof(old_hw_state.dbg_regs) / sizeof(old_hw_state.dbg_regs[0]); i++) { + if(!is_my_hwbp_handle_addr(old_hw_state.dbg_regs[i].addr)) { + memcpy(&new_hw_state.dbg_regs[y++], &old_hw_state.dbg_regs[i], sizeof(old_hw_state.dbg_regs[i])); + } + } + + printk_debug(KERN_INFO "After memset:\n"); + for (i = 0; i < 16; i++) { + printk_debug(KERN_INFO "Reg %d: addr=%llu, ctrl=%u\n", i, new_hw_state.dbg_regs[i].addr, new_hw_state.dbg_regs[i].ctrl); + } + + // Copy the modified hw_ste back to the buffer in user space + if (x_copy_to_user((void __user *)data->iov.iov_base, &new_hw_state, copy_size) != 0) { + printk_debug(KERN_INFO "Failed to copy modified new_hw_state back to user buffer\n"); + } else { + printk_debug(KERN_INFO "Successfully cleared dbg_regs in user_hwdebug_state\n"); + } + return 0; +} + + +static struct kretprobe kretp_ptrace = { + .kp.symbol_name = "arch_ptrace", + .data_size = sizeof(struct hook_ptrace_data), + .entry_handler = entry_ptrace_handler, + .handler = ret_ptrace_handler, + .maxactive = 20, +}; + +static bool start_anti_ptrace_detection(struct mutex *p_hwbp_handle_info_mutex, cvector *p_hwbp_handle_info_arr) { + int ret = 0; + g_p_hwbp_handle_info_mutex = p_hwbp_handle_info_mutex; + g_p_hwbp_handle_info_arr = p_hwbp_handle_info_arr; + if(!g_p_hwbp_handle_info_mutex || !g_p_hwbp_handle_info_arr) { + printk_debug(KERN_INFO "start_anti_ptrace_detection param error\n"); + return false; + } + ret = register_kretprobe(&kretp_ptrace); + if (ret < 0) { + printk_debug(KERN_INFO "register_kretprobe failed, returned %d\n", ret); + return false; + } + printk_debug(KERN_INFO "kretprobe at %s registered, addr: %lx\n", kretp_ptrace.kp.symbol_name, kretp_ptrace.kp.addr); + return true; +} + + +static void stop_anti_ptrace_detection(void) { + if(kretp_ptrace.kp.addr) { + unregister_kretprobe(&kretp_ptrace); + printk_debug(KERN_INFO "kretprobe unregistered\n"); + } +} + +#endif diff --git a/code/api_proxy.h b/code/api_proxy.h new file mode 100644 index 00000000..9349e957 --- /dev/null +++ b/code/api_proxy.h @@ -0,0 +1,43 @@ +#ifndef _API_PROXY_H_ +#define _API_PROXY_H_ +#include "ver_control.h" + +#ifdef CONFIG_KALLSYMS_LOOKUP_NAME +#include "kallsyms_lookup_api.h" +static struct perf_event* x_register_user_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context, struct task_struct *tsk) { + return register_user_hw_breakpoint_sym(attr, triggered, context, tsk); +} + +static void x_unregister_hw_breakpoint(struct perf_event *bp) { + unregister_hw_breakpoint_sym(bp); +} + +static int x_modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) { + return modify_user_hw_breakpoint_sym(bp, attr); +} +#else +static struct perf_event* x_register_user_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context, struct task_struct *tsk) { + return register_user_hw_breakpoint(attr, triggered, context, tsk); +} + +static void x_unregister_hw_breakpoint(struct perf_event *bp) { + unregister_hw_breakpoint(bp); +} + +static int x_modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) { + return modify_user_hw_breakpoint(bp, attr); +} +#endif + +static void * x_kmalloc(size_t size, gfp_t flags) { + return __kmalloc(size, flags); +} + +static unsigned long x_copy_from_user(void *to, const void __user *from, unsigned long n) { + return __arch_copy_from_user(to, from, n); +} + +static unsigned long x_copy_to_user(void __user *to, const void *from, unsigned long n) { + return __arch_copy_to_user(to, from, n); +} +#endif diff --git a/code/arm64_register_helper.h b/code/arm64_register_helper.h new file mode 100644 index 00000000..2a135174 --- /dev/null +++ b/code/arm64_register_helper.h @@ -0,0 +1,160 @@ +# ifndef __ARM64_REGISTER_HELPER_H__ +# define __ARM64_REGISTER_HELPER_H__ +#include +#include +#include +#include +#include + +#define READ_WB_REG_CASE(OFF, N, REG, VAL) \ + case (OFF + N): \ + AARCH64_DBG_READ(N, REG, VAL); \ + break + +#define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ + case (OFF + N): \ + AARCH64_DBG_WRITE(N, REG, VAL); \ + break + +#define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \ + READ_WB_REG_CASE(OFF, 0, REG, VAL); \ + READ_WB_REG_CASE(OFF, 1, REG, VAL); \ + READ_WB_REG_CASE(OFF, 2, REG, VAL); \ + READ_WB_REG_CASE(OFF, 3, REG, VAL); \ + READ_WB_REG_CASE(OFF, 4, REG, VAL); \ + READ_WB_REG_CASE(OFF, 5, REG, VAL); \ + READ_WB_REG_CASE(OFF, 6, REG, VAL); \ + READ_WB_REG_CASE(OFF, 7, REG, VAL); \ + READ_WB_REG_CASE(OFF, 8, REG, VAL); \ + READ_WB_REG_CASE(OFF, 9, REG, VAL); \ + READ_WB_REG_CASE(OFF, 10, REG, VAL); \ + READ_WB_REG_CASE(OFF, 11, REG, VAL); \ + READ_WB_REG_CASE(OFF, 12, REG, VAL); \ + READ_WB_REG_CASE(OFF, 13, REG, VAL); \ + READ_WB_REG_CASE(OFF, 14, REG, VAL); \ + READ_WB_REG_CASE(OFF, 15, REG, VAL) + +#define GEN_WRITE_WB_REG_CASES(OFF, REG, VAL) \ + WRITE_WB_REG_CASE(OFF, 0, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 15, REG, VAL) + +static int getCpuNumBrps(void) { + return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1; +} + +static int getCpuNumWrps(void) { + return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1; +} + +static uint64_t read_wb_reg(int reg, int n) +{ + uint64_t val = 0; + + switch (reg + n) { + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); + default: + pr_warn("attempt to read from unknown breakpoint register %d\n", n); + } + + return val; +} + +static void write_wb_reg(int reg, int n, uint64_t val) +{ + switch (reg + n) { + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); + default: + pr_warn("attempt to write to unknown breakpoint register %d\n", n); + } + isb(); +} + +static uint64_t calc_hw_addr(const struct perf_event_attr* attr, bool is_32bit_task) { + uint64_t alignment_mask, hw_addr; + if(!attr) { + return 0; + } + if (is_32bit_task) { + if (attr->bp_len == HW_BREAKPOINT_LEN_8) + alignment_mask = 0x7; + else + alignment_mask = 0x3; + } else { + if (attr->type == HW_BREAKPOINT_X) + alignment_mask = 0x3; + else + alignment_mask = 0x7; + } + hw_addr = attr->bp_addr; + hw_addr &= ~alignment_mask; + return hw_addr; +} + +static bool toggle_bp_registers_directly(const struct perf_event_attr * attr, bool is_32bit_task, int enable) { + int i, max_slots, val_reg, ctrl_reg, cur_slot; + u32 ctrl; + uint64_t hw_addr = calc_hw_addr(attr, is_32bit_task); + if(!attr) { + return false; + } + + switch (attr->bp_type) + { + case HW_BREAKPOINT_R: + case HW_BREAKPOINT_W: + case HW_BREAKPOINT_RW: + ctrl_reg = AARCH64_DBG_REG_WCR; + val_reg = AARCH64_DBG_REG_WVR; + max_slots = getCpuNumWrps(); + break; + case HW_BREAKPOINT_X: + ctrl_reg = AARCH64_DBG_REG_BCR; + val_reg = AARCH64_DBG_REG_BVR; + max_slots = getCpuNumBrps(); + break; + default: + return false; + } + cur_slot = -1; + + for (i = 0; i < max_slots; ++i) { + uint64_t addr = read_wb_reg(val_reg, i); + if(addr == hw_addr) { + cur_slot = i; + break; + } + } + if(cur_slot == -1) { + return false; + } + + ctrl = read_wb_reg(ctrl_reg, cur_slot); + if (enable) + ctrl |= 0x1; + else + ctrl &= ~0x1; + write_wb_reg(ctrl_reg, cur_slot, ctrl); + return true; +} +#endif + diff --git a/code/hide_procfs_dir.h b/code/hide_procfs_dir.h new file mode 100644 index 00000000..e92c15f0 --- /dev/null +++ b/code/hide_procfs_dir.h @@ -0,0 +1,82 @@ +#ifndef _HIDE_PROCFS_DIR_H_ +#define _HIDE_PROCFS_DIR_H_ + +#include "ver_control.h" + +#include +#include +#include +#include +#include +#include + +static char g_hide_dir_name[256] = {0}; + +static filldir_t old_filldir; + +#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(6,1,0) +static int my_filldir(struct dir_context *buf, + const char *name, + int namelen, + loff_t offset, + u64 ino, + unsigned int d_type) +{ + if (namelen == strlen(g_hide_dir_name) && + !strncmp(name, g_hide_dir_name, namelen)) + { + return 0; + } + return old_filldir(buf, name, namelen, offset, ino, d_type); +} +#else +static bool my_filldir(struct dir_context *ctx, + const char *name, + int namelen, + loff_t offset, + u64 ino, + unsigned int d_type) +{ + if (namelen == strlen(g_hide_dir_name) && + !strncmp(name, g_hide_dir_name, namelen)) + { + return true; + } + return old_filldir(ctx, name, namelen, offset, ino, d_type); +} +#endif + +static int handler_pre(struct kprobe *kp, struct pt_regs *regs) +{ + struct dir_context *ctx = (struct dir_context *)regs->regs[1]; + old_filldir = ctx->actor; + ctx->actor = my_filldir; + return 0; +} + +static struct kprobe kp_hide_procfs_dir = { + .symbol_name = "proc_root_readdir", + .pre_handler = handler_pre, +}; + +static bool start_hide_procfs_dir(const char* hide_dir_name) +{ + //这里原理上可以换成SKRoot的汇编写法。避免kprobe。 + int ret; + strlcpy(g_hide_dir_name, hide_dir_name, sizeof(g_hide_dir_name)); + ret = register_kprobe(&kp_hide_procfs_dir); + if (ret) { + printk_debug("[hide_procfs_dir] register_kprobe failed: %d\n", ret); + return false; + } + printk_debug("[hide_procfs_dir] kprobe installed, hiding \"%s\"\n", g_hide_dir_name); + return true; +} + +static void stop_hide_procfs_dir(void) +{ + unregister_kprobe(&kp_hide_procfs_dir); + printk_debug("[hide_procfs_dir] kprobe removed\n"); +} + +#endif // _HIDE_PROCFS_DIR_H_ diff --git a/code/hwBreakpointProc_module.c b/code/hwBreakpointProc_module.c new file mode 100644 index 00000000..e20edc7d --- /dev/null +++ b/code/hwBreakpointProc_module.c @@ -0,0 +1,591 @@ +#include "hwBreakpointProc_module.h" +#include "proc_pid.h" +#include "api_proxy.h" +#include "anti_ptrace_detection.h" + + +#pragma pack(push,1) +struct ioctl_request { + char cmd; /* 1 字节命令 */ + uint64_t param1; /* 参数1 */ + uint64_t param2; /* 参数2 */ + uint64_t param3; /* 参数3 */ + uint64_t buf_size; /* 紧随其后的动态数据长度 */ +}; +#pragma pack(pop) +////////////////////////////////////////////////////////////////// + +static atomic64_t g_hook_pc; + + +static struct mutex g_hwbp_handle_info_mutex; +static cvector g_hwbp_handle_info_arr = NULL; + +static void record_hit_details(struct HWBP_HANDLE_INFO *info, struct pt_regs *regs) { + struct HWBP_HIT_ITEM hit_item = {0}; + if (!info || !regs) { + return; + } + hit_item.task_id = info->task_id; + hit_item.hit_addr = regs->pc; + hit_item.hit_time = ktime_get_real_seconds(); + memcpy(&hit_item.regs_info.regs, regs->regs, sizeof(hit_item.regs_info.regs)); + hit_item.regs_info.sp = regs->sp; + hit_item.regs_info.pc = regs->pc; + hit_item.regs_info.pstate = regs->pstate; + hit_item.regs_info.orig_x0 = regs->orig_x0; + hit_item.regs_info.syscallno = regs->syscallno; + if (info->hit_item_arr) { + if(cvector_length(info->hit_item_arr) < MIN_LEN) { // 最多存放MIN_LEN个 + cvector_pushback(info->hit_item_arr, &hit_item); + } + } +} + +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE +static bool arm64_move_bp_to_next_instruction(struct perf_event *bp, uint64_t next_instruction_addr, struct perf_event_attr *original_attr, struct perf_event_attr * next_instruction_attr) { + int result; + if (!bp || !original_attr || !next_instruction_attr || !next_instruction_addr) { + return false; + } + memcpy(next_instruction_attr, original_attr, sizeof(struct perf_event_attr)); + next_instruction_attr->bp_addr = next_instruction_addr; + next_instruction_attr->bp_len = HW_BREAKPOINT_LEN_4; + next_instruction_attr->bp_type = HW_BREAKPOINT_X; + next_instruction_attr->disabled = 0; + result = x_modify_user_hw_breakpoint(bp, next_instruction_attr); + if(result) { + next_instruction_attr->bp_addr = 0; + return false; + } + return true; +} + +static bool arm64_recovery_bp_to_original(struct perf_event *bp, struct perf_event_attr *original_attr, struct perf_event_attr * next_instruction_attr) { + int result; + if (!bp || !original_attr || !next_instruction_attr) { + return false; + } + result = x_modify_user_hw_breakpoint(bp, original_attr); + if(result) { + return false; + } + next_instruction_attr->bp_addr = 0; + return true; +} +#endif + +static void hwbp_hit_user_info_callback(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs, struct HWBP_HANDLE_INFO * hwbp_handle_info) { + hwbp_handle_info->hit_total_count++; + record_hit_details(hwbp_handle_info, regs); +} + +/* + * Handle hitting a HW-breakpoint. + */ +static void hwbp_handler(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs) { + citerator iter; + uint64_t hook_pc; + printk_debug(KERN_INFO "hw_breakpoint HIT!!!!! bp:%px, pc:%px, id:%d\n", bp, regs->pc, bp->id); + + hook_pc = atomic64_read(&g_hook_pc); + if(hook_pc) { + regs->pc = hook_pc; + return; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp != bp) { + continue; + } +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + if(hwbp_handle_info->next_instruction_attr.bp_addr != regs->pc) { + // first hit + bool should_toggle = true; + hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); + if(!hwbp_handle_info->is_32bit_task) { + if(arm64_move_bp_to_next_instruction(bp, regs->pc + 4, &hwbp_handle_info->original_attr, &hwbp_handle_info->next_instruction_attr)) { + should_toggle = false; + } + } + if(should_toggle) { + toggle_bp_registers_directly(&hwbp_handle_info->original_attr, hwbp_handle_info->is_32bit_task, 0); + } + } else { + // second hit + if(!arm64_recovery_bp_to_original(bp, &hwbp_handle_info->original_attr, &hwbp_handle_info->next_instruction_attr)) { + toggle_bp_registers_directly(&hwbp_handle_info->next_instruction_attr, hwbp_handle_info->is_32bit_task, 0); + } + } +#else + hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); + toggle_bp_registers_directly(&hwbp_handle_info->original_attr, hwbp_handle_info->is_32bit_task, 0); +#endif + } + + mutex_unlock(&g_hwbp_handle_info_mutex); +} + + + +static ssize_t OnCmdOpenProcess(struct ioctl_request *hdr, char __user* buf) { + uint64_t pid = hdr->param1, handle = 0; + struct pid * proc_pid_struct = NULL; + printk_debug(KERN_INFO "CMD_OPEN_PROCESS\n"); + + printk_debug(KERN_INFO "pid:%llu,size:%ld\n", pid, sizeof(pid)); + + proc_pid_struct = get_proc_pid_struct(pid); + printk_debug(KERN_INFO "proc_pid_struct *:0x%p\n", (void*)proc_pid_struct); + if (!proc_pid_struct) { + return -EINVAL; + } + handle = (uint64_t)proc_pid_struct; + + printk_debug(KERN_INFO "handle:%llu,size:%ld\n", handle, sizeof(handle)); + if (!!x_copy_to_user((void*)buf, (void*)&handle, sizeof(handle))) { + return -EINVAL; + } + return 0; +} + +static ssize_t OnCmdCloseProcess(struct ioctl_request *hdr, char __user* buf) { + struct pid * proc_pid_struct = (struct pid *)hdr->param1; + printk_debug(KERN_INFO "CMD_CLOSE_PROCESS\n"); + printk_debug(KERN_INFO "proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); + release_proc_pid_struct(proc_pid_struct); + return 0; +} + +static ssize_t OnCmdGetCpuNumBrps(struct ioctl_request *hdr, char __user* buf) { + printk_debug(KERN_INFO "CMD_GET_NUM_BRPS\n"); + return getCpuNumBrps(); +} + +static ssize_t OnCmdGetCpuNumWrps(struct ioctl_request *hdr, char __user* buf) { + printk_debug(KERN_INFO "CMD_GET_NUM_WRPS\n"); + return getCpuNumWrps(); +} + +static ssize_t OnCmdInstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct pid * proc_pid_struct = (struct pid *)hdr->param1; + uint64_t proc_virt_addr = hdr->param2; + char hwbp_len = hdr->param3 & 0xFF; + char hwbp_type = (hdr->param3 >> 8) & 0xFF; + + pid_t pid_val; + struct task_struct *task; + struct HWBP_HANDLE_INFO hwbp_handle_info = { 0 }; + printk_debug(KERN_INFO "CMD_INST_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "proc_pid_struct *:%px\n", proc_pid_struct); + printk_debug(KERN_INFO "proc_virt_addr :%px\n", proc_virt_addr); + printk_debug(KERN_INFO "hwbp_len:%zu\n", hwbp_len); + printk_debug(KERN_INFO "hwbp_type:%d\n", hwbp_type); + + pid_val = pid_nr(proc_pid_struct); + printk_debug(KERN_INFO "pid_val:%d\n", pid_val); + + if (!pid_val) { + printk_debug(KERN_INFO "pid_nr failed.\n"); + return -EINVAL; + } + + task = pid_task(proc_pid_struct, PIDTYPE_PID); + if (!task) { + printk_debug(KERN_INFO "get_pid_task failed.\n"); + return -EINVAL; + } + + hwbp_handle_info.task_id = pid_val; + hwbp_handle_info.is_32bit_task = is_compat_thread(task_thread_info(task)); + ptrace_breakpoint_init(&hwbp_handle_info.original_attr); + hwbp_handle_info.original_attr.bp_addr = proc_virt_addr; + hwbp_handle_info.original_attr.bp_len = hwbp_len; + hwbp_handle_info.original_attr.bp_type = hwbp_type; + hwbp_handle_info.original_attr.disabled = 0; + + hwbp_handle_info.sample_hbp = x_register_user_hw_breakpoint(&hwbp_handle_info.original_attr, hwbp_handler, NULL, task); + printk_debug(KERN_INFO "register_user_hw_breakpoint return: %px\n", hwbp_handle_info.sample_hbp); + if (IS_ERR((void __force *)hwbp_handle_info.sample_hbp)) { + int ret = PTR_ERR((void __force *)hwbp_handle_info.sample_hbp); + printk_debug(KERN_INFO "register_user_hw_breakpoint failed: %d\n", ret); + return ret; + } + hwbp_handle_info.hit_item_arr = cvector_create(sizeof(struct HWBP_HIT_ITEM)); + mutex_lock(&g_hwbp_handle_info_mutex); + cvector_pushback(g_hwbp_handle_info_arr, &hwbp_handle_info); + mutex_unlock(&g_hwbp_handle_info_mutex); + + if (x_copy_to_user((void*)buf, &hwbp_handle_info.sample_hbp, sizeof(uint64_t))) { + return -EINVAL; + } + return 0; +} + +static ssize_t OnCmdUninstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct perf_event * sample_hbp = (struct perf_event *)hdr->param1; + citerator iter; + bool found = false; + printk_debug(KERN_INFO "CMD_UNINST_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + if(!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp == sample_hbp) { + if(hwbp_handle_info->hit_item_arr) { + cvector_destroy(hwbp_handle_info->hit_item_arr); + hwbp_handle_info->hit_item_arr = NULL; + } + cvector_rm(g_hwbp_handle_info_arr, iter); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + if(found) { + x_unregister_hw_breakpoint(sample_hbp); + } + + return 0; +} + +static ssize_t OnCmdSuspendProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct perf_event * sample_hbp = (struct perf_event *)hdr->param1; + struct perf_event_attr new_instruction_attr; + citerator iter; + bool found = false; + printk_debug(KERN_INFO "CMD_SUSPEND_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + if(!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp == sample_hbp) { + hwbp_handle_info->original_attr.disabled = 1; + memcpy(&new_instruction_attr, &hwbp_handle_info->original_attr, sizeof(struct perf_event_attr)); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + if(found) { + if(!x_modify_user_hw_breakpoint(sample_hbp, &new_instruction_attr)) { + return 0; + } + } + return -EFAULT; +} + +static ssize_t OnCmdResumeProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct perf_event * sample_hbp = (struct perf_event *)hdr->param1; + struct perf_event_attr new_instruction_attr; + citerator iter; + bool found = false; + printk_debug(KERN_INFO "CMD_RESUME_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + if(!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp == sample_hbp) { + hwbp_handle_info->original_attr.disabled = 0; + memcpy(&new_instruction_attr, &hwbp_handle_info->original_attr, sizeof(struct perf_event_attr)); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + if(found) { + if(!x_modify_user_hw_breakpoint(sample_hbp, &new_instruction_attr)) { + return 0; + } + } + return -EFAULT; +} + +static ssize_t OnCmdGetHwbpHitCount(struct ioctl_request *hdr, char __user* buf) { + #pragma pack(1) + struct buf_layout { + uint64_t hit_total_count; + uint64_t hit_item_arr_count; + }; + #pragma pack() + struct perf_event *sample_hbp = (struct perf_event *)hdr->param1; + struct buf_layout user_data = {0}; + citerator iter; + printk_debug(KERN_INFO "CMD_GET_HWBP_HIT_COUNT\n"); + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp == sample_hbp && hwbp_handle_info->hit_item_arr) { + user_data.hit_total_count = hwbp_handle_info->hit_total_count; + user_data.hit_item_arr_count = cvector_length(hwbp_handle_info->hit_item_arr); + break; + } + } + + mutex_unlock(&g_hwbp_handle_info_mutex); + + printk_debug(KERN_INFO "user_data.hit_total_count:%zu\n", user_data.hit_total_count); + if (x_copy_to_user((void*)buf, &user_data, sizeof(user_data))) { + return -EINVAL; + } + return 0; +} + +static ssize_t OnCmdGetHwbpHitDetail(struct ioctl_request *hdr, char __user* buf) { + struct perf_event *sample_hbp = (struct perf_event *)hdr->param1; + size_t size = hdr->buf_size; + ssize_t count = 0; + size_t copy_pos; + size_t end_pos; + + citerator iter; + printk_debug(KERN_INFO "sample_hbp *:%ld\n", sample_hbp); + + copy_pos = (size_t)buf; + end_pos = (size_t)((size_t)buf + size); + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp == sample_hbp && hwbp_handle_info->hit_item_arr) { + citerator child; + for (child = cvector_begin(hwbp_handle_info->hit_item_arr); child != cvector_end(hwbp_handle_info->hit_item_arr); child = cvector_next(hwbp_handle_info->hit_item_arr, child)) { + struct HWBP_HIT_ITEM * hit_item = (struct HWBP_HIT_ITEM *)child; + if (copy_pos >= end_pos) { + break; + } + if (x_copy_to_user((void*)copy_pos, hit_item, sizeof(struct HWBP_HIT_ITEM))) { + break; + } + copy_pos += sizeof(struct HWBP_HIT_ITEM); + count++; + } + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + return count; +} + +static ssize_t OnCmdSetHookPc(struct ioctl_request *hdr, char __user* buf) { + uint64_t pc = hdr->param1; + printk_debug(KERN_INFO "CMD_SET_HOOK_PC\n"); + printk_debug(KERN_INFO "pc:%px\n", pc); + atomic64_set(&g_hook_pc, pc); + return 0; +} + +static ssize_t OnCmdHideKernelModule(struct ioctl_request *hdr, char __user* buf) { + printk_debug(KERN_INFO "CMD_HIDE_KERNEL_MODULE\n"); + if (g_hwBreakpointProc_devp->is_hidden_module == false) { + g_hwBreakpointProc_devp->is_hidden_module = true; + list_del_init(&__this_module.list); + kobject_del(&THIS_MODULE->mkobj.kobj); + } + return 0; +} + +static inline ssize_t DispatchCommand(struct ioctl_request *hdr, char __user* buf) { + switch (hdr->cmd) { + case CMD_OPEN_PROCESS: + return OnCmdOpenProcess(hdr, buf); + case CMD_CLOSE_PROCESS: + return OnCmdCloseProcess(hdr, buf); + case CMD_GET_NUM_BRPS: + return OnCmdGetCpuNumBrps(hdr, buf); + case CMD_GET_NUM_WRPS: + return OnCmdGetCpuNumWrps(hdr, buf); + case CMD_INST_PROCESS_HWBP: + return OnCmdInstProcessHwbp(hdr, buf); + case CMD_UNINST_PROCESS_HWBP: + return OnCmdUninstProcessHwbp(hdr, buf); + case CMD_SUSPEND_PROCESS_HWBP: + return OnCmdSuspendProcessHwbp(hdr, buf); + case CMD_RESUME_PROCESS_HWBP: + return OnCmdResumeProcessHwbp(hdr, buf); + case CMD_GET_HWBP_HIT_COUNT: + return OnCmdGetHwbpHitCount(hdr, buf); + case CMD_GET_HWBP_HIT_DETAIL: + return OnCmdGetHwbpHitDetail(hdr, buf); + case CMD_SET_HOOK_PC: + return OnCmdSetHookPc(hdr, buf); + case CMD_HIDE_KERNEL_MODULE: + return OnCmdHideKernelModule(hdr, buf); + default: + return -EINVAL; + } + return -EINVAL; +} + +static ssize_t hwBreakpointProc_read(struct file* filp, + char __user* buf, + size_t size, + loff_t* ppos) { + struct ioctl_request hdr = {0}; + size_t header_size = sizeof(hdr); + + if (size < header_size) { + return -EINVAL; + } + + if (x_copy_from_user(&hdr, buf, header_size)) { + return -EFAULT; + } + + if (size < header_size + hdr.buf_size) { + return -EINVAL; + } + + return DispatchCommand(&hdr, buf + header_size); +} + +static void clean_hwbp(void) { + citerator iter; + cvector wait_unregister_bp_arr = cvector_create(sizeof(struct perf_event *)); + if(!wait_unregister_bp_arr || !g_hwbp_handle_info_arr) { + return; + } + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp) { + cvector_pushback(wait_unregister_bp_arr, &hwbp_handle_info->sample_hbp); + hwbp_handle_info->sample_hbp = NULL; + } + if(hwbp_handle_info->hit_item_arr) { + cvector_destroy(hwbp_handle_info->hit_item_arr); + hwbp_handle_info->hit_item_arr = NULL; + } + } + cvector_destroy(g_hwbp_handle_info_arr); + g_hwbp_handle_info_arr = NULL; + mutex_unlock(&g_hwbp_handle_info_mutex); + + for (iter = cvector_begin(wait_unregister_bp_arr); iter != cvector_end(wait_unregister_bp_arr); iter = cvector_next(wait_unregister_bp_arr, iter)) { + struct perf_event * bp = *(struct perf_event **)iter; + x_unregister_hw_breakpoint(bp); + } + cvector_destroy(wait_unregister_bp_arr); +} + +static int hwBreakpointProc_release(struct inode *inode, struct file *filp) { + clean_hwbp(); + mutex_lock(&g_hwbp_handle_info_mutex); + g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); + mutex_unlock(&g_hwbp_handle_info_mutex); + return 0; +} + +static int hwBreakpointProc_dev_init(void) { +#ifdef CONFIG_KALLSYMS_LOOKUP_NAME + if(!init_kallsyms_lookup()) { + printk(KERN_EMERG "init_kallsyms_lookup failed\n"); + return -EBADF; + } +#endif + g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); + mutex_init(&g_hwbp_handle_info_mutex); + +#ifdef CONFIG_ANTI_PTRACE_DETECTION_MODE + start_anti_ptrace_detection(&g_hwbp_handle_info_mutex, &g_hwbp_handle_info_arr); +#endif + + g_hwBreakpointProc_devp = x_kmalloc(sizeof(struct hwBreakpointProcDev), GFP_KERNEL); + memset(g_hwBreakpointProc_devp, 0, sizeof(struct hwBreakpointProcDev)); + +#ifdef CONFIG_USE_PROC_FILE_NODE + g_hwBreakpointProc_devp->proc_parent = proc_mkdir(CONFIG_PROC_NODE_AUTH_KEY, NULL); + if(g_hwBreakpointProc_devp->proc_parent) { + g_hwBreakpointProc_devp->proc_entry = proc_create(CONFIG_PROC_NODE_AUTH_KEY, S_IRUGO | S_IWUGO, g_hwBreakpointProc_devp->proc_parent, &hwBreakpointProc_proc_ops); + start_hide_procfs_dir(CONFIG_PROC_NODE_AUTH_KEY); + } +#endif + +#ifdef DEBUG_PRINTK + printk(KERN_EMERG "Hello, %s debug\n", CONFIG_PROC_NODE_AUTH_KEY); + //test1(); + //test2(); + //test3(); + //test4(); +#else + printk(KERN_EMERG "Hello\n"); +#endif + return 0; +} + +static void hwBreakpointProc_dev_exit(void) { + +#ifdef CONFIG_ANTI_PTRACE_DETECTION_MODE + stop_anti_ptrace_detection(); +#endif + + clean_hwbp(); + + mutex_destroy(&g_hwbp_handle_info_mutex); + +#ifdef CONFIG_USE_PROC_FILE_NODE + if(g_hwBreakpointProc_devp->proc_entry) { + proc_remove(g_hwBreakpointProc_devp->proc_entry); + g_hwBreakpointProc_devp->proc_entry = NULL; + } + + if(g_hwBreakpointProc_devp->proc_parent) { + proc_remove(g_hwBreakpointProc_devp->proc_parent); + g_hwBreakpointProc_devp->proc_parent = NULL; + } + stop_hide_procfs_dir(); +#endif + kfree(g_hwBreakpointProc_devp); + printk(KERN_EMERG "Goodbye\n"); +} + +int __init init_module(void) { + return hwBreakpointProc_dev_init(); +} + +void __exit cleanup_module(void) { + hwBreakpointProc_dev_exit(); +} + +#ifndef CONFIG_MODULE_GUIDE_ENTRY +//Hook:__cfi_check_fn +unsigned char* __check_(unsigned char* result, void *ptr, void *diag) +{ + printk_debug(KERN_EMERG "my__cfi_check_fn!!!\n"); + return result; +} + +//Hook:__cfi_check_fail +unsigned char * __check_fail_(unsigned char *result) +{ + printk_debug(KERN_EMERG "my__cfi_check_fail!!!\n"); + return result; +} +#endif + +unsigned long __stack_chk_guard; + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linux"); +MODULE_DESCRIPTION("Linux default module"); + diff --git a/code/hwBreakpointProc_module.h b/code/hwBreakpointProc_module.h new file mode 100644 index 00000000..fe2422c8 --- /dev/null +++ b/code/hwBreakpointProc_module.h @@ -0,0 +1,93 @@ +#ifndef _HWBP_PROC_H_ +#define _HWBP_PROC_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //kmalloc与kfree +#include "ver_control.h" +#include "arm64_register_helper.h" +#include "cvector.h" +#ifdef CONFIG_USE_PROC_FILE_NODE +#include +#include "hide_procfs_dir.h" +#endif +////////////////////////////////////////////////////////////////// + +enum { + CMD_OPEN_PROCESS, // 打开进程 + CMD_CLOSE_PROCESS, // 关闭进程 + CMD_GET_NUM_BRPS, // 获取CPU硬件执行断点支持数量 + CMD_GET_NUM_WRPS, // 获取CPU硬件访问断点支持数量 + CMD_INST_PROCESS_HWBP, // 安装进程硬件断点 + CMD_UNINST_PROCESS_HWBP, // 卸载进程硬件断点 + CMD_SUSPEND_PROCESS_HWBP, // 暂停进程硬件断点 + CMD_RESUME_PROCESS_HWBP, // 恢复进程硬件断点 + CMD_GET_HWBP_HIT_COUNT, // 获取硬件断点命中地址数量 + CMD_GET_HWBP_HIT_DETAIL, // 获取硬件断点命中详细信息 + CMD_SET_HOOK_PC, // 设置无条件Hook跳转 + CMD_HIDE_KERNEL_MODULE, // 隐藏驱动 +}; + +struct hwBreakpointProcDev { +#ifdef CONFIG_USE_PROC_FILE_NODE + struct proc_dir_entry *proc_parent; + struct proc_dir_entry *proc_entry; +#endif + bool is_hidden_module; //是否已经隐藏过驱动列表了 +}; +static struct hwBreakpointProcDev *g_hwBreakpointProc_devp; + +static ssize_t hwBreakpointProc_read(struct file* filp, char __user* buf, size_t size, loff_t* ppos); +static int hwBreakpointProc_release(struct inode *inode, struct file *filp); +static const struct proc_ops hwBreakpointProc_proc_ops = { + .proc_read = hwBreakpointProc_read, + .proc_release = hwBreakpointProc_release, +}; + +#pragma pack(1) +struct my_user_pt_regs { + uint64_t regs[31]; + uint64_t sp; + uint64_t pc; + uint64_t pstate; + uint64_t orig_x0; + uint64_t syscallno; +}; +struct HWBP_HIT_ITEM { + uint64_t task_id; + uint64_t hit_addr; + uint64_t hit_time; + struct my_user_pt_regs regs_info; +}; +#pragma pack() + +struct HWBP_HANDLE_INFO { + uint64_t task_id; + struct perf_event * sample_hbp; + struct perf_event_attr original_attr; + bool is_32bit_task; +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + struct perf_event_attr next_instruction_attr; +#endif + size_t hit_total_count; + cvector hit_item_arr; +}; + +#endif /* _HWBP_PROC_H_ */ \ No newline at end of file diff --git a/code/hwbp_proc.h b/code/hwbp_proc.h new file mode 100644 index 00000000..88801c5f --- /dev/null +++ b/code/hwbp_proc.h @@ -0,0 +1,34 @@ +#ifndef _HWBP_PROC_H_ +#define _HWBP_PROC_H_ +#include "ver_control.h" + +#pragma pack(1) +struct my_user_pt_regs { + uint64_t regs[31]; + uint64_t sp; + uint64_t pc; + uint64_t pstate; + uint64_t orig_x0; + uint64_t syscallno; +}; +struct HWBP_HIT_ITEM { + uint64_t task_id; + uint64_t hit_addr; + uint64_t hit_time; + struct my_user_pt_regs regs_info; +}; +#pragma pack() + +struct HWBP_HANDLE_INFO { + uint64_t task_id; + struct perf_event * sample_hbp; + struct perf_event_attr original_attr; + bool is_32bit_task; +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + struct perf_event_attr next_instruction_attr; +#endif + size_t hit_total_count; + cvector hit_item_arr; +}; + +#endif \ No newline at end of file diff --git a/code/kallsyms_lookup_api.h b/code/kallsyms_lookup_api.h new file mode 100644 index 00000000..f3592579 --- /dev/null +++ b/code/kallsyms_lookup_api.h @@ -0,0 +1,64 @@ +#ifndef _KALLSYMS_LOOKUP_API_H_ +#define _KALLSYMS_LOOKUP_API_H_ +#include "ver_control.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned long (*kallsyms_lookup_name_sym)(const char *name); +static struct perf_event* (*register_user_hw_breakpoint_sym)(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context, struct task_struct *tsk); +static void (*unregister_hw_breakpoint_sym)(struct perf_event *bp); +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE +static int (*modify_user_hw_breakpoint_sym)(struct perf_event *bp, struct perf_event_attr *attr); +#endif + +static int _kallsyms_lookup_kprobe(struct kprobe *p, struct pt_regs *regs) { return 0; } +static unsigned long get_kallsyms_func(void) { + int ret; + unsigned long addr = 0; + struct kprobe probe = {0}; + probe.pre_handler = _kallsyms_lookup_kprobe; + probe.symbol_name = "kallsyms_lookup_name"; + ret = register_kprobe(&probe); + if (ret == 0) { + addr = (unsigned long)probe.addr; + printk_debug(KERN_EMERG "get_kallsyms_func(kallsyms_lookup_name):%px\n", addr); + unregister_kprobe(&probe); + } + return addr; +} + +static unsigned long generic_kallsyms_lookup_name(const char *name) { + if (!kallsyms_lookup_name_sym) { + kallsyms_lookup_name_sym = (void *)get_kallsyms_func(); + printk_debug(KERN_EMERG "get_kallsyms_func:%px\n", kallsyms_lookup_name_sym); + if(!kallsyms_lookup_name_sym) + return 0; + } + return kallsyms_lookup_name_sym(name); +} + +static bool init_kallsyms_lookup(void) { + register_user_hw_breakpoint_sym = (void *)generic_kallsyms_lookup_name("register_user_hw_breakpoint"); + printk_debug(KERN_EMERG "register_user_hw_breakpoint_sym:%px\n", register_user_hw_breakpoint_sym); + if(!register_user_hw_breakpoint_sym) { return false; } + + unregister_hw_breakpoint_sym = (void *)generic_kallsyms_lookup_name("unregister_hw_breakpoint"); + printk_debug(KERN_EMERG "unregister_hw_breakpoint_sym:%px\n", unregister_hw_breakpoint_sym); + if(!unregister_hw_breakpoint_sym) { return false; } + +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + modify_user_hw_breakpoint_sym = (void *)generic_kallsyms_lookup_name("modify_user_hw_breakpoint"); + printk_debug(KERN_EMERG "modify_user_hw_breakpoint_sym:%px\n", modify_user_hw_breakpoint_sym); + if(!modify_user_hw_breakpoint_sym) { return false; } +#endif + + return true; +} +#endif diff --git a/code/ver_control.h b/code/ver_control.h new file mode 100644 index 00000000..474e9163 --- /dev/null +++ b/code/ver_control.h @@ -0,0 +1,57 @@ +#ifndef VER_CONTROL_H_ +#define VER_CONTROL_H_ +#include + +// 独立内核模块入口模式 +#define CONFIG_MODULE_GUIDE_ENTRY + +// 生成proc用户层交互节点文件 +#define CONFIG_USE_PROC_FILE_NODE +// 隐蔽通信密钥 +#define CONFIG_PROC_NODE_AUTH_KEY "dce3771681d4c7a143d5d06b7d32548e" + +// 调试打印模式 +//#define CONFIG_DEBUG_PRINTK + +// 动态寻址模式 +#define CONFIG_KALLSYMS_LOOKUP_NAME + +// 精准命中记录模式 +#define CONFIG_MODIFY_HIT_NEXT_MODE + +// 反PTRACE侦测模式 +#define CONFIG_ANTI_PTRACE_DETECTION_MODE + +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif +#ifndef MY_LINUX_VERSION_CODE +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,10,0) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,10,84) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,18,71) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,18,140) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,21) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,78) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,153) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,192) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,9,112) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,9,186) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,83) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,117) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,141) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,19,81) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,19,113) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,4,61) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,10,43) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,15,41) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,1,75) +#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,6,30) +#endif + +#ifdef CONFIG_DEBUG_PRINTK +#define printk_debug printk +#else +static inline void printk_debug(char *fmt, ...) {} +#endif + +#endif /* VER_CONTROL_H_ */ From 897a0c84679f1fb0b20cf35a10076d5d780b3b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 3 Feb 2026 10:44:01 +0800 Subject: [PATCH 29/35] Delete code directory --- code/Makefile | 1 - code/anti_ptrace_detection.h | 146 -------- code/api_proxy.h | 43 --- code/arm64_register_helper.h | 160 --------- code/hide_procfs_dir.h | 82 ----- code/hwBreakpointProc_module.c | 591 --------------------------------- code/hwBreakpointProc_module.h | 93 ------ code/hwbp_proc.h | 34 -- code/kallsyms_lookup_api.h | 64 ---- code/ver_control.h | 57 ---- 10 files changed, 1271 deletions(-) delete mode 100644 code/Makefile delete mode 100644 code/anti_ptrace_detection.h delete mode 100644 code/api_proxy.h delete mode 100644 code/arm64_register_helper.h delete mode 100644 code/hide_procfs_dir.h delete mode 100644 code/hwBreakpointProc_module.c delete mode 100644 code/hwBreakpointProc_module.h delete mode 100644 code/hwbp_proc.h delete mode 100644 code/kallsyms_lookup_api.h delete mode 100644 code/ver_control.h diff --git a/code/Makefile b/code/Makefile deleted file mode 100644 index 20d191c4..00000000 --- a/code/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m += hwBreakpointProc_module.o diff --git a/code/anti_ptrace_detection.h b/code/anti_ptrace_detection.h deleted file mode 100644 index d3158657..00000000 --- a/code/anti_ptrace_detection.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef _ANTI_PTRACE_DETECTION_H_ -#define _ANTI_PTRACE_DETECTION_H_ -#include -#include -#include -#include -#include -#include - -#define PTRACE_GETREGSET 0x4204 -#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ -#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ - -struct hook_ptrace_data { - struct iovec iov; -}; - -static struct mutex *g_p_hwbp_handle_info_mutex = NULL; -static cvector *g_p_hwbp_handle_info_arr = NULL; - -static bool is_my_hwbp_handle_addr(size_t addr) { - citerator iter; - bool found = false; - if(addr == 0) { - return found; - } - mutex_lock(g_p_hwbp_handle_info_mutex); - for (iter = cvector_begin(*g_p_hwbp_handle_info_arr); iter != cvector_end(*g_p_hwbp_handle_info_arr); iter = cvector_next(*g_p_hwbp_handle_info_arr, iter)) { - struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if(hwbp_handle_info->original_attr.bp_addr == addr) { - found = true; - break; - } - } - mutex_unlock(g_p_hwbp_handle_info_mutex); - return found; -} - -static int entry_ptrace_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { - long request = regs->regs[1]; - unsigned long addr = (unsigned long)regs->regs[2]; - struct hook_ptrace_data *data = (struct hook_ptrace_data *)ri->data; - data->iov.iov_base = 0; - data->iov.iov_len = 0; - printk_debug(KERN_INFO "entry_ptrace_handler called with request: %lx, addr: %lx\n", request, addr); - if (request == PTRACE_GETREGSET && (addr == NT_ARM_HW_WATCH || addr == NT_ARM_HW_BREAK)) { - unsigned long iov_user_ptr = regs->regs[3]; - printk_debug(KERN_INFO "entry_ptrace_handler called with request: %lx, addr: %lx, iov_user_ptr: %lx\n", request, addr, iov_user_ptr); - if(!iov_user_ptr) { - return 0; - } - if (x_copy_from_user(&data->iov, (struct iovec __user *)iov_user_ptr, sizeof(struct iovec)) != 0) { - printk_debug(KERN_INFO "Failed to copy iovec from user space\n"); - return 0; - } - printk_debug(KERN_INFO "entry_ptrace_handler iov_base: %lx, iov_len %ld\n", data->iov.iov_base, data->iov.iov_len); - } - return 0; -} -static int ret_ptrace_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { - unsigned long retval = regs_return_value(regs); - struct hook_ptrace_data *data = (struct hook_ptrace_data *)ri->data; - struct user_hwdebug_state old_hw_state; - struct user_hwdebug_state new_hw_state; - size_t copy_size; - int i = 0, y = 0; - printk_debug(KERN_INFO "ret_ptrace_handler called with retval: %lx, iov_base: %lx, iov_len %ld\n", retval, data->iov.iov_base, data->iov.iov_len); - if (!data->iov.iov_base || !data->iov.iov_len) { - return 0; - } - - // Check if the buffer of the IoV is readable and writable - if (!access_ok((void __user *)data->iov.iov_base, data->iov.iov_len)) { - printk_debug(KERN_INFO "User buffer is not accessible\n"); - return 0; - } - copy_size = min(data->iov.iov_len, sizeof(struct user_hwdebug_state)); - if (x_copy_from_user(&old_hw_state, (void __user *)data->iov.iov_base, copy_size) != 0) { - printk_debug(KERN_INFO "Failed to copy old_hw_state from user buffer\n"); - return 0; - } - // After x_copy_from_user - printk_debug(KERN_INFO "Original old_hw_state.dbg_info: %u, size %ld\n", old_hw_state.dbg_info, copy_size); - for (i = 0; i < 16; i++) { - printk_debug(KERN_INFO "Reg %d: addr=%llu, ctrl=%u\n", i, old_hw_state.dbg_regs[i].addr, old_hw_state.dbg_regs[i].ctrl); - } - // Clear the dbd_regs array - memcpy(&new_hw_state, &old_hw_state, sizeof(new_hw_state)); - memset(new_hw_state.dbg_regs, 0x00, sizeof(new_hw_state.dbg_regs)); - - printk_debug(KERN_INFO "After memset:\n"); - for (i = 0; i < sizeof(old_hw_state.dbg_regs) / sizeof(old_hw_state.dbg_regs[0]); i++) { - if(!is_my_hwbp_handle_addr(old_hw_state.dbg_regs[i].addr)) { - memcpy(&new_hw_state.dbg_regs[y++], &old_hw_state.dbg_regs[i], sizeof(old_hw_state.dbg_regs[i])); - } - } - - printk_debug(KERN_INFO "After memset:\n"); - for (i = 0; i < 16; i++) { - printk_debug(KERN_INFO "Reg %d: addr=%llu, ctrl=%u\n", i, new_hw_state.dbg_regs[i].addr, new_hw_state.dbg_regs[i].ctrl); - } - - // Copy the modified hw_ste back to the buffer in user space - if (x_copy_to_user((void __user *)data->iov.iov_base, &new_hw_state, copy_size) != 0) { - printk_debug(KERN_INFO "Failed to copy modified new_hw_state back to user buffer\n"); - } else { - printk_debug(KERN_INFO "Successfully cleared dbg_regs in user_hwdebug_state\n"); - } - return 0; -} - - -static struct kretprobe kretp_ptrace = { - .kp.symbol_name = "arch_ptrace", - .data_size = sizeof(struct hook_ptrace_data), - .entry_handler = entry_ptrace_handler, - .handler = ret_ptrace_handler, - .maxactive = 20, -}; - -static bool start_anti_ptrace_detection(struct mutex *p_hwbp_handle_info_mutex, cvector *p_hwbp_handle_info_arr) { - int ret = 0; - g_p_hwbp_handle_info_mutex = p_hwbp_handle_info_mutex; - g_p_hwbp_handle_info_arr = p_hwbp_handle_info_arr; - if(!g_p_hwbp_handle_info_mutex || !g_p_hwbp_handle_info_arr) { - printk_debug(KERN_INFO "start_anti_ptrace_detection param error\n"); - return false; - } - ret = register_kretprobe(&kretp_ptrace); - if (ret < 0) { - printk_debug(KERN_INFO "register_kretprobe failed, returned %d\n", ret); - return false; - } - printk_debug(KERN_INFO "kretprobe at %s registered, addr: %lx\n", kretp_ptrace.kp.symbol_name, kretp_ptrace.kp.addr); - return true; -} - - -static void stop_anti_ptrace_detection(void) { - if(kretp_ptrace.kp.addr) { - unregister_kretprobe(&kretp_ptrace); - printk_debug(KERN_INFO "kretprobe unregistered\n"); - } -} - -#endif diff --git a/code/api_proxy.h b/code/api_proxy.h deleted file mode 100644 index 9349e957..00000000 --- a/code/api_proxy.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _API_PROXY_H_ -#define _API_PROXY_H_ -#include "ver_control.h" - -#ifdef CONFIG_KALLSYMS_LOOKUP_NAME -#include "kallsyms_lookup_api.h" -static struct perf_event* x_register_user_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context, struct task_struct *tsk) { - return register_user_hw_breakpoint_sym(attr, triggered, context, tsk); -} - -static void x_unregister_hw_breakpoint(struct perf_event *bp) { - unregister_hw_breakpoint_sym(bp); -} - -static int x_modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) { - return modify_user_hw_breakpoint_sym(bp, attr); -} -#else -static struct perf_event* x_register_user_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context, struct task_struct *tsk) { - return register_user_hw_breakpoint(attr, triggered, context, tsk); -} - -static void x_unregister_hw_breakpoint(struct perf_event *bp) { - unregister_hw_breakpoint(bp); -} - -static int x_modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) { - return modify_user_hw_breakpoint(bp, attr); -} -#endif - -static void * x_kmalloc(size_t size, gfp_t flags) { - return __kmalloc(size, flags); -} - -static unsigned long x_copy_from_user(void *to, const void __user *from, unsigned long n) { - return __arch_copy_from_user(to, from, n); -} - -static unsigned long x_copy_to_user(void __user *to, const void *from, unsigned long n) { - return __arch_copy_to_user(to, from, n); -} -#endif diff --git a/code/arm64_register_helper.h b/code/arm64_register_helper.h deleted file mode 100644 index 2a135174..00000000 --- a/code/arm64_register_helper.h +++ /dev/null @@ -1,160 +0,0 @@ -# ifndef __ARM64_REGISTER_HELPER_H__ -# define __ARM64_REGISTER_HELPER_H__ -#include -#include -#include -#include -#include - -#define READ_WB_REG_CASE(OFF, N, REG, VAL) \ - case (OFF + N): \ - AARCH64_DBG_READ(N, REG, VAL); \ - break - -#define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ - case (OFF + N): \ - AARCH64_DBG_WRITE(N, REG, VAL); \ - break - -#define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \ - READ_WB_REG_CASE(OFF, 0, REG, VAL); \ - READ_WB_REG_CASE(OFF, 1, REG, VAL); \ - READ_WB_REG_CASE(OFF, 2, REG, VAL); \ - READ_WB_REG_CASE(OFF, 3, REG, VAL); \ - READ_WB_REG_CASE(OFF, 4, REG, VAL); \ - READ_WB_REG_CASE(OFF, 5, REG, VAL); \ - READ_WB_REG_CASE(OFF, 6, REG, VAL); \ - READ_WB_REG_CASE(OFF, 7, REG, VAL); \ - READ_WB_REG_CASE(OFF, 8, REG, VAL); \ - READ_WB_REG_CASE(OFF, 9, REG, VAL); \ - READ_WB_REG_CASE(OFF, 10, REG, VAL); \ - READ_WB_REG_CASE(OFF, 11, REG, VAL); \ - READ_WB_REG_CASE(OFF, 12, REG, VAL); \ - READ_WB_REG_CASE(OFF, 13, REG, VAL); \ - READ_WB_REG_CASE(OFF, 14, REG, VAL); \ - READ_WB_REG_CASE(OFF, 15, REG, VAL) - -#define GEN_WRITE_WB_REG_CASES(OFF, REG, VAL) \ - WRITE_WB_REG_CASE(OFF, 0, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ - WRITE_WB_REG_CASE(OFF, 15, REG, VAL) - -static int getCpuNumBrps(void) { - return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1; -} - -static int getCpuNumWrps(void) { - return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1; -} - -static uint64_t read_wb_reg(int reg, int n) -{ - uint64_t val = 0; - - switch (reg + n) { - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); - GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); - default: - pr_warn("attempt to read from unknown breakpoint register %d\n", n); - } - - return val; -} - -static void write_wb_reg(int reg, int n, uint64_t val) -{ - switch (reg + n) { - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); - GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); - default: - pr_warn("attempt to write to unknown breakpoint register %d\n", n); - } - isb(); -} - -static uint64_t calc_hw_addr(const struct perf_event_attr* attr, bool is_32bit_task) { - uint64_t alignment_mask, hw_addr; - if(!attr) { - return 0; - } - if (is_32bit_task) { - if (attr->bp_len == HW_BREAKPOINT_LEN_8) - alignment_mask = 0x7; - else - alignment_mask = 0x3; - } else { - if (attr->type == HW_BREAKPOINT_X) - alignment_mask = 0x3; - else - alignment_mask = 0x7; - } - hw_addr = attr->bp_addr; - hw_addr &= ~alignment_mask; - return hw_addr; -} - -static bool toggle_bp_registers_directly(const struct perf_event_attr * attr, bool is_32bit_task, int enable) { - int i, max_slots, val_reg, ctrl_reg, cur_slot; - u32 ctrl; - uint64_t hw_addr = calc_hw_addr(attr, is_32bit_task); - if(!attr) { - return false; - } - - switch (attr->bp_type) - { - case HW_BREAKPOINT_R: - case HW_BREAKPOINT_W: - case HW_BREAKPOINT_RW: - ctrl_reg = AARCH64_DBG_REG_WCR; - val_reg = AARCH64_DBG_REG_WVR; - max_slots = getCpuNumWrps(); - break; - case HW_BREAKPOINT_X: - ctrl_reg = AARCH64_DBG_REG_BCR; - val_reg = AARCH64_DBG_REG_BVR; - max_slots = getCpuNumBrps(); - break; - default: - return false; - } - cur_slot = -1; - - for (i = 0; i < max_slots; ++i) { - uint64_t addr = read_wb_reg(val_reg, i); - if(addr == hw_addr) { - cur_slot = i; - break; - } - } - if(cur_slot == -1) { - return false; - } - - ctrl = read_wb_reg(ctrl_reg, cur_slot); - if (enable) - ctrl |= 0x1; - else - ctrl &= ~0x1; - write_wb_reg(ctrl_reg, cur_slot, ctrl); - return true; -} -#endif - diff --git a/code/hide_procfs_dir.h b/code/hide_procfs_dir.h deleted file mode 100644 index e92c15f0..00000000 --- a/code/hide_procfs_dir.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _HIDE_PROCFS_DIR_H_ -#define _HIDE_PROCFS_DIR_H_ - -#include "ver_control.h" - -#include -#include -#include -#include -#include -#include - -static char g_hide_dir_name[256] = {0}; - -static filldir_t old_filldir; - -#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(6,1,0) -static int my_filldir(struct dir_context *buf, - const char *name, - int namelen, - loff_t offset, - u64 ino, - unsigned int d_type) -{ - if (namelen == strlen(g_hide_dir_name) && - !strncmp(name, g_hide_dir_name, namelen)) - { - return 0; - } - return old_filldir(buf, name, namelen, offset, ino, d_type); -} -#else -static bool my_filldir(struct dir_context *ctx, - const char *name, - int namelen, - loff_t offset, - u64 ino, - unsigned int d_type) -{ - if (namelen == strlen(g_hide_dir_name) && - !strncmp(name, g_hide_dir_name, namelen)) - { - return true; - } - return old_filldir(ctx, name, namelen, offset, ino, d_type); -} -#endif - -static int handler_pre(struct kprobe *kp, struct pt_regs *regs) -{ - struct dir_context *ctx = (struct dir_context *)regs->regs[1]; - old_filldir = ctx->actor; - ctx->actor = my_filldir; - return 0; -} - -static struct kprobe kp_hide_procfs_dir = { - .symbol_name = "proc_root_readdir", - .pre_handler = handler_pre, -}; - -static bool start_hide_procfs_dir(const char* hide_dir_name) -{ - //这里原理上可以换成SKRoot的汇编写法。避免kprobe。 - int ret; - strlcpy(g_hide_dir_name, hide_dir_name, sizeof(g_hide_dir_name)); - ret = register_kprobe(&kp_hide_procfs_dir); - if (ret) { - printk_debug("[hide_procfs_dir] register_kprobe failed: %d\n", ret); - return false; - } - printk_debug("[hide_procfs_dir] kprobe installed, hiding \"%s\"\n", g_hide_dir_name); - return true; -} - -static void stop_hide_procfs_dir(void) -{ - unregister_kprobe(&kp_hide_procfs_dir); - printk_debug("[hide_procfs_dir] kprobe removed\n"); -} - -#endif // _HIDE_PROCFS_DIR_H_ diff --git a/code/hwBreakpointProc_module.c b/code/hwBreakpointProc_module.c deleted file mode 100644 index e20edc7d..00000000 --- a/code/hwBreakpointProc_module.c +++ /dev/null @@ -1,591 +0,0 @@ -#include "hwBreakpointProc_module.h" -#include "proc_pid.h" -#include "api_proxy.h" -#include "anti_ptrace_detection.h" - - -#pragma pack(push,1) -struct ioctl_request { - char cmd; /* 1 字节命令 */ - uint64_t param1; /* 参数1 */ - uint64_t param2; /* 参数2 */ - uint64_t param3; /* 参数3 */ - uint64_t buf_size; /* 紧随其后的动态数据长度 */ -}; -#pragma pack(pop) -////////////////////////////////////////////////////////////////// - -static atomic64_t g_hook_pc; - - -static struct mutex g_hwbp_handle_info_mutex; -static cvector g_hwbp_handle_info_arr = NULL; - -static void record_hit_details(struct HWBP_HANDLE_INFO *info, struct pt_regs *regs) { - struct HWBP_HIT_ITEM hit_item = {0}; - if (!info || !regs) { - return; - } - hit_item.task_id = info->task_id; - hit_item.hit_addr = regs->pc; - hit_item.hit_time = ktime_get_real_seconds(); - memcpy(&hit_item.regs_info.regs, regs->regs, sizeof(hit_item.regs_info.regs)); - hit_item.regs_info.sp = regs->sp; - hit_item.regs_info.pc = regs->pc; - hit_item.regs_info.pstate = regs->pstate; - hit_item.regs_info.orig_x0 = regs->orig_x0; - hit_item.regs_info.syscallno = regs->syscallno; - if (info->hit_item_arr) { - if(cvector_length(info->hit_item_arr) < MIN_LEN) { // 最多存放MIN_LEN个 - cvector_pushback(info->hit_item_arr, &hit_item); - } - } -} - -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE -static bool arm64_move_bp_to_next_instruction(struct perf_event *bp, uint64_t next_instruction_addr, struct perf_event_attr *original_attr, struct perf_event_attr * next_instruction_attr) { - int result; - if (!bp || !original_attr || !next_instruction_attr || !next_instruction_addr) { - return false; - } - memcpy(next_instruction_attr, original_attr, sizeof(struct perf_event_attr)); - next_instruction_attr->bp_addr = next_instruction_addr; - next_instruction_attr->bp_len = HW_BREAKPOINT_LEN_4; - next_instruction_attr->bp_type = HW_BREAKPOINT_X; - next_instruction_attr->disabled = 0; - result = x_modify_user_hw_breakpoint(bp, next_instruction_attr); - if(result) { - next_instruction_attr->bp_addr = 0; - return false; - } - return true; -} - -static bool arm64_recovery_bp_to_original(struct perf_event *bp, struct perf_event_attr *original_attr, struct perf_event_attr * next_instruction_attr) { - int result; - if (!bp || !original_attr || !next_instruction_attr) { - return false; - } - result = x_modify_user_hw_breakpoint(bp, original_attr); - if(result) { - return false; - } - next_instruction_attr->bp_addr = 0; - return true; -} -#endif - -static void hwbp_hit_user_info_callback(struct perf_event *bp, - struct perf_sample_data *data, - struct pt_regs *regs, struct HWBP_HANDLE_INFO * hwbp_handle_info) { - hwbp_handle_info->hit_total_count++; - record_hit_details(hwbp_handle_info, regs); -} - -/* - * Handle hitting a HW-breakpoint. - */ -static void hwbp_handler(struct perf_event *bp, - struct perf_sample_data *data, - struct pt_regs *regs) { - citerator iter; - uint64_t hook_pc; - printk_debug(KERN_INFO "hw_breakpoint HIT!!!!! bp:%px, pc:%px, id:%d\n", bp, regs->pc, bp->id); - - hook_pc = atomic64_read(&g_hook_pc); - if(hook_pc) { - regs->pc = hook_pc; - return; - } - - mutex_lock(&g_hwbp_handle_info_mutex); - for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { - struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if (hwbp_handle_info->sample_hbp != bp) { - continue; - } -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE - if(hwbp_handle_info->next_instruction_attr.bp_addr != regs->pc) { - // first hit - bool should_toggle = true; - hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); - if(!hwbp_handle_info->is_32bit_task) { - if(arm64_move_bp_to_next_instruction(bp, regs->pc + 4, &hwbp_handle_info->original_attr, &hwbp_handle_info->next_instruction_attr)) { - should_toggle = false; - } - } - if(should_toggle) { - toggle_bp_registers_directly(&hwbp_handle_info->original_attr, hwbp_handle_info->is_32bit_task, 0); - } - } else { - // second hit - if(!arm64_recovery_bp_to_original(bp, &hwbp_handle_info->original_attr, &hwbp_handle_info->next_instruction_attr)) { - toggle_bp_registers_directly(&hwbp_handle_info->next_instruction_attr, hwbp_handle_info->is_32bit_task, 0); - } - } -#else - hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); - toggle_bp_registers_directly(&hwbp_handle_info->original_attr, hwbp_handle_info->is_32bit_task, 0); -#endif - } - - mutex_unlock(&g_hwbp_handle_info_mutex); -} - - - -static ssize_t OnCmdOpenProcess(struct ioctl_request *hdr, char __user* buf) { - uint64_t pid = hdr->param1, handle = 0; - struct pid * proc_pid_struct = NULL; - printk_debug(KERN_INFO "CMD_OPEN_PROCESS\n"); - - printk_debug(KERN_INFO "pid:%llu,size:%ld\n", pid, sizeof(pid)); - - proc_pid_struct = get_proc_pid_struct(pid); - printk_debug(KERN_INFO "proc_pid_struct *:0x%p\n", (void*)proc_pid_struct); - if (!proc_pid_struct) { - return -EINVAL; - } - handle = (uint64_t)proc_pid_struct; - - printk_debug(KERN_INFO "handle:%llu,size:%ld\n", handle, sizeof(handle)); - if (!!x_copy_to_user((void*)buf, (void*)&handle, sizeof(handle))) { - return -EINVAL; - } - return 0; -} - -static ssize_t OnCmdCloseProcess(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - printk_debug(KERN_INFO "CMD_CLOSE_PROCESS\n"); - printk_debug(KERN_INFO "proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); - release_proc_pid_struct(proc_pid_struct); - return 0; -} - -static ssize_t OnCmdGetCpuNumBrps(struct ioctl_request *hdr, char __user* buf) { - printk_debug(KERN_INFO "CMD_GET_NUM_BRPS\n"); - return getCpuNumBrps(); -} - -static ssize_t OnCmdGetCpuNumWrps(struct ioctl_request *hdr, char __user* buf) { - printk_debug(KERN_INFO "CMD_GET_NUM_WRPS\n"); - return getCpuNumWrps(); -} - -static ssize_t OnCmdInstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { - struct pid * proc_pid_struct = (struct pid *)hdr->param1; - uint64_t proc_virt_addr = hdr->param2; - char hwbp_len = hdr->param3 & 0xFF; - char hwbp_type = (hdr->param3 >> 8) & 0xFF; - - pid_t pid_val; - struct task_struct *task; - struct HWBP_HANDLE_INFO hwbp_handle_info = { 0 }; - printk_debug(KERN_INFO "CMD_INST_PROCESS_HWBP\n"); - printk_debug(KERN_INFO "proc_pid_struct *:%px\n", proc_pid_struct); - printk_debug(KERN_INFO "proc_virt_addr :%px\n", proc_virt_addr); - printk_debug(KERN_INFO "hwbp_len:%zu\n", hwbp_len); - printk_debug(KERN_INFO "hwbp_type:%d\n", hwbp_type); - - pid_val = pid_nr(proc_pid_struct); - printk_debug(KERN_INFO "pid_val:%d\n", pid_val); - - if (!pid_val) { - printk_debug(KERN_INFO "pid_nr failed.\n"); - return -EINVAL; - } - - task = pid_task(proc_pid_struct, PIDTYPE_PID); - if (!task) { - printk_debug(KERN_INFO "get_pid_task failed.\n"); - return -EINVAL; - } - - hwbp_handle_info.task_id = pid_val; - hwbp_handle_info.is_32bit_task = is_compat_thread(task_thread_info(task)); - ptrace_breakpoint_init(&hwbp_handle_info.original_attr); - hwbp_handle_info.original_attr.bp_addr = proc_virt_addr; - hwbp_handle_info.original_attr.bp_len = hwbp_len; - hwbp_handle_info.original_attr.bp_type = hwbp_type; - hwbp_handle_info.original_attr.disabled = 0; - - hwbp_handle_info.sample_hbp = x_register_user_hw_breakpoint(&hwbp_handle_info.original_attr, hwbp_handler, NULL, task); - printk_debug(KERN_INFO "register_user_hw_breakpoint return: %px\n", hwbp_handle_info.sample_hbp); - if (IS_ERR((void __force *)hwbp_handle_info.sample_hbp)) { - int ret = PTR_ERR((void __force *)hwbp_handle_info.sample_hbp); - printk_debug(KERN_INFO "register_user_hw_breakpoint failed: %d\n", ret); - return ret; - } - hwbp_handle_info.hit_item_arr = cvector_create(sizeof(struct HWBP_HIT_ITEM)); - mutex_lock(&g_hwbp_handle_info_mutex); - cvector_pushback(g_hwbp_handle_info_arr, &hwbp_handle_info); - mutex_unlock(&g_hwbp_handle_info_mutex); - - if (x_copy_to_user((void*)buf, &hwbp_handle_info.sample_hbp, sizeof(uint64_t))) { - return -EINVAL; - } - return 0; -} - -static ssize_t OnCmdUninstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { - struct perf_event * sample_hbp = (struct perf_event *)hdr->param1; - citerator iter; - bool found = false; - printk_debug(KERN_INFO "CMD_UNINST_PROCESS_HWBP\n"); - printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); - if(!sample_hbp) { - return -EFAULT; - } - - mutex_lock(&g_hwbp_handle_info_mutex); - for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { - struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if(hwbp_handle_info->sample_hbp == sample_hbp) { - if(hwbp_handle_info->hit_item_arr) { - cvector_destroy(hwbp_handle_info->hit_item_arr); - hwbp_handle_info->hit_item_arr = NULL; - } - cvector_rm(g_hwbp_handle_info_arr, iter); - found = true; - break; - } - } - mutex_unlock(&g_hwbp_handle_info_mutex); - if(found) { - x_unregister_hw_breakpoint(sample_hbp); - } - - return 0; -} - -static ssize_t OnCmdSuspendProcessHwbp(struct ioctl_request *hdr, char __user* buf) { - struct perf_event * sample_hbp = (struct perf_event *)hdr->param1; - struct perf_event_attr new_instruction_attr; - citerator iter; - bool found = false; - printk_debug(KERN_INFO "CMD_SUSPEND_PROCESS_HWBP\n"); - printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); - if(!sample_hbp) { - return -EFAULT; - } - - mutex_lock(&g_hwbp_handle_info_mutex); - for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { - struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if(hwbp_handle_info->sample_hbp == sample_hbp) { - hwbp_handle_info->original_attr.disabled = 1; - memcpy(&new_instruction_attr, &hwbp_handle_info->original_attr, sizeof(struct perf_event_attr)); - found = true; - break; - } - } - mutex_unlock(&g_hwbp_handle_info_mutex); - if(found) { - if(!x_modify_user_hw_breakpoint(sample_hbp, &new_instruction_attr)) { - return 0; - } - } - return -EFAULT; -} - -static ssize_t OnCmdResumeProcessHwbp(struct ioctl_request *hdr, char __user* buf) { - struct perf_event * sample_hbp = (struct perf_event *)hdr->param1; - struct perf_event_attr new_instruction_attr; - citerator iter; - bool found = false; - printk_debug(KERN_INFO "CMD_RESUME_PROCESS_HWBP\n"); - printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); - if(!sample_hbp) { - return -EFAULT; - } - - mutex_lock(&g_hwbp_handle_info_mutex); - for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { - struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if(hwbp_handle_info->sample_hbp == sample_hbp) { - hwbp_handle_info->original_attr.disabled = 0; - memcpy(&new_instruction_attr, &hwbp_handle_info->original_attr, sizeof(struct perf_event_attr)); - found = true; - break; - } - } - mutex_unlock(&g_hwbp_handle_info_mutex); - if(found) { - if(!x_modify_user_hw_breakpoint(sample_hbp, &new_instruction_attr)) { - return 0; - } - } - return -EFAULT; -} - -static ssize_t OnCmdGetHwbpHitCount(struct ioctl_request *hdr, char __user* buf) { - #pragma pack(1) - struct buf_layout { - uint64_t hit_total_count; - uint64_t hit_item_arr_count; - }; - #pragma pack() - struct perf_event *sample_hbp = (struct perf_event *)hdr->param1; - struct buf_layout user_data = {0}; - citerator iter; - printk_debug(KERN_INFO "CMD_GET_HWBP_HIT_COUNT\n"); - printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); - - mutex_lock(&g_hwbp_handle_info_mutex); - for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { - struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if (hwbp_handle_info->sample_hbp == sample_hbp && hwbp_handle_info->hit_item_arr) { - user_data.hit_total_count = hwbp_handle_info->hit_total_count; - user_data.hit_item_arr_count = cvector_length(hwbp_handle_info->hit_item_arr); - break; - } - } - - mutex_unlock(&g_hwbp_handle_info_mutex); - - printk_debug(KERN_INFO "user_data.hit_total_count:%zu\n", user_data.hit_total_count); - if (x_copy_to_user((void*)buf, &user_data, sizeof(user_data))) { - return -EINVAL; - } - return 0; -} - -static ssize_t OnCmdGetHwbpHitDetail(struct ioctl_request *hdr, char __user* buf) { - struct perf_event *sample_hbp = (struct perf_event *)hdr->param1; - size_t size = hdr->buf_size; - ssize_t count = 0; - size_t copy_pos; - size_t end_pos; - - citerator iter; - printk_debug(KERN_INFO "sample_hbp *:%ld\n", sample_hbp); - - copy_pos = (size_t)buf; - end_pos = (size_t)((size_t)buf + size); - - mutex_lock(&g_hwbp_handle_info_mutex); - for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { - struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if (hwbp_handle_info->sample_hbp == sample_hbp && hwbp_handle_info->hit_item_arr) { - citerator child; - for (child = cvector_begin(hwbp_handle_info->hit_item_arr); child != cvector_end(hwbp_handle_info->hit_item_arr); child = cvector_next(hwbp_handle_info->hit_item_arr, child)) { - struct HWBP_HIT_ITEM * hit_item = (struct HWBP_HIT_ITEM *)child; - if (copy_pos >= end_pos) { - break; - } - if (x_copy_to_user((void*)copy_pos, hit_item, sizeof(struct HWBP_HIT_ITEM))) { - break; - } - copy_pos += sizeof(struct HWBP_HIT_ITEM); - count++; - } - break; - } - } - mutex_unlock(&g_hwbp_handle_info_mutex); - return count; -} - -static ssize_t OnCmdSetHookPc(struct ioctl_request *hdr, char __user* buf) { - uint64_t pc = hdr->param1; - printk_debug(KERN_INFO "CMD_SET_HOOK_PC\n"); - printk_debug(KERN_INFO "pc:%px\n", pc); - atomic64_set(&g_hook_pc, pc); - return 0; -} - -static ssize_t OnCmdHideKernelModule(struct ioctl_request *hdr, char __user* buf) { - printk_debug(KERN_INFO "CMD_HIDE_KERNEL_MODULE\n"); - if (g_hwBreakpointProc_devp->is_hidden_module == false) { - g_hwBreakpointProc_devp->is_hidden_module = true; - list_del_init(&__this_module.list); - kobject_del(&THIS_MODULE->mkobj.kobj); - } - return 0; -} - -static inline ssize_t DispatchCommand(struct ioctl_request *hdr, char __user* buf) { - switch (hdr->cmd) { - case CMD_OPEN_PROCESS: - return OnCmdOpenProcess(hdr, buf); - case CMD_CLOSE_PROCESS: - return OnCmdCloseProcess(hdr, buf); - case CMD_GET_NUM_BRPS: - return OnCmdGetCpuNumBrps(hdr, buf); - case CMD_GET_NUM_WRPS: - return OnCmdGetCpuNumWrps(hdr, buf); - case CMD_INST_PROCESS_HWBP: - return OnCmdInstProcessHwbp(hdr, buf); - case CMD_UNINST_PROCESS_HWBP: - return OnCmdUninstProcessHwbp(hdr, buf); - case CMD_SUSPEND_PROCESS_HWBP: - return OnCmdSuspendProcessHwbp(hdr, buf); - case CMD_RESUME_PROCESS_HWBP: - return OnCmdResumeProcessHwbp(hdr, buf); - case CMD_GET_HWBP_HIT_COUNT: - return OnCmdGetHwbpHitCount(hdr, buf); - case CMD_GET_HWBP_HIT_DETAIL: - return OnCmdGetHwbpHitDetail(hdr, buf); - case CMD_SET_HOOK_PC: - return OnCmdSetHookPc(hdr, buf); - case CMD_HIDE_KERNEL_MODULE: - return OnCmdHideKernelModule(hdr, buf); - default: - return -EINVAL; - } - return -EINVAL; -} - -static ssize_t hwBreakpointProc_read(struct file* filp, - char __user* buf, - size_t size, - loff_t* ppos) { - struct ioctl_request hdr = {0}; - size_t header_size = sizeof(hdr); - - if (size < header_size) { - return -EINVAL; - } - - if (x_copy_from_user(&hdr, buf, header_size)) { - return -EFAULT; - } - - if (size < header_size + hdr.buf_size) { - return -EINVAL; - } - - return DispatchCommand(&hdr, buf + header_size); -} - -static void clean_hwbp(void) { - citerator iter; - cvector wait_unregister_bp_arr = cvector_create(sizeof(struct perf_event *)); - if(!wait_unregister_bp_arr || !g_hwbp_handle_info_arr) { - return; - } - mutex_lock(&g_hwbp_handle_info_mutex); - for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { - struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; - if(hwbp_handle_info->sample_hbp) { - cvector_pushback(wait_unregister_bp_arr, &hwbp_handle_info->sample_hbp); - hwbp_handle_info->sample_hbp = NULL; - } - if(hwbp_handle_info->hit_item_arr) { - cvector_destroy(hwbp_handle_info->hit_item_arr); - hwbp_handle_info->hit_item_arr = NULL; - } - } - cvector_destroy(g_hwbp_handle_info_arr); - g_hwbp_handle_info_arr = NULL; - mutex_unlock(&g_hwbp_handle_info_mutex); - - for (iter = cvector_begin(wait_unregister_bp_arr); iter != cvector_end(wait_unregister_bp_arr); iter = cvector_next(wait_unregister_bp_arr, iter)) { - struct perf_event * bp = *(struct perf_event **)iter; - x_unregister_hw_breakpoint(bp); - } - cvector_destroy(wait_unregister_bp_arr); -} - -static int hwBreakpointProc_release(struct inode *inode, struct file *filp) { - clean_hwbp(); - mutex_lock(&g_hwbp_handle_info_mutex); - g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); - mutex_unlock(&g_hwbp_handle_info_mutex); - return 0; -} - -static int hwBreakpointProc_dev_init(void) { -#ifdef CONFIG_KALLSYMS_LOOKUP_NAME - if(!init_kallsyms_lookup()) { - printk(KERN_EMERG "init_kallsyms_lookup failed\n"); - return -EBADF; - } -#endif - g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); - mutex_init(&g_hwbp_handle_info_mutex); - -#ifdef CONFIG_ANTI_PTRACE_DETECTION_MODE - start_anti_ptrace_detection(&g_hwbp_handle_info_mutex, &g_hwbp_handle_info_arr); -#endif - - g_hwBreakpointProc_devp = x_kmalloc(sizeof(struct hwBreakpointProcDev), GFP_KERNEL); - memset(g_hwBreakpointProc_devp, 0, sizeof(struct hwBreakpointProcDev)); - -#ifdef CONFIG_USE_PROC_FILE_NODE - g_hwBreakpointProc_devp->proc_parent = proc_mkdir(CONFIG_PROC_NODE_AUTH_KEY, NULL); - if(g_hwBreakpointProc_devp->proc_parent) { - g_hwBreakpointProc_devp->proc_entry = proc_create(CONFIG_PROC_NODE_AUTH_KEY, S_IRUGO | S_IWUGO, g_hwBreakpointProc_devp->proc_parent, &hwBreakpointProc_proc_ops); - start_hide_procfs_dir(CONFIG_PROC_NODE_AUTH_KEY); - } -#endif - -#ifdef DEBUG_PRINTK - printk(KERN_EMERG "Hello, %s debug\n", CONFIG_PROC_NODE_AUTH_KEY); - //test1(); - //test2(); - //test3(); - //test4(); -#else - printk(KERN_EMERG "Hello\n"); -#endif - return 0; -} - -static void hwBreakpointProc_dev_exit(void) { - -#ifdef CONFIG_ANTI_PTRACE_DETECTION_MODE - stop_anti_ptrace_detection(); -#endif - - clean_hwbp(); - - mutex_destroy(&g_hwbp_handle_info_mutex); - -#ifdef CONFIG_USE_PROC_FILE_NODE - if(g_hwBreakpointProc_devp->proc_entry) { - proc_remove(g_hwBreakpointProc_devp->proc_entry); - g_hwBreakpointProc_devp->proc_entry = NULL; - } - - if(g_hwBreakpointProc_devp->proc_parent) { - proc_remove(g_hwBreakpointProc_devp->proc_parent); - g_hwBreakpointProc_devp->proc_parent = NULL; - } - stop_hide_procfs_dir(); -#endif - kfree(g_hwBreakpointProc_devp); - printk(KERN_EMERG "Goodbye\n"); -} - -int __init init_module(void) { - return hwBreakpointProc_dev_init(); -} - -void __exit cleanup_module(void) { - hwBreakpointProc_dev_exit(); -} - -#ifndef CONFIG_MODULE_GUIDE_ENTRY -//Hook:__cfi_check_fn -unsigned char* __check_(unsigned char* result, void *ptr, void *diag) -{ - printk_debug(KERN_EMERG "my__cfi_check_fn!!!\n"); - return result; -} - -//Hook:__cfi_check_fail -unsigned char * __check_fail_(unsigned char *result) -{ - printk_debug(KERN_EMERG "my__cfi_check_fail!!!\n"); - return result; -} -#endif - -unsigned long __stack_chk_guard; - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Linux"); -MODULE_DESCRIPTION("Linux default module"); - diff --git a/code/hwBreakpointProc_module.h b/code/hwBreakpointProc_module.h deleted file mode 100644 index fe2422c8..00000000 --- a/code/hwBreakpointProc_module.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef _HWBP_PROC_H_ -#define _HWBP_PROC_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include //kmalloc与kfree -#include "ver_control.h" -#include "arm64_register_helper.h" -#include "cvector.h" -#ifdef CONFIG_USE_PROC_FILE_NODE -#include -#include "hide_procfs_dir.h" -#endif -////////////////////////////////////////////////////////////////// - -enum { - CMD_OPEN_PROCESS, // 打开进程 - CMD_CLOSE_PROCESS, // 关闭进程 - CMD_GET_NUM_BRPS, // 获取CPU硬件执行断点支持数量 - CMD_GET_NUM_WRPS, // 获取CPU硬件访问断点支持数量 - CMD_INST_PROCESS_HWBP, // 安装进程硬件断点 - CMD_UNINST_PROCESS_HWBP, // 卸载进程硬件断点 - CMD_SUSPEND_PROCESS_HWBP, // 暂停进程硬件断点 - CMD_RESUME_PROCESS_HWBP, // 恢复进程硬件断点 - CMD_GET_HWBP_HIT_COUNT, // 获取硬件断点命中地址数量 - CMD_GET_HWBP_HIT_DETAIL, // 获取硬件断点命中详细信息 - CMD_SET_HOOK_PC, // 设置无条件Hook跳转 - CMD_HIDE_KERNEL_MODULE, // 隐藏驱动 -}; - -struct hwBreakpointProcDev { -#ifdef CONFIG_USE_PROC_FILE_NODE - struct proc_dir_entry *proc_parent; - struct proc_dir_entry *proc_entry; -#endif - bool is_hidden_module; //是否已经隐藏过驱动列表了 -}; -static struct hwBreakpointProcDev *g_hwBreakpointProc_devp; - -static ssize_t hwBreakpointProc_read(struct file* filp, char __user* buf, size_t size, loff_t* ppos); -static int hwBreakpointProc_release(struct inode *inode, struct file *filp); -static const struct proc_ops hwBreakpointProc_proc_ops = { - .proc_read = hwBreakpointProc_read, - .proc_release = hwBreakpointProc_release, -}; - -#pragma pack(1) -struct my_user_pt_regs { - uint64_t regs[31]; - uint64_t sp; - uint64_t pc; - uint64_t pstate; - uint64_t orig_x0; - uint64_t syscallno; -}; -struct HWBP_HIT_ITEM { - uint64_t task_id; - uint64_t hit_addr; - uint64_t hit_time; - struct my_user_pt_regs regs_info; -}; -#pragma pack() - -struct HWBP_HANDLE_INFO { - uint64_t task_id; - struct perf_event * sample_hbp; - struct perf_event_attr original_attr; - bool is_32bit_task; -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE - struct perf_event_attr next_instruction_attr; -#endif - size_t hit_total_count; - cvector hit_item_arr; -}; - -#endif /* _HWBP_PROC_H_ */ \ No newline at end of file diff --git a/code/hwbp_proc.h b/code/hwbp_proc.h deleted file mode 100644 index 88801c5f..00000000 --- a/code/hwbp_proc.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _HWBP_PROC_H_ -#define _HWBP_PROC_H_ -#include "ver_control.h" - -#pragma pack(1) -struct my_user_pt_regs { - uint64_t regs[31]; - uint64_t sp; - uint64_t pc; - uint64_t pstate; - uint64_t orig_x0; - uint64_t syscallno; -}; -struct HWBP_HIT_ITEM { - uint64_t task_id; - uint64_t hit_addr; - uint64_t hit_time; - struct my_user_pt_regs regs_info; -}; -#pragma pack() - -struct HWBP_HANDLE_INFO { - uint64_t task_id; - struct perf_event * sample_hbp; - struct perf_event_attr original_attr; - bool is_32bit_task; -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE - struct perf_event_attr next_instruction_attr; -#endif - size_t hit_total_count; - cvector hit_item_arr; -}; - -#endif \ No newline at end of file diff --git a/code/kallsyms_lookup_api.h b/code/kallsyms_lookup_api.h deleted file mode 100644 index f3592579..00000000 --- a/code/kallsyms_lookup_api.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _KALLSYMS_LOOKUP_API_H_ -#define _KALLSYMS_LOOKUP_API_H_ -#include "ver_control.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned long (*kallsyms_lookup_name_sym)(const char *name); -static struct perf_event* (*register_user_hw_breakpoint_sym)(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context, struct task_struct *tsk); -static void (*unregister_hw_breakpoint_sym)(struct perf_event *bp); -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE -static int (*modify_user_hw_breakpoint_sym)(struct perf_event *bp, struct perf_event_attr *attr); -#endif - -static int _kallsyms_lookup_kprobe(struct kprobe *p, struct pt_regs *regs) { return 0; } -static unsigned long get_kallsyms_func(void) { - int ret; - unsigned long addr = 0; - struct kprobe probe = {0}; - probe.pre_handler = _kallsyms_lookup_kprobe; - probe.symbol_name = "kallsyms_lookup_name"; - ret = register_kprobe(&probe); - if (ret == 0) { - addr = (unsigned long)probe.addr; - printk_debug(KERN_EMERG "get_kallsyms_func(kallsyms_lookup_name):%px\n", addr); - unregister_kprobe(&probe); - } - return addr; -} - -static unsigned long generic_kallsyms_lookup_name(const char *name) { - if (!kallsyms_lookup_name_sym) { - kallsyms_lookup_name_sym = (void *)get_kallsyms_func(); - printk_debug(KERN_EMERG "get_kallsyms_func:%px\n", kallsyms_lookup_name_sym); - if(!kallsyms_lookup_name_sym) - return 0; - } - return kallsyms_lookup_name_sym(name); -} - -static bool init_kallsyms_lookup(void) { - register_user_hw_breakpoint_sym = (void *)generic_kallsyms_lookup_name("register_user_hw_breakpoint"); - printk_debug(KERN_EMERG "register_user_hw_breakpoint_sym:%px\n", register_user_hw_breakpoint_sym); - if(!register_user_hw_breakpoint_sym) { return false; } - - unregister_hw_breakpoint_sym = (void *)generic_kallsyms_lookup_name("unregister_hw_breakpoint"); - printk_debug(KERN_EMERG "unregister_hw_breakpoint_sym:%px\n", unregister_hw_breakpoint_sym); - if(!unregister_hw_breakpoint_sym) { return false; } - -#ifdef CONFIG_MODIFY_HIT_NEXT_MODE - modify_user_hw_breakpoint_sym = (void *)generic_kallsyms_lookup_name("modify_user_hw_breakpoint"); - printk_debug(KERN_EMERG "modify_user_hw_breakpoint_sym:%px\n", modify_user_hw_breakpoint_sym); - if(!modify_user_hw_breakpoint_sym) { return false; } -#endif - - return true; -} -#endif diff --git a/code/ver_control.h b/code/ver_control.h deleted file mode 100644 index 474e9163..00000000 --- a/code/ver_control.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef VER_CONTROL_H_ -#define VER_CONTROL_H_ -#include - -// 独立内核模块入口模式 -#define CONFIG_MODULE_GUIDE_ENTRY - -// 生成proc用户层交互节点文件 -#define CONFIG_USE_PROC_FILE_NODE -// 隐蔽通信密钥 -#define CONFIG_PROC_NODE_AUTH_KEY "dce3771681d4c7a143d5d06b7d32548e" - -// 调试打印模式 -//#define CONFIG_DEBUG_PRINTK - -// 动态寻址模式 -#define CONFIG_KALLSYMS_LOOKUP_NAME - -// 精准命中记录模式 -#define CONFIG_MODIFY_HIT_NEXT_MODE - -// 反PTRACE侦测模式 -#define CONFIG_ANTI_PTRACE_DETECTION_MODE - -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif -#ifndef MY_LINUX_VERSION_CODE -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,10,0) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,10,84) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,18,71) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,18,140) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,21) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,78) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,153) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,192) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,9,112) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,9,186) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,83) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,117) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,141) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,19,81) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,19,113) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,4,61) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,10,43) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,15,41) -//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,1,75) -#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,6,30) -#endif - -#ifdef CONFIG_DEBUG_PRINTK -#define printk_debug printk -#else -static inline void printk_debug(char *fmt, ...) {} -#endif - -#endif /* VER_CONTROL_H_ */ From c07d026fb03726fa4bcec048318e0d75f283ad3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 3 Feb 2026 10:44:22 +0800 Subject: [PATCH 30/35] Create Makefile --- code/Makefile | 1 + 1 file changed, 1 insertion(+) create mode 100644 code/Makefile diff --git a/code/Makefile b/code/Makefile new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/code/Makefile @@ -0,0 +1 @@ + From 8d3f836ae4c4444c0d5eb9e0351d4dfb5d90be33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 3 Feb 2026 10:45:39 +0800 Subject: [PATCH 31/35] Add files via upload --- code/Makefile | 2 +- code/anti_ptrace_detection.h | 146 +++++++ code/api_proxy.h | 43 ++ code/arm64_register_helper.h | 160 ++++++++ code/cvector.h | 361 +++++++++++++++++ code/hide_procfs_dir.h | 83 ++++ code/hwBreakpointProc_module.c | 591 +++++++++++++++++++++++++++ code/hwBreakpointProc_module.h | 93 +++++ code/hwbp_proc.c | 705 +++++++++++++++++++++++++++++++++ code/hwbp_proc.h | 34 ++ code/kallsyms_lookup_api.h | 64 +++ code/proc_pid.h | 16 + code/ver_control.h | 57 +++ 13 files changed, 2354 insertions(+), 1 deletion(-) create mode 100644 code/anti_ptrace_detection.h create mode 100644 code/api_proxy.h create mode 100644 code/arm64_register_helper.h create mode 100644 code/cvector.h create mode 100644 code/hide_procfs_dir.h create mode 100644 code/hwBreakpointProc_module.c create mode 100644 code/hwBreakpointProc_module.h create mode 100644 code/hwbp_proc.c create mode 100644 code/hwbp_proc.h create mode 100644 code/kallsyms_lookup_api.h create mode 100644 code/proc_pid.h create mode 100644 code/ver_control.h diff --git a/code/Makefile b/code/Makefile index 8b137891..20d191c4 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1 +1 @@ - +obj-m += hwBreakpointProc_module.o diff --git a/code/anti_ptrace_detection.h b/code/anti_ptrace_detection.h new file mode 100644 index 00000000..d3158657 --- /dev/null +++ b/code/anti_ptrace_detection.h @@ -0,0 +1,146 @@ +#ifndef _ANTI_PTRACE_DETECTION_H_ +#define _ANTI_PTRACE_DETECTION_H_ +#include +#include +#include +#include +#include +#include + +#define PTRACE_GETREGSET 0x4204 +#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ +#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ + +struct hook_ptrace_data { + struct iovec iov; +}; + +static struct mutex *g_p_hwbp_handle_info_mutex = NULL; +static cvector *g_p_hwbp_handle_info_arr = NULL; + +static bool is_my_hwbp_handle_addr(size_t addr) { + citerator iter; + bool found = false; + if(addr == 0) { + return found; + } + mutex_lock(g_p_hwbp_handle_info_mutex); + for (iter = cvector_begin(*g_p_hwbp_handle_info_arr); iter != cvector_end(*g_p_hwbp_handle_info_arr); iter = cvector_next(*g_p_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->original_attr.bp_addr == addr) { + found = true; + break; + } + } + mutex_unlock(g_p_hwbp_handle_info_mutex); + return found; +} + +static int entry_ptrace_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { + long request = regs->regs[1]; + unsigned long addr = (unsigned long)regs->regs[2]; + struct hook_ptrace_data *data = (struct hook_ptrace_data *)ri->data; + data->iov.iov_base = 0; + data->iov.iov_len = 0; + printk_debug(KERN_INFO "entry_ptrace_handler called with request: %lx, addr: %lx\n", request, addr); + if (request == PTRACE_GETREGSET && (addr == NT_ARM_HW_WATCH || addr == NT_ARM_HW_BREAK)) { + unsigned long iov_user_ptr = regs->regs[3]; + printk_debug(KERN_INFO "entry_ptrace_handler called with request: %lx, addr: %lx, iov_user_ptr: %lx\n", request, addr, iov_user_ptr); + if(!iov_user_ptr) { + return 0; + } + if (x_copy_from_user(&data->iov, (struct iovec __user *)iov_user_ptr, sizeof(struct iovec)) != 0) { + printk_debug(KERN_INFO "Failed to copy iovec from user space\n"); + return 0; + } + printk_debug(KERN_INFO "entry_ptrace_handler iov_base: %lx, iov_len %ld\n", data->iov.iov_base, data->iov.iov_len); + } + return 0; +} +static int ret_ptrace_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { + unsigned long retval = regs_return_value(regs); + struct hook_ptrace_data *data = (struct hook_ptrace_data *)ri->data; + struct user_hwdebug_state old_hw_state; + struct user_hwdebug_state new_hw_state; + size_t copy_size; + int i = 0, y = 0; + printk_debug(KERN_INFO "ret_ptrace_handler called with retval: %lx, iov_base: %lx, iov_len %ld\n", retval, data->iov.iov_base, data->iov.iov_len); + if (!data->iov.iov_base || !data->iov.iov_len) { + return 0; + } + + // Check if the buffer of the IoV is readable and writable + if (!access_ok((void __user *)data->iov.iov_base, data->iov.iov_len)) { + printk_debug(KERN_INFO "User buffer is not accessible\n"); + return 0; + } + copy_size = min(data->iov.iov_len, sizeof(struct user_hwdebug_state)); + if (x_copy_from_user(&old_hw_state, (void __user *)data->iov.iov_base, copy_size) != 0) { + printk_debug(KERN_INFO "Failed to copy old_hw_state from user buffer\n"); + return 0; + } + // After x_copy_from_user + printk_debug(KERN_INFO "Original old_hw_state.dbg_info: %u, size %ld\n", old_hw_state.dbg_info, copy_size); + for (i = 0; i < 16; i++) { + printk_debug(KERN_INFO "Reg %d: addr=%llu, ctrl=%u\n", i, old_hw_state.dbg_regs[i].addr, old_hw_state.dbg_regs[i].ctrl); + } + // Clear the dbd_regs array + memcpy(&new_hw_state, &old_hw_state, sizeof(new_hw_state)); + memset(new_hw_state.dbg_regs, 0x00, sizeof(new_hw_state.dbg_regs)); + + printk_debug(KERN_INFO "After memset:\n"); + for (i = 0; i < sizeof(old_hw_state.dbg_regs) / sizeof(old_hw_state.dbg_regs[0]); i++) { + if(!is_my_hwbp_handle_addr(old_hw_state.dbg_regs[i].addr)) { + memcpy(&new_hw_state.dbg_regs[y++], &old_hw_state.dbg_regs[i], sizeof(old_hw_state.dbg_regs[i])); + } + } + + printk_debug(KERN_INFO "After memset:\n"); + for (i = 0; i < 16; i++) { + printk_debug(KERN_INFO "Reg %d: addr=%llu, ctrl=%u\n", i, new_hw_state.dbg_regs[i].addr, new_hw_state.dbg_regs[i].ctrl); + } + + // Copy the modified hw_ste back to the buffer in user space + if (x_copy_to_user((void __user *)data->iov.iov_base, &new_hw_state, copy_size) != 0) { + printk_debug(KERN_INFO "Failed to copy modified new_hw_state back to user buffer\n"); + } else { + printk_debug(KERN_INFO "Successfully cleared dbg_regs in user_hwdebug_state\n"); + } + return 0; +} + + +static struct kretprobe kretp_ptrace = { + .kp.symbol_name = "arch_ptrace", + .data_size = sizeof(struct hook_ptrace_data), + .entry_handler = entry_ptrace_handler, + .handler = ret_ptrace_handler, + .maxactive = 20, +}; + +static bool start_anti_ptrace_detection(struct mutex *p_hwbp_handle_info_mutex, cvector *p_hwbp_handle_info_arr) { + int ret = 0; + g_p_hwbp_handle_info_mutex = p_hwbp_handle_info_mutex; + g_p_hwbp_handle_info_arr = p_hwbp_handle_info_arr; + if(!g_p_hwbp_handle_info_mutex || !g_p_hwbp_handle_info_arr) { + printk_debug(KERN_INFO "start_anti_ptrace_detection param error\n"); + return false; + } + ret = register_kretprobe(&kretp_ptrace); + if (ret < 0) { + printk_debug(KERN_INFO "register_kretprobe failed, returned %d\n", ret); + return false; + } + printk_debug(KERN_INFO "kretprobe at %s registered, addr: %lx\n", kretp_ptrace.kp.symbol_name, kretp_ptrace.kp.addr); + return true; +} + + +static void stop_anti_ptrace_detection(void) { + if(kretp_ptrace.kp.addr) { + unregister_kretprobe(&kretp_ptrace); + printk_debug(KERN_INFO "kretprobe unregistered\n"); + } +} + +#endif diff --git a/code/api_proxy.h b/code/api_proxy.h new file mode 100644 index 00000000..9349e957 --- /dev/null +++ b/code/api_proxy.h @@ -0,0 +1,43 @@ +#ifndef _API_PROXY_H_ +#define _API_PROXY_H_ +#include "ver_control.h" + +#ifdef CONFIG_KALLSYMS_LOOKUP_NAME +#include "kallsyms_lookup_api.h" +static struct perf_event* x_register_user_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context, struct task_struct *tsk) { + return register_user_hw_breakpoint_sym(attr, triggered, context, tsk); +} + +static void x_unregister_hw_breakpoint(struct perf_event *bp) { + unregister_hw_breakpoint_sym(bp); +} + +static int x_modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) { + return modify_user_hw_breakpoint_sym(bp, attr); +} +#else +static struct perf_event* x_register_user_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context, struct task_struct *tsk) { + return register_user_hw_breakpoint(attr, triggered, context, tsk); +} + +static void x_unregister_hw_breakpoint(struct perf_event *bp) { + unregister_hw_breakpoint(bp); +} + +static int x_modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) { + return modify_user_hw_breakpoint(bp, attr); +} +#endif + +static void * x_kmalloc(size_t size, gfp_t flags) { + return __kmalloc(size, flags); +} + +static unsigned long x_copy_from_user(void *to, const void __user *from, unsigned long n) { + return __arch_copy_from_user(to, from, n); +} + +static unsigned long x_copy_to_user(void __user *to, const void *from, unsigned long n) { + return __arch_copy_to_user(to, from, n); +} +#endif diff --git a/code/arm64_register_helper.h b/code/arm64_register_helper.h new file mode 100644 index 00000000..2a135174 --- /dev/null +++ b/code/arm64_register_helper.h @@ -0,0 +1,160 @@ +# ifndef __ARM64_REGISTER_HELPER_H__ +# define __ARM64_REGISTER_HELPER_H__ +#include +#include +#include +#include +#include + +#define READ_WB_REG_CASE(OFF, N, REG, VAL) \ + case (OFF + N): \ + AARCH64_DBG_READ(N, REG, VAL); \ + break + +#define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ + case (OFF + N): \ + AARCH64_DBG_WRITE(N, REG, VAL); \ + break + +#define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \ + READ_WB_REG_CASE(OFF, 0, REG, VAL); \ + READ_WB_REG_CASE(OFF, 1, REG, VAL); \ + READ_WB_REG_CASE(OFF, 2, REG, VAL); \ + READ_WB_REG_CASE(OFF, 3, REG, VAL); \ + READ_WB_REG_CASE(OFF, 4, REG, VAL); \ + READ_WB_REG_CASE(OFF, 5, REG, VAL); \ + READ_WB_REG_CASE(OFF, 6, REG, VAL); \ + READ_WB_REG_CASE(OFF, 7, REG, VAL); \ + READ_WB_REG_CASE(OFF, 8, REG, VAL); \ + READ_WB_REG_CASE(OFF, 9, REG, VAL); \ + READ_WB_REG_CASE(OFF, 10, REG, VAL); \ + READ_WB_REG_CASE(OFF, 11, REG, VAL); \ + READ_WB_REG_CASE(OFF, 12, REG, VAL); \ + READ_WB_REG_CASE(OFF, 13, REG, VAL); \ + READ_WB_REG_CASE(OFF, 14, REG, VAL); \ + READ_WB_REG_CASE(OFF, 15, REG, VAL) + +#define GEN_WRITE_WB_REG_CASES(OFF, REG, VAL) \ + WRITE_WB_REG_CASE(OFF, 0, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ + WRITE_WB_REG_CASE(OFF, 15, REG, VAL) + +static int getCpuNumBrps(void) { + return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1; +} + +static int getCpuNumWrps(void) { + return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1; +} + +static uint64_t read_wb_reg(int reg, int n) +{ + uint64_t val = 0; + + switch (reg + n) { + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); + GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); + default: + pr_warn("attempt to read from unknown breakpoint register %d\n", n); + } + + return val; +} + +static void write_wb_reg(int reg, int n, uint64_t val) +{ + switch (reg + n) { + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); + GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); + default: + pr_warn("attempt to write to unknown breakpoint register %d\n", n); + } + isb(); +} + +static uint64_t calc_hw_addr(const struct perf_event_attr* attr, bool is_32bit_task) { + uint64_t alignment_mask, hw_addr; + if(!attr) { + return 0; + } + if (is_32bit_task) { + if (attr->bp_len == HW_BREAKPOINT_LEN_8) + alignment_mask = 0x7; + else + alignment_mask = 0x3; + } else { + if (attr->type == HW_BREAKPOINT_X) + alignment_mask = 0x3; + else + alignment_mask = 0x7; + } + hw_addr = attr->bp_addr; + hw_addr &= ~alignment_mask; + return hw_addr; +} + +static bool toggle_bp_registers_directly(const struct perf_event_attr * attr, bool is_32bit_task, int enable) { + int i, max_slots, val_reg, ctrl_reg, cur_slot; + u32 ctrl; + uint64_t hw_addr = calc_hw_addr(attr, is_32bit_task); + if(!attr) { + return false; + } + + switch (attr->bp_type) + { + case HW_BREAKPOINT_R: + case HW_BREAKPOINT_W: + case HW_BREAKPOINT_RW: + ctrl_reg = AARCH64_DBG_REG_WCR; + val_reg = AARCH64_DBG_REG_WVR; + max_slots = getCpuNumWrps(); + break; + case HW_BREAKPOINT_X: + ctrl_reg = AARCH64_DBG_REG_BCR; + val_reg = AARCH64_DBG_REG_BVR; + max_slots = getCpuNumBrps(); + break; + default: + return false; + } + cur_slot = -1; + + for (i = 0; i < max_slots; ++i) { + uint64_t addr = read_wb_reg(val_reg, i); + if(addr == hw_addr) { + cur_slot = i; + break; + } + } + if(cur_slot == -1) { + return false; + } + + ctrl = read_wb_reg(ctrl_reg, cur_slot); + if (enable) + ctrl |= 0x1; + else + ctrl &= ~0x1; + write_wb_reg(ctrl_reg, cur_slot, ctrl); + return true; +} +#endif + diff --git a/code/cvector.h b/code/cvector.h new file mode 100644 index 00000000..ef5d4eb3 --- /dev/null +++ b/code/cvector.h @@ -0,0 +1,361 @@ +# ifndef __CVECTOR_H__ +# define __CVECTOR_H__ + +#include +# define MIN_LEN 1024 +# define CVEFAILED -1 +# define CVESUCCESS 0 +# define CVEPUSHBACK 1 +# define CVEPOPBACK 2 +# define CVEINSERT 3 +# define CVERM 4 +# define EXPANED_VAL 1 +# define REDUSED_VAL 2 + +typedef void *citerator; +typedef struct _cvector *cvector; + +# ifdef __cplusplus +extern "C" { +# endif + + cvector cvector_create(const size_t size ); + void cvector_destroy (const cvector cv ); + size_t cvector_length (const cvector cv ); + int cvector_pushback (const cvector cv, void *memb ); + int cvector_popback (const cvector cv, void *memb ); + size_t cvector_iter_at (const cvector cv, citerator iter ); + int cvector_iter_val (const cvector cv, citerator iter, void *memb); + citerator cvector_begin (const cvector cv ); + citerator cvector_end (const cvector cv ); + citerator cvector_next (const cvector cv, citerator iter ); + int cvector_val_at (const cvector cv, size_t index, void *memb ); + int cvector_insert (const cvector cv, citerator iter, void *memb); + int cvector_insert_at(const cvector cv, size_t index, void *memb ); + int cvector_rm (const cvector cv, citerator iter ); + int cvector_rm_at (const cvector cv, size_t index ); + + /* for test */ + void cv_info (const cvector cv ); + void cv_print (const cvector cv ); + +# ifdef __cplusplus +} +# endif + +#endif /* EOF file cvector.h */ + + + +// #include "cvector.h" +// +// int main() +// { +// int i = 1; +// cvector cv = cvector_create(sizeof(int)); +// cvector_pushback(cv, &i); +// cvector_pushback(cv, &i); +// cvector_pushback(cv, &i); +// cvector_pushback(cv, &i); +// cv_print(cv); +// cvector_destroy(cv); +// return 0; +// } + + + + +#include "api_proxy.h" +#include +#include +#include + +#ifndef __gnu_linux__ +//#define __func__ "unknown" +//#define inline __forceinline +#endif + +# define CWARNING_ITER(cv, iter, file, func, line) \ + do {\ + if ((cvector_begin(cv) > iter) || (cvector_end(cv) <= iter)) {\ + printk(KERN_INFO "var(" #iter ") warng out of range, "\ + "at file:%s func:%s line:%d!!\n", file, func, line);\ + return CVEFAILED;\ + }\ + } while (0) + +void *vmalloc_realloc(void *old_ptr, size_t old_size, size_t new_size) { + void *new_ptr; + if (!old_ptr) { + return vmalloc(new_size); + } + if (new_size == 0) { + vfree(old_ptr); + return NULL; + } + new_ptr = vmalloc(new_size); + if (!new_ptr) { + pr_err("vmalloc realloc failed for size: %zu\n", new_size); + return NULL; + } + memcpy(new_ptr, old_ptr, min(old_size, new_size)); + vfree(old_ptr); + return new_ptr; +} + +struct _cvector +{ + void *cv_pdata; + size_t cv_len, cv_tot_len, cv_size; +}; + + +cvector cvector_create(const size_t size) +{ + cvector cv = (cvector)x_kmalloc(sizeof (struct _cvector), GFP_KERNEL); + + if (!cv) return NULL; + + cv->cv_pdata = vmalloc(MIN_LEN * size); + + if (!cv->cv_pdata) + { + kfree(cv); + return NULL; + } + + cv->cv_size = size; + cv->cv_tot_len = MIN_LEN; + cv->cv_len = 0; + + return cv; +} + +void cvector_destroy(const cvector cv) +{ + vfree(cv->cv_pdata); + kfree(cv); + return; +} + +size_t cvector_length(const cvector cv) +{ + return cv->cv_len; +} + +int cvector_pushback(const cvector cv, void *memb) +{ + if (cv->cv_len >= cv->cv_tot_len) + { + void *pd_sav = cv->cv_pdata; + size_t old_size = cv->cv_tot_len * cv->cv_size; + cv->cv_tot_len <<= EXPANED_VAL; + cv->cv_pdata = vmalloc_realloc(cv->cv_pdata, old_size, cv->cv_tot_len * cv->cv_size); + + if (!cv->cv_pdata) + { + cv->cv_pdata = pd_sav; + cv->cv_tot_len >>= EXPANED_VAL; + return CVEPUSHBACK; + } + } + + memcpy((char *)cv->cv_pdata + cv->cv_len * cv->cv_size, memb, cv->cv_size); + cv->cv_len++; + + return CVESUCCESS; +} + +int cvector_popback(const cvector cv, void *memb) +{ + if (cv->cv_len <= 0) return CVEPOPBACK; + + cv->cv_len--; + memcpy(memb, (char *)cv->cv_pdata + cv->cv_len * cv->cv_size, cv->cv_size); + + if ((cv->cv_tot_len >= (MIN_LEN << REDUSED_VAL)) + && (cv->cv_len <= (cv->cv_tot_len >> REDUSED_VAL))) + { + void *pd_sav = cv->cv_pdata; + size_t old_size = cv->cv_tot_len * cv->cv_size; + cv->cv_tot_len >>= EXPANED_VAL; + cv->cv_pdata = vmalloc_realloc(cv->cv_pdata, old_size, cv->cv_tot_len * cv->cv_size); + + if (!cv->cv_pdata) + { + cv->cv_tot_len <<= EXPANED_VAL; + cv->cv_pdata = pd_sav; + return CVEPOPBACK; + } + } + + return CVESUCCESS; +} + +size_t cvector_iter_at(const cvector cv, citerator iter) +{ + CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__); + return ((char *)iter - (char *)cv->cv_pdata) / cv->cv_size; +} + +int cvector_iter_val(const cvector cv, citerator iter, void *memb) +{ + CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__); + memcpy(memb, iter, cv->cv_size); + return 0; +} + +citerator cvector_begin(const cvector cv) +{ + return cv->cv_pdata; +} + +citerator cvector_end(const cvector cv) +{ + return (char *)cv->cv_pdata + (cv->cv_size * cv->cv_len); +} + +static inline void cvmemove_foreward(const cvector cv, void *from, void *to) +{ + size_t size = cv->cv_size; + char *p; + for (p = (char *)to; p >= (char *)from; p -= size) memcpy(p + size, p, size); + return; +} + +static inline void cvmemove_backward(const cvector cv, void *from, void *to) +{ + memcpy(from, (char *)from + cv->cv_size, (char *)to - (char *)from); + return; +} + +int cvector_insert(const cvector cv, citerator iter, void *memb) +{ + CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__); + + if (cv->cv_len >= cv->cv_tot_len) + { + void *pd_sav = cv->cv_pdata; + size_t old_size = cv->cv_tot_len * cv->cv_size; + cv->cv_tot_len <<= EXPANED_VAL; + cv->cv_pdata = vmalloc_realloc(cv->cv_pdata, old_size, cv->cv_tot_len * cv->cv_size); + + if (!cv->cv_pdata) + { + cv->cv_pdata = pd_sav; + cv->cv_tot_len >>= EXPANED_VAL; + return CVEINSERT; + } + } + + cvmemove_foreward(cv, iter, (char *)cv->cv_pdata + cv->cv_len * cv->cv_size); + memcpy(iter, memb, cv->cv_size); + cv->cv_len++; + + return CVESUCCESS; +} + +int cvector_insert_at(const cvector cv, size_t index, void *memb) +{ + citerator iter; + + if (index >= cv->cv_tot_len) + { + // 保存旧大小 + size_t old_size = cv->cv_tot_len * cv->cv_size; + cv->cv_len = index + 1; + while (cv->cv_len >= cv->cv_tot_len) cv->cv_tot_len <<= EXPANED_VAL; + cv->cv_pdata = vmalloc_realloc(cv->cv_pdata, old_size, cv->cv_tot_len * cv->cv_size); + iter = (char *)cv->cv_pdata + cv->cv_size * index; + memcpy(iter, memb, cv->cv_size); + } + else + { + iter = (char *)cv->cv_pdata + cv->cv_size * index; + cvector_insert(cv, iter, memb); + } + + return 0; +} + +citerator cvector_next(const cvector cv, citerator iter) +{ + return (char *)iter + cv->cv_size; +} + +int cvector_val(const cvector cv, citerator iter, void *memb) +{ + memcpy(memb, iter, cv->cv_size); + return 0; +} + +int cvector_val_at(const cvector cv, size_t index, void *memb) +{ + memcpy(memb, (char *)cv->cv_pdata + index * cv->cv_size, cv->cv_size); + return 0; +} + +int cvector_rm(const cvector cv, citerator iter) +{ + citerator from; + citerator end; + CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__); + from = iter; + end = cvector_end(cv); + memcpy(from, (char *)from + cv->cv_size, (char *)end - (char *)from); + cv->cv_len--; + + if ((cv->cv_tot_len >= (MIN_LEN << REDUSED_VAL)) + && (cv->cv_len <= (cv->cv_tot_len >> REDUSED_VAL))) + { + void *pd_sav = cv->cv_pdata; + size_t old_size = cv->cv_tot_len * cv->cv_size; + cv->cv_tot_len >>= EXPANED_VAL; + cv->cv_pdata = vmalloc_realloc(cv->cv_pdata, old_size, cv->cv_tot_len * cv->cv_size); + + if (!cv->cv_pdata) + { + cv->cv_tot_len <<= EXPANED_VAL; + cv->cv_pdata = pd_sav; + return CVERM; + } + } + + return CVESUCCESS; +} + +int cvector_rm_at(const cvector cv, size_t index) +{ + citerator iter; + iter = (char *)cv->cv_pdata + cv->cv_size * index; + CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__); + return cvector_rm(cv, iter); +} + +void cv_info(const cvector cv) +{ + printk("\n\ntot :%s : %zu\n", __func__, cv->cv_tot_len); + printk("len :%s : %zu\n", __func__, cv->cv_len); + printk("size:%s : %zu\n\n", __func__, cv->cv_size); + return; +} + +void cv_print(const cvector cv) +{ + int num; + citerator iter; + + if (cvector_length(cv) == 0) + printk(KERN_INFO "file:%s func:%s line:%d error, null length cvector!!\n", __FILE__, __func__, __LINE__); + + for (iter = cvector_begin(cv); + iter != cvector_end(cv); + iter = cvector_next(cv, iter)) + { + cvector_iter_val(cv, iter, &num); + printk("var:%d at:%zu\n", num, cvector_iter_at(cv, iter)); + } + + + return; +} diff --git a/code/hide_procfs_dir.h b/code/hide_procfs_dir.h new file mode 100644 index 00000000..8fc38a57 --- /dev/null +++ b/code/hide_procfs_dir.h @@ -0,0 +1,83 @@ +#ifndef _HIDE_PROCFS_DIR_H_ +#define _HIDE_PROCFS_DIR_H_ + +#include "ver_control.h" + +#include +#include +#include +#include +#include +#include + +static char g_hide_dir_name[256] = {0}; + +static filldir_t old_filldir; + +#if MY_LINUX_VERSION_CODE < KERNEL_VERSION(6,1,0) +static int my_filldir(struct dir_context *buf, + const char *name, + int namelen, + loff_t offset, + u64 ino, + unsigned int d_type) +{ + if (namelen == strlen(g_hide_dir_name) && + !strncmp(name, g_hide_dir_name, namelen)) + { + return 0; + } + return old_filldir(buf, name, namelen, offset, ino, d_type); +} +#else +static bool my_filldir(struct dir_context *ctx, + const char *name, + int namelen, + loff_t offset, + u64 ino, + unsigned int d_type) +{ + if (namelen == strlen(g_hide_dir_name) && + !strncmp(name, g_hide_dir_name, namelen)) + { + return true; + } + return old_filldir(ctx, name, namelen, offset, ino, d_type); +} +#endif + +static int handler_pre(struct kprobe *kp, struct pt_regs *regs) +{ + struct dir_context *ctx = (struct dir_context *)regs->regs[1]; + old_filldir = ctx->actor; + // 如果编译器要求显式转换 + ctx->actor = (filldir_t)my_filldir; + return 0; +} + +static struct kprobe kp_hide_procfs_dir = { + .symbol_name = "proc_root_readdir", + .pre_handler = handler_pre, +}; + +static bool start_hide_procfs_dir(const char* hide_dir_name) +{ + //这里原理上可以换成SKRoot的汇编写法。避免kprobe。 + int ret; + strlcpy(g_hide_dir_name, hide_dir_name, sizeof(g_hide_dir_name)); + ret = register_kprobe(&kp_hide_procfs_dir); + if (ret) { + printk_debug("[hide_procfs_dir] register_kprobe failed: %d\n", ret); + return false; + } + printk_debug("[hide_procfs_dir] kprobe installed, hiding \"%s\"\n", g_hide_dir_name); + return true; +} + +static void stop_hide_procfs_dir(void) +{ + unregister_kprobe(&kp_hide_procfs_dir); + printk_debug("[hide_procfs_dir] kprobe removed\n"); +} + +#endif // _HIDE_PROCFS_DIR_H_ diff --git a/code/hwBreakpointProc_module.c b/code/hwBreakpointProc_module.c new file mode 100644 index 00000000..e20edc7d --- /dev/null +++ b/code/hwBreakpointProc_module.c @@ -0,0 +1,591 @@ +#include "hwBreakpointProc_module.h" +#include "proc_pid.h" +#include "api_proxy.h" +#include "anti_ptrace_detection.h" + + +#pragma pack(push,1) +struct ioctl_request { + char cmd; /* 1 字节命令 */ + uint64_t param1; /* 参数1 */ + uint64_t param2; /* 参数2 */ + uint64_t param3; /* 参数3 */ + uint64_t buf_size; /* 紧随其后的动态数据长度 */ +}; +#pragma pack(pop) +////////////////////////////////////////////////////////////////// + +static atomic64_t g_hook_pc; + + +static struct mutex g_hwbp_handle_info_mutex; +static cvector g_hwbp_handle_info_arr = NULL; + +static void record_hit_details(struct HWBP_HANDLE_INFO *info, struct pt_regs *regs) { + struct HWBP_HIT_ITEM hit_item = {0}; + if (!info || !regs) { + return; + } + hit_item.task_id = info->task_id; + hit_item.hit_addr = regs->pc; + hit_item.hit_time = ktime_get_real_seconds(); + memcpy(&hit_item.regs_info.regs, regs->regs, sizeof(hit_item.regs_info.regs)); + hit_item.regs_info.sp = regs->sp; + hit_item.regs_info.pc = regs->pc; + hit_item.regs_info.pstate = regs->pstate; + hit_item.regs_info.orig_x0 = regs->orig_x0; + hit_item.regs_info.syscallno = regs->syscallno; + if (info->hit_item_arr) { + if(cvector_length(info->hit_item_arr) < MIN_LEN) { // 最多存放MIN_LEN个 + cvector_pushback(info->hit_item_arr, &hit_item); + } + } +} + +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE +static bool arm64_move_bp_to_next_instruction(struct perf_event *bp, uint64_t next_instruction_addr, struct perf_event_attr *original_attr, struct perf_event_attr * next_instruction_attr) { + int result; + if (!bp || !original_attr || !next_instruction_attr || !next_instruction_addr) { + return false; + } + memcpy(next_instruction_attr, original_attr, sizeof(struct perf_event_attr)); + next_instruction_attr->bp_addr = next_instruction_addr; + next_instruction_attr->bp_len = HW_BREAKPOINT_LEN_4; + next_instruction_attr->bp_type = HW_BREAKPOINT_X; + next_instruction_attr->disabled = 0; + result = x_modify_user_hw_breakpoint(bp, next_instruction_attr); + if(result) { + next_instruction_attr->bp_addr = 0; + return false; + } + return true; +} + +static bool arm64_recovery_bp_to_original(struct perf_event *bp, struct perf_event_attr *original_attr, struct perf_event_attr * next_instruction_attr) { + int result; + if (!bp || !original_attr || !next_instruction_attr) { + return false; + } + result = x_modify_user_hw_breakpoint(bp, original_attr); + if(result) { + return false; + } + next_instruction_attr->bp_addr = 0; + return true; +} +#endif + +static void hwbp_hit_user_info_callback(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs, struct HWBP_HANDLE_INFO * hwbp_handle_info) { + hwbp_handle_info->hit_total_count++; + record_hit_details(hwbp_handle_info, regs); +} + +/* + * Handle hitting a HW-breakpoint. + */ +static void hwbp_handler(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs) { + citerator iter; + uint64_t hook_pc; + printk_debug(KERN_INFO "hw_breakpoint HIT!!!!! bp:%px, pc:%px, id:%d\n", bp, regs->pc, bp->id); + + hook_pc = atomic64_read(&g_hook_pc); + if(hook_pc) { + regs->pc = hook_pc; + return; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp != bp) { + continue; + } +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + if(hwbp_handle_info->next_instruction_attr.bp_addr != regs->pc) { + // first hit + bool should_toggle = true; + hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); + if(!hwbp_handle_info->is_32bit_task) { + if(arm64_move_bp_to_next_instruction(bp, regs->pc + 4, &hwbp_handle_info->original_attr, &hwbp_handle_info->next_instruction_attr)) { + should_toggle = false; + } + } + if(should_toggle) { + toggle_bp_registers_directly(&hwbp_handle_info->original_attr, hwbp_handle_info->is_32bit_task, 0); + } + } else { + // second hit + if(!arm64_recovery_bp_to_original(bp, &hwbp_handle_info->original_attr, &hwbp_handle_info->next_instruction_attr)) { + toggle_bp_registers_directly(&hwbp_handle_info->next_instruction_attr, hwbp_handle_info->is_32bit_task, 0); + } + } +#else + hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); + toggle_bp_registers_directly(&hwbp_handle_info->original_attr, hwbp_handle_info->is_32bit_task, 0); +#endif + } + + mutex_unlock(&g_hwbp_handle_info_mutex); +} + + + +static ssize_t OnCmdOpenProcess(struct ioctl_request *hdr, char __user* buf) { + uint64_t pid = hdr->param1, handle = 0; + struct pid * proc_pid_struct = NULL; + printk_debug(KERN_INFO "CMD_OPEN_PROCESS\n"); + + printk_debug(KERN_INFO "pid:%llu,size:%ld\n", pid, sizeof(pid)); + + proc_pid_struct = get_proc_pid_struct(pid); + printk_debug(KERN_INFO "proc_pid_struct *:0x%p\n", (void*)proc_pid_struct); + if (!proc_pid_struct) { + return -EINVAL; + } + handle = (uint64_t)proc_pid_struct; + + printk_debug(KERN_INFO "handle:%llu,size:%ld\n", handle, sizeof(handle)); + if (!!x_copy_to_user((void*)buf, (void*)&handle, sizeof(handle))) { + return -EINVAL; + } + return 0; +} + +static ssize_t OnCmdCloseProcess(struct ioctl_request *hdr, char __user* buf) { + struct pid * proc_pid_struct = (struct pid *)hdr->param1; + printk_debug(KERN_INFO "CMD_CLOSE_PROCESS\n"); + printk_debug(KERN_INFO "proc_pid_struct*:0x%p,size:%ld\n", (void*)proc_pid_struct, sizeof(proc_pid_struct)); + release_proc_pid_struct(proc_pid_struct); + return 0; +} + +static ssize_t OnCmdGetCpuNumBrps(struct ioctl_request *hdr, char __user* buf) { + printk_debug(KERN_INFO "CMD_GET_NUM_BRPS\n"); + return getCpuNumBrps(); +} + +static ssize_t OnCmdGetCpuNumWrps(struct ioctl_request *hdr, char __user* buf) { + printk_debug(KERN_INFO "CMD_GET_NUM_WRPS\n"); + return getCpuNumWrps(); +} + +static ssize_t OnCmdInstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct pid * proc_pid_struct = (struct pid *)hdr->param1; + uint64_t proc_virt_addr = hdr->param2; + char hwbp_len = hdr->param3 & 0xFF; + char hwbp_type = (hdr->param3 >> 8) & 0xFF; + + pid_t pid_val; + struct task_struct *task; + struct HWBP_HANDLE_INFO hwbp_handle_info = { 0 }; + printk_debug(KERN_INFO "CMD_INST_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "proc_pid_struct *:%px\n", proc_pid_struct); + printk_debug(KERN_INFO "proc_virt_addr :%px\n", proc_virt_addr); + printk_debug(KERN_INFO "hwbp_len:%zu\n", hwbp_len); + printk_debug(KERN_INFO "hwbp_type:%d\n", hwbp_type); + + pid_val = pid_nr(proc_pid_struct); + printk_debug(KERN_INFO "pid_val:%d\n", pid_val); + + if (!pid_val) { + printk_debug(KERN_INFO "pid_nr failed.\n"); + return -EINVAL; + } + + task = pid_task(proc_pid_struct, PIDTYPE_PID); + if (!task) { + printk_debug(KERN_INFO "get_pid_task failed.\n"); + return -EINVAL; + } + + hwbp_handle_info.task_id = pid_val; + hwbp_handle_info.is_32bit_task = is_compat_thread(task_thread_info(task)); + ptrace_breakpoint_init(&hwbp_handle_info.original_attr); + hwbp_handle_info.original_attr.bp_addr = proc_virt_addr; + hwbp_handle_info.original_attr.bp_len = hwbp_len; + hwbp_handle_info.original_attr.bp_type = hwbp_type; + hwbp_handle_info.original_attr.disabled = 0; + + hwbp_handle_info.sample_hbp = x_register_user_hw_breakpoint(&hwbp_handle_info.original_attr, hwbp_handler, NULL, task); + printk_debug(KERN_INFO "register_user_hw_breakpoint return: %px\n", hwbp_handle_info.sample_hbp); + if (IS_ERR((void __force *)hwbp_handle_info.sample_hbp)) { + int ret = PTR_ERR((void __force *)hwbp_handle_info.sample_hbp); + printk_debug(KERN_INFO "register_user_hw_breakpoint failed: %d\n", ret); + return ret; + } + hwbp_handle_info.hit_item_arr = cvector_create(sizeof(struct HWBP_HIT_ITEM)); + mutex_lock(&g_hwbp_handle_info_mutex); + cvector_pushback(g_hwbp_handle_info_arr, &hwbp_handle_info); + mutex_unlock(&g_hwbp_handle_info_mutex); + + if (x_copy_to_user((void*)buf, &hwbp_handle_info.sample_hbp, sizeof(uint64_t))) { + return -EINVAL; + } + return 0; +} + +static ssize_t OnCmdUninstProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct perf_event * sample_hbp = (struct perf_event *)hdr->param1; + citerator iter; + bool found = false; + printk_debug(KERN_INFO "CMD_UNINST_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + if(!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp == sample_hbp) { + if(hwbp_handle_info->hit_item_arr) { + cvector_destroy(hwbp_handle_info->hit_item_arr); + hwbp_handle_info->hit_item_arr = NULL; + } + cvector_rm(g_hwbp_handle_info_arr, iter); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + if(found) { + x_unregister_hw_breakpoint(sample_hbp); + } + + return 0; +} + +static ssize_t OnCmdSuspendProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct perf_event * sample_hbp = (struct perf_event *)hdr->param1; + struct perf_event_attr new_instruction_attr; + citerator iter; + bool found = false; + printk_debug(KERN_INFO "CMD_SUSPEND_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + if(!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp == sample_hbp) { + hwbp_handle_info->original_attr.disabled = 1; + memcpy(&new_instruction_attr, &hwbp_handle_info->original_attr, sizeof(struct perf_event_attr)); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + if(found) { + if(!x_modify_user_hw_breakpoint(sample_hbp, &new_instruction_attr)) { + return 0; + } + } + return -EFAULT; +} + +static ssize_t OnCmdResumeProcessHwbp(struct ioctl_request *hdr, char __user* buf) { + struct perf_event * sample_hbp = (struct perf_event *)hdr->param1; + struct perf_event_attr new_instruction_attr; + citerator iter; + bool found = false; + printk_debug(KERN_INFO "CMD_RESUME_PROCESS_HWBP\n"); + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + if(!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp == sample_hbp) { + hwbp_handle_info->original_attr.disabled = 0; + memcpy(&new_instruction_attr, &hwbp_handle_info->original_attr, sizeof(struct perf_event_attr)); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + if(found) { + if(!x_modify_user_hw_breakpoint(sample_hbp, &new_instruction_attr)) { + return 0; + } + } + return -EFAULT; +} + +static ssize_t OnCmdGetHwbpHitCount(struct ioctl_request *hdr, char __user* buf) { + #pragma pack(1) + struct buf_layout { + uint64_t hit_total_count; + uint64_t hit_item_arr_count; + }; + #pragma pack() + struct perf_event *sample_hbp = (struct perf_event *)hdr->param1; + struct buf_layout user_data = {0}; + citerator iter; + printk_debug(KERN_INFO "CMD_GET_HWBP_HIT_COUNT\n"); + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp == sample_hbp && hwbp_handle_info->hit_item_arr) { + user_data.hit_total_count = hwbp_handle_info->hit_total_count; + user_data.hit_item_arr_count = cvector_length(hwbp_handle_info->hit_item_arr); + break; + } + } + + mutex_unlock(&g_hwbp_handle_info_mutex); + + printk_debug(KERN_INFO "user_data.hit_total_count:%zu\n", user_data.hit_total_count); + if (x_copy_to_user((void*)buf, &user_data, sizeof(user_data))) { + return -EINVAL; + } + return 0; +} + +static ssize_t OnCmdGetHwbpHitDetail(struct ioctl_request *hdr, char __user* buf) { + struct perf_event *sample_hbp = (struct perf_event *)hdr->param1; + size_t size = hdr->buf_size; + ssize_t count = 0; + size_t copy_pos; + size_t end_pos; + + citerator iter; + printk_debug(KERN_INFO "sample_hbp *:%ld\n", sample_hbp); + + copy_pos = (size_t)buf; + end_pos = (size_t)((size_t)buf + size); + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp == sample_hbp && hwbp_handle_info->hit_item_arr) { + citerator child; + for (child = cvector_begin(hwbp_handle_info->hit_item_arr); child != cvector_end(hwbp_handle_info->hit_item_arr); child = cvector_next(hwbp_handle_info->hit_item_arr, child)) { + struct HWBP_HIT_ITEM * hit_item = (struct HWBP_HIT_ITEM *)child; + if (copy_pos >= end_pos) { + break; + } + if (x_copy_to_user((void*)copy_pos, hit_item, sizeof(struct HWBP_HIT_ITEM))) { + break; + } + copy_pos += sizeof(struct HWBP_HIT_ITEM); + count++; + } + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + return count; +} + +static ssize_t OnCmdSetHookPc(struct ioctl_request *hdr, char __user* buf) { + uint64_t pc = hdr->param1; + printk_debug(KERN_INFO "CMD_SET_HOOK_PC\n"); + printk_debug(KERN_INFO "pc:%px\n", pc); + atomic64_set(&g_hook_pc, pc); + return 0; +} + +static ssize_t OnCmdHideKernelModule(struct ioctl_request *hdr, char __user* buf) { + printk_debug(KERN_INFO "CMD_HIDE_KERNEL_MODULE\n"); + if (g_hwBreakpointProc_devp->is_hidden_module == false) { + g_hwBreakpointProc_devp->is_hidden_module = true; + list_del_init(&__this_module.list); + kobject_del(&THIS_MODULE->mkobj.kobj); + } + return 0; +} + +static inline ssize_t DispatchCommand(struct ioctl_request *hdr, char __user* buf) { + switch (hdr->cmd) { + case CMD_OPEN_PROCESS: + return OnCmdOpenProcess(hdr, buf); + case CMD_CLOSE_PROCESS: + return OnCmdCloseProcess(hdr, buf); + case CMD_GET_NUM_BRPS: + return OnCmdGetCpuNumBrps(hdr, buf); + case CMD_GET_NUM_WRPS: + return OnCmdGetCpuNumWrps(hdr, buf); + case CMD_INST_PROCESS_HWBP: + return OnCmdInstProcessHwbp(hdr, buf); + case CMD_UNINST_PROCESS_HWBP: + return OnCmdUninstProcessHwbp(hdr, buf); + case CMD_SUSPEND_PROCESS_HWBP: + return OnCmdSuspendProcessHwbp(hdr, buf); + case CMD_RESUME_PROCESS_HWBP: + return OnCmdResumeProcessHwbp(hdr, buf); + case CMD_GET_HWBP_HIT_COUNT: + return OnCmdGetHwbpHitCount(hdr, buf); + case CMD_GET_HWBP_HIT_DETAIL: + return OnCmdGetHwbpHitDetail(hdr, buf); + case CMD_SET_HOOK_PC: + return OnCmdSetHookPc(hdr, buf); + case CMD_HIDE_KERNEL_MODULE: + return OnCmdHideKernelModule(hdr, buf); + default: + return -EINVAL; + } + return -EINVAL; +} + +static ssize_t hwBreakpointProc_read(struct file* filp, + char __user* buf, + size_t size, + loff_t* ppos) { + struct ioctl_request hdr = {0}; + size_t header_size = sizeof(hdr); + + if (size < header_size) { + return -EINVAL; + } + + if (x_copy_from_user(&hdr, buf, header_size)) { + return -EFAULT; + } + + if (size < header_size + hdr.buf_size) { + return -EINVAL; + } + + return DispatchCommand(&hdr, buf + header_size); +} + +static void clean_hwbp(void) { + citerator iter; + cvector wait_unregister_bp_arr = cvector_create(sizeof(struct perf_event *)); + if(!wait_unregister_bp_arr || !g_hwbp_handle_info_arr) { + return; + } + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp) { + cvector_pushback(wait_unregister_bp_arr, &hwbp_handle_info->sample_hbp); + hwbp_handle_info->sample_hbp = NULL; + } + if(hwbp_handle_info->hit_item_arr) { + cvector_destroy(hwbp_handle_info->hit_item_arr); + hwbp_handle_info->hit_item_arr = NULL; + } + } + cvector_destroy(g_hwbp_handle_info_arr); + g_hwbp_handle_info_arr = NULL; + mutex_unlock(&g_hwbp_handle_info_mutex); + + for (iter = cvector_begin(wait_unregister_bp_arr); iter != cvector_end(wait_unregister_bp_arr); iter = cvector_next(wait_unregister_bp_arr, iter)) { + struct perf_event * bp = *(struct perf_event **)iter; + x_unregister_hw_breakpoint(bp); + } + cvector_destroy(wait_unregister_bp_arr); +} + +static int hwBreakpointProc_release(struct inode *inode, struct file *filp) { + clean_hwbp(); + mutex_lock(&g_hwbp_handle_info_mutex); + g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); + mutex_unlock(&g_hwbp_handle_info_mutex); + return 0; +} + +static int hwBreakpointProc_dev_init(void) { +#ifdef CONFIG_KALLSYMS_LOOKUP_NAME + if(!init_kallsyms_lookup()) { + printk(KERN_EMERG "init_kallsyms_lookup failed\n"); + return -EBADF; + } +#endif + g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); + mutex_init(&g_hwbp_handle_info_mutex); + +#ifdef CONFIG_ANTI_PTRACE_DETECTION_MODE + start_anti_ptrace_detection(&g_hwbp_handle_info_mutex, &g_hwbp_handle_info_arr); +#endif + + g_hwBreakpointProc_devp = x_kmalloc(sizeof(struct hwBreakpointProcDev), GFP_KERNEL); + memset(g_hwBreakpointProc_devp, 0, sizeof(struct hwBreakpointProcDev)); + +#ifdef CONFIG_USE_PROC_FILE_NODE + g_hwBreakpointProc_devp->proc_parent = proc_mkdir(CONFIG_PROC_NODE_AUTH_KEY, NULL); + if(g_hwBreakpointProc_devp->proc_parent) { + g_hwBreakpointProc_devp->proc_entry = proc_create(CONFIG_PROC_NODE_AUTH_KEY, S_IRUGO | S_IWUGO, g_hwBreakpointProc_devp->proc_parent, &hwBreakpointProc_proc_ops); + start_hide_procfs_dir(CONFIG_PROC_NODE_AUTH_KEY); + } +#endif + +#ifdef DEBUG_PRINTK + printk(KERN_EMERG "Hello, %s debug\n", CONFIG_PROC_NODE_AUTH_KEY); + //test1(); + //test2(); + //test3(); + //test4(); +#else + printk(KERN_EMERG "Hello\n"); +#endif + return 0; +} + +static void hwBreakpointProc_dev_exit(void) { + +#ifdef CONFIG_ANTI_PTRACE_DETECTION_MODE + stop_anti_ptrace_detection(); +#endif + + clean_hwbp(); + + mutex_destroy(&g_hwbp_handle_info_mutex); + +#ifdef CONFIG_USE_PROC_FILE_NODE + if(g_hwBreakpointProc_devp->proc_entry) { + proc_remove(g_hwBreakpointProc_devp->proc_entry); + g_hwBreakpointProc_devp->proc_entry = NULL; + } + + if(g_hwBreakpointProc_devp->proc_parent) { + proc_remove(g_hwBreakpointProc_devp->proc_parent); + g_hwBreakpointProc_devp->proc_parent = NULL; + } + stop_hide_procfs_dir(); +#endif + kfree(g_hwBreakpointProc_devp); + printk(KERN_EMERG "Goodbye\n"); +} + +int __init init_module(void) { + return hwBreakpointProc_dev_init(); +} + +void __exit cleanup_module(void) { + hwBreakpointProc_dev_exit(); +} + +#ifndef CONFIG_MODULE_GUIDE_ENTRY +//Hook:__cfi_check_fn +unsigned char* __check_(unsigned char* result, void *ptr, void *diag) +{ + printk_debug(KERN_EMERG "my__cfi_check_fn!!!\n"); + return result; +} + +//Hook:__cfi_check_fail +unsigned char * __check_fail_(unsigned char *result) +{ + printk_debug(KERN_EMERG "my__cfi_check_fail!!!\n"); + return result; +} +#endif + +unsigned long __stack_chk_guard; + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linux"); +MODULE_DESCRIPTION("Linux default module"); + diff --git a/code/hwBreakpointProc_module.h b/code/hwBreakpointProc_module.h new file mode 100644 index 00000000..fe2422c8 --- /dev/null +++ b/code/hwBreakpointProc_module.h @@ -0,0 +1,93 @@ +#ifndef _HWBP_PROC_H_ +#define _HWBP_PROC_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //kmalloc与kfree +#include "ver_control.h" +#include "arm64_register_helper.h" +#include "cvector.h" +#ifdef CONFIG_USE_PROC_FILE_NODE +#include +#include "hide_procfs_dir.h" +#endif +////////////////////////////////////////////////////////////////// + +enum { + CMD_OPEN_PROCESS, // 打开进程 + CMD_CLOSE_PROCESS, // 关闭进程 + CMD_GET_NUM_BRPS, // 获取CPU硬件执行断点支持数量 + CMD_GET_NUM_WRPS, // 获取CPU硬件访问断点支持数量 + CMD_INST_PROCESS_HWBP, // 安装进程硬件断点 + CMD_UNINST_PROCESS_HWBP, // 卸载进程硬件断点 + CMD_SUSPEND_PROCESS_HWBP, // 暂停进程硬件断点 + CMD_RESUME_PROCESS_HWBP, // 恢复进程硬件断点 + CMD_GET_HWBP_HIT_COUNT, // 获取硬件断点命中地址数量 + CMD_GET_HWBP_HIT_DETAIL, // 获取硬件断点命中详细信息 + CMD_SET_HOOK_PC, // 设置无条件Hook跳转 + CMD_HIDE_KERNEL_MODULE, // 隐藏驱动 +}; + +struct hwBreakpointProcDev { +#ifdef CONFIG_USE_PROC_FILE_NODE + struct proc_dir_entry *proc_parent; + struct proc_dir_entry *proc_entry; +#endif + bool is_hidden_module; //是否已经隐藏过驱动列表了 +}; +static struct hwBreakpointProcDev *g_hwBreakpointProc_devp; + +static ssize_t hwBreakpointProc_read(struct file* filp, char __user* buf, size_t size, loff_t* ppos); +static int hwBreakpointProc_release(struct inode *inode, struct file *filp); +static const struct proc_ops hwBreakpointProc_proc_ops = { + .proc_read = hwBreakpointProc_read, + .proc_release = hwBreakpointProc_release, +}; + +#pragma pack(1) +struct my_user_pt_regs { + uint64_t regs[31]; + uint64_t sp; + uint64_t pc; + uint64_t pstate; + uint64_t orig_x0; + uint64_t syscallno; +}; +struct HWBP_HIT_ITEM { + uint64_t task_id; + uint64_t hit_addr; + uint64_t hit_time; + struct my_user_pt_regs regs_info; +}; +#pragma pack() + +struct HWBP_HANDLE_INFO { + uint64_t task_id; + struct perf_event * sample_hbp; + struct perf_event_attr original_attr; + bool is_32bit_task; +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + struct perf_event_attr next_instruction_attr; +#endif + size_t hit_total_count; + cvector hit_item_arr; +}; + +#endif /* _HWBP_PROC_H_ */ \ No newline at end of file diff --git a/code/hwbp_proc.c b/code/hwbp_proc.c new file mode 100644 index 00000000..3b80df65 --- /dev/null +++ b/code/hwbp_proc.c @@ -0,0 +1,705 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "arm64_register_helper.h" +#include "cvector.h" +#include "proc_pid.h" +#include "api_proxy.h" + + +#define MAJOR_NUM 100 +#define IOCTL_HWBP_OPEN_PROCESS _IOR(MAJOR_NUM, 1, char*) //打开进程 +#define IOCTL_HWBP_CLOSE_HANDLE _IOR(MAJOR_NUM, 2, char*) //关闭进程 +#define IOCTL_HWBP_GET_NUM_BRPS _IOR(MAJOR_NUM, 3, char*) //获取CPU支持硬件执行断点的数量 +#define IOCTL_HWBP_GET_NUM_WRPS _IOR(MAJOR_NUM, 4, char*) //获取CPU支持硬件访问断点的数量 +#define IOCTL_HWBP_INST_PROCESS_HWBP _IOR(MAJOR_NUM, 5, char*) //设置进程硬件断点 +#define IOCTL_HWBP_UNINST_PROCESS_HWBP _IOR(MAJOR_NUM, 6, char*) //删除进程硬件断点 +#define IOCTL_HWBP_SUSPEND_PROCESS_HWBP _IOR(MAJOR_NUM, 7, char*) //暂停进程硬件断点 +#define IOCTL_HWBP_RESUME_PROCESS_HWBP _IOR(MAJOR_NUM, 8, char*) //恢复进程硬件断点 +#define IOCTL_HWBP_GET_HWBP_HIT_COUNT _IOR(MAJOR_NUM, 9, char*) //获取硬件断点命中地址数量 +#define IOCTL_HWBP_SET_HOOK_PC _IOR(MAJOR_NUM, 20, char*) + +static atomic64_t g_hook_pc; + + +////////////////////////////////////////////////////////////////// +static int g_hwBreakpointProc_major = 0; +static dev_t g_hwBreakpointProc_devno; + +struct hwBreakpointProcDev { + struct cdev *pcdev; + size_t cur_dev_open_count; + bool is_already_hide_dev_file; +}; +static struct hwBreakpointProcDev *g_hwBreakpointProc_devp; +static struct class *g_Class_devp; + +static struct mutex g_hwbp_handle_info_mutex; +static cvector g_hwbp_handle_info_arr = NULL; + +static void record_hit_details(struct HWBP_HANDLE_INFO *info, struct pt_regs *regs) { + struct HWBP_HIT_ITEM hit_item = {0}; + if (!info || !regs) { + return; + } + hit_item.task_id = info->task_id; + hit_item.hit_addr = regs->pc; + hit_item.hit_time = ktime_get_real_seconds(); + memcpy(&hit_item.regs_info.regs, regs->regs, sizeof(hit_item.regs_info.regs)); + hit_item.regs_info.sp = regs->sp; + hit_item.regs_info.pc = regs->pc; + hit_item.regs_info.pstate = regs->pstate; + hit_item.regs_info.orig_x0 = regs->orig_x0; + hit_item.regs_info.syscallno = regs->syscallno; + if (info->hit_item_arr) { + if(cvector_length(info->hit_item_arr) < MIN_LEN) { // 最多存放MIN_LEN个 + cvector_pushback(info->hit_item_arr, &hit_item); + } + } +} + +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE +static bool arm64_move_bp_to_next_instruction(struct perf_event *bp, uint64_t next_instruction_addr, struct perf_event_attr *original_attr, struct perf_event_attr * next_instruction_attr) { + int result; + if (!bp || !original_attr || !next_instruction_attr || !next_instruction_addr) { + return false; + } + memcpy(next_instruction_attr, original_attr, sizeof(struct perf_event_attr)); + next_instruction_attr->bp_addr = next_instruction_addr; + next_instruction_attr->bp_len = HW_BREAKPOINT_LEN_4; + next_instruction_attr->bp_type = HW_BREAKPOINT_X; + next_instruction_attr->disabled = 0; + result = x_modify_user_hw_breakpoint(bp, next_instruction_attr); + if(result) { + next_instruction_attr->bp_addr = 0; + return false; + } + return true; +} + +static bool arm64_recovery_bp_to_original(struct perf_event *bp, struct perf_event_attr *original_attr, struct perf_event_attr * next_instruction_attr) { + int result; + if (!bp || !original_attr || !next_instruction_attr) { + return false; + } + result = x_modify_user_hw_breakpoint(bp, original_attr); + if(result) { + return false; + } + next_instruction_attr->bp_addr = 0; + return true; +} +#endif + +static void hwbp_hit_user_info_callback(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs, struct HWBP_HANDLE_INFO * hwbp_handle_info) { + hwbp_handle_info->hit_total_count++; + record_hit_details(hwbp_handle_info, regs); +} + +/* + * Handle hitting a HW-breakpoint. + */ +static void hwbp_handler(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs) { + citerator iter; + uint64_t hook_pc; + printk_debug(KERN_INFO "hw_breakpoint HIT!!!!! bp:%px, pc:%px, id:%d\n", bp, regs->pc, bp->id); + + hook_pc = atomic64_read(&g_hook_pc); + if(hook_pc) { + regs->pc = hook_pc; + return; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp != bp) { + continue; + } +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + if(hwbp_handle_info->next_instruction_attr.bp_addr != regs->pc) { + // first hit + bool should_toggle = true; + hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); + if(!hwbp_handle_info->is_32bit_task) { + if(arm64_move_bp_to_next_instruction(bp, regs->pc + 4, &hwbp_handle_info->original_attr, &hwbp_handle_info->next_instruction_attr)) { + should_toggle = false; + } + } + if(should_toggle) { + toggle_bp_registers_directly(&hwbp_handle_info->original_attr, hwbp_handle_info->is_32bit_task, 0); + } + } else { + // second hit + if(!arm64_recovery_bp_to_original(bp, &hwbp_handle_info->original_attr, &hwbp_handle_info->next_instruction_attr)) { + toggle_bp_registers_directly(&hwbp_handle_info->next_instruction_attr, hwbp_handle_info->is_32bit_task, 0); + } + } +#else + hwbp_hit_user_info_callback(bp, data, regs, hwbp_handle_info); + toggle_bp_registers_directly(&hwbp_handle_info->original_attr, hwbp_handle_info->is_32bit_task, 0); +#endif + } + + mutex_unlock(&g_hwbp_handle_info_mutex); +} + + + +static long OnIoctlOpenProcess(unsigned long arg) { + int64_t pid = 0; + struct pid * proc_pid_struct = NULL; + if (copy_from_user(&pid, (void __user *)arg, 8)) { + return -EINVAL; + } + printk_debug(KERN_INFO "pid:%ld\n", pid); + proc_pid_struct = get_proc_pid_struct(pid); + printk_debug(KERN_INFO "proc_pid_struct *:%px\n", proc_pid_struct); + if (!proc_pid_struct) { + return -EINVAL; + } + if (copy_to_user((void*)arg, &proc_pid_struct, 8)) { + return -EINVAL; + } + return 0; +} + +static long OnIoctlCloseProcess(unsigned long arg) { + //获取进程句柄 + struct pid * proc_pid_struct = NULL; + if (copy_from_user((void*)&proc_pid_struct, (void*)arg, 8)) { + return -EFAULT; + } + //关闭进程句柄 + printk_debug(KERN_INFO "proc_pid_struct *:%px\n", proc_pid_struct); + release_proc_pid_struct(proc_pid_struct); + return 0; +} + +static long OnIoctlGetCpuNumBrps(void) { + return getCpuNumBrps(); +} + +static long OnIoctlGetCpuNumWrps(void) { + return getCpuNumWrps(); +} + +static long OnIoctlInstProcessHwbp(unsigned long arg) { + #pragma pack(1) + struct buf_layout { + struct pid * proc_pid_struct; + size_t proc_virt_addr; + unsigned int hwbp_len; + unsigned int hwbp_type; + }; + #pragma pack() + pid_t pid_val; + struct task_struct *task; + struct buf_layout user_data = {0}; + struct HWBP_HANDLE_INFO hwbp_handle_info = { 0 }; + if (copy_from_user((void*)&user_data, (void*)arg, 24)) { + return -EFAULT; + } + printk_debug(KERN_INFO "proc_pid_struct *:%px\n", user_data.proc_pid_struct); + printk_debug(KERN_INFO "proc_virt_addr :%px\n", user_data.proc_virt_addr); + printk_debug(KERN_INFO "hwbp_len:%zu\n", user_data.hwbp_len); + printk_debug(KERN_INFO "hwbp_type:%d\n", user_data.hwbp_type); + pid_val = pid_nr(user_data.proc_pid_struct); + printk_debug(KERN_INFO "pid_val:%d\n", pid_val); + + if (!pid_val) { + printk_debug(KERN_INFO "pid_nr failed.\n"); + return -EINVAL; + } + + task = pid_task(user_data.proc_pid_struct, PIDTYPE_PID); + if (!task) { + printk_debug(KERN_INFO "get_pid_task failed.\n"); + return -EINVAL; + } + + hwbp_handle_info.task_id = pid_val; + hwbp_handle_info.is_32bit_task = is_compat_thread(task_thread_info(task)); + ptrace_breakpoint_init(&hwbp_handle_info.original_attr); + hwbp_handle_info.original_attr.bp_addr = user_data.proc_virt_addr; + hwbp_handle_info.original_attr.bp_len = user_data.hwbp_len; + hwbp_handle_info.original_attr.bp_type = user_data.hwbp_type; + hwbp_handle_info.original_attr.disabled = 0; + + hwbp_handle_info.sample_hbp = x_register_user_hw_breakpoint(&hwbp_handle_info.original_attr, hwbp_handler, NULL, task); + printk_debug(KERN_INFO "register_user_hw_breakpoint return: %px\n", hwbp_handle_info.sample_hbp); + if (IS_ERR((void __force *)hwbp_handle_info.sample_hbp)) { + int ret = PTR_ERR((void __force *)hwbp_handle_info.sample_hbp); + printk_debug(KERN_INFO "register_user_hw_breakpoint failed: %d\n", ret); + return ret; + } + hwbp_handle_info.hit_item_arr = cvector_create(sizeof(struct HWBP_HIT_ITEM)); + mutex_lock(&g_hwbp_handle_info_mutex); + cvector_pushback(g_hwbp_handle_info_arr, &hwbp_handle_info); + mutex_unlock(&g_hwbp_handle_info_mutex); + if (copy_to_user((void*)arg, &hwbp_handle_info.sample_hbp, 8)) { + return -EINVAL; + } + return 0; +} + +static long OnIoctlUninstProcessHwbp(unsigned long arg) { + struct perf_event * sample_hbp = NULL; + citerator iter; + bool found = false; + if (copy_from_user(&sample_hbp, (void __user *)arg, 8)) { + return -EFAULT; + } + + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + if(!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp == sample_hbp) { + if(hwbp_handle_info->hit_item_arr) { + cvector_destroy(hwbp_handle_info->hit_item_arr); + hwbp_handle_info->hit_item_arr = NULL; + } + cvector_rm(g_hwbp_handle_info_arr, iter); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + if(found) { + x_unregister_hw_breakpoint(sample_hbp); + } + + return 0; +} + +static long OnIoctlSuspendProcessHwbp(unsigned long arg) { + struct perf_event * sample_hbp = NULL; + struct perf_event_attr new_instruction_attr; + citerator iter; + bool found = false; + if (copy_from_user(&sample_hbp, (void __user *)arg, 8)) { + return -EFAULT; + } + + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + if(!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp == sample_hbp) { + hwbp_handle_info->original_attr.disabled = 1; + memcpy(&new_instruction_attr, &hwbp_handle_info->original_attr, sizeof(struct perf_event_attr)); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + if(found) { + if(!x_modify_user_hw_breakpoint(sample_hbp, &new_instruction_attr)) { + return 0; + } + } + return -EFAULT; +} + +static long OnIoctlResumeProcessHwbp(unsigned long arg) { + struct perf_event * sample_hbp = NULL; + struct perf_event_attr new_instruction_attr; + citerator iter; + bool found = false; + if (copy_from_user(&sample_hbp, (void __user *)arg, 8)) { + return -EFAULT; + } + + printk_debug(KERN_INFO "sample_hbp *:%px\n", sample_hbp); + if(!sample_hbp) { + return -EFAULT; + } + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp == sample_hbp) { + hwbp_handle_info->original_attr.disabled = 0; + memcpy(&new_instruction_attr, &hwbp_handle_info->original_attr, sizeof(struct perf_event_attr)); + found = true; + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + if(found) { + if(!x_modify_user_hw_breakpoint(sample_hbp, &new_instruction_attr)) { + return 0; + } + } + return -EFAULT; +} + +static long OnIoctlGetHwbpHitCount(unsigned long arg) { + #pragma pack(1) + struct buf_layout { + struct perf_event *sample_hbp; + uint64_t hit_total_count; + uint64_t hit_item_arr_count; + }; + #pragma pack() + struct buf_layout user_data = {0}; + citerator iter; + if (copy_from_user(&user_data.sample_hbp, (void __user *)arg, 8)) { + return -EFAULT; + } + printk_debug(KERN_INFO "sample_hbp *:%px\n", user_data.sample_hbp); + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp == user_data.sample_hbp && hwbp_handle_info->hit_item_arr) { + user_data.hit_total_count = hwbp_handle_info->hit_total_count; + user_data.hit_item_arr_count = cvector_length(hwbp_handle_info->hit_item_arr); + break; + } + } + + mutex_unlock(&g_hwbp_handle_info_mutex); + + printk_debug(KERN_INFO "user_data.hit_total_count:%zu\n", user_data.hit_total_count); + if (copy_to_user((void*)arg, &user_data, 24)) { + return -EINVAL; + } + return 0; +} + +static long OnIoctlSetHookPc(unsigned long arg) { + uint64_t pc = 0; + if (copy_from_user(&pc, (void __user *)arg, 8)) { + return -EFAULT; + } + printk_debug(KERN_INFO "pc:%px\n", pc); + atomic64_set(&g_hook_pc, pc); + return 0; +} + +static ssize_t hwBreakpointProc_read(struct file* filp, char __user* buf, size_t size, loff_t* ppos) { + struct perf_event * sample_hbp = NULL; + ssize_t count = 0; + size_t copy_pos; + size_t end_pos; + + citerator iter; + if (copy_from_user((void*)&sample_hbp, buf, 8)) { + return -EFAULT; + } + printk_debug(KERN_INFO "sample_hbp *:%ld\n", sample_hbp); + + copy_pos = (size_t)buf; + end_pos = (size_t)((size_t)buf + size); + + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if (hwbp_handle_info->sample_hbp == sample_hbp && hwbp_handle_info->hit_item_arr) { + citerator child; + for (child = cvector_begin(hwbp_handle_info->hit_item_arr); child != cvector_end(hwbp_handle_info->hit_item_arr); child = cvector_next(hwbp_handle_info->hit_item_arr, child)) { + struct HWBP_HIT_ITEM * hit_item = (struct HWBP_HIT_ITEM *)child; + if (copy_pos >= end_pos) { + break; + } + if (copy_to_user((void*)copy_pos, hit_item, sizeof(struct HWBP_HIT_ITEM))) { + break; + } + copy_pos += sizeof(struct HWBP_HIT_ITEM); + count++; + } + break; + } + } + mutex_unlock(&g_hwbp_handle_info_mutex); + return count; +} + +static inline long DispatchCommand(unsigned int cmd, unsigned long arg) { + switch (cmd) { + case IOCTL_HWBP_OPEN_PROCESS: //打开进程 + printk_debug(KERN_INFO "IOCTL_HWBP_OPEN_PROCESS\n"); + return OnIoctlOpenProcess(arg); + case IOCTL_HWBP_CLOSE_HANDLE: //关闭进程 + printk_debug(KERN_INFO "IOCTL_HWBP_CLOSE_HANDLE\n"); + return OnIoctlCloseProcess(arg); + case IOCTL_HWBP_GET_NUM_BRPS: //获取CPU支持硬件执行断点的数量 + printk_debug(KERN_INFO "IOCTL_HWBP_GET_NUM_BRPS\n"); + return OnIoctlGetCpuNumBrps(); + case IOCTL_HWBP_GET_NUM_WRPS: //获取CPU支持硬件访问断点的数量 + printk_debug(KERN_INFO "IOCTL_HWBP_GET_NUM_WRPS\n"); + return OnIoctlGetCpuNumWrps(); + case IOCTL_HWBP_INST_PROCESS_HWBP: //设置进程硬件断点 + printk_debug(KERN_INFO "IOCTL_HWBP_INST_PROCESS_HWBP\n"); + return OnIoctlInstProcessHwbp(arg); + case IOCTL_HWBP_UNINST_PROCESS_HWBP: //删除进程硬件断点 + printk_debug(KERN_INFO "IOCTL_HWBP_UNINST_PROCESS_HWBP\n"); + return OnIoctlUninstProcessHwbp(arg); + case IOCTL_HWBP_SUSPEND_PROCESS_HWBP: //暂停进程硬件断点 + printk_debug(KERN_INFO "IOCTL_HWBP_SUSPEND_PROCESS_HWBP\n"); + return OnIoctlSuspendProcessHwbp(arg); + case IOCTL_HWBP_RESUME_PROCESS_HWBP: //恢复进程硬件断点 + printk_debug(KERN_INFO "IOCTL_HWBP_RESUME_PROCESS_HWBP\n"); + return OnIoctlResumeProcessHwbp(arg); + case IOCTL_HWBP_GET_HWBP_HIT_COUNT: //获取硬件断点命中地址数量 + printk_debug(KERN_INFO "IOCTL_HWBP_GET_HWBP_HIT_COUNT\n"); + return OnIoctlGetHwbpHitCount(arg); + case IOCTL_HWBP_SET_HOOK_PC: + printk_debug(KERN_INFO "IOCTL_HWBP_SET_HOOK_PC\n"); + return OnIoctlSetHookPc(arg); + default: + return -EINVAL; + } + return -EINVAL; +} + + +//long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); +//long (*compat_ioctl) (struct file *, unsigned int cmd, unsigned long arg) +static long hwBreakpointProc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + return DispatchCommand(cmd, arg); +} + +static int hwBreakpointProc_open(struct inode *inode, struct file *filp) { + g_hwBreakpointProc_devp->cur_dev_open_count++; + if (g_hwBreakpointProc_devp->cur_dev_open_count >= 2) { + if (!g_hwBreakpointProc_devp->is_already_hide_dev_file) { + g_hwBreakpointProc_devp->is_already_hide_dev_file = true; + device_destroy(g_Class_devp, g_hwBreakpointProc_devno); + class_destroy(g_Class_devp); + } + } + return 0; +} + +static loff_t hwBreakpointProc_llseek(struct file* filp, loff_t offset, int orig) { + unsigned int cmd = 0; + printk_debug("hwBreakpointProc llseek offset:%zd\n", (ssize_t)offset); + if (!!copy_from_user((void*)&cmd, (void*)offset, sizeof(unsigned int))) { + return -EINVAL; + } + printk_debug("hwBreakpointProc llseek cmd:%u\n", cmd); + return DispatchCommand(cmd, offset + sizeof(unsigned int)); +} + +static ssize_t hwBreakpointProc_write(struct file* filp, const char __user* buf, size_t size, loff_t *ppos) { + return 0; +} + +static void clean_hwbp(void) { + citerator iter; + cvector wait_unregister_bp_arr = cvector_create(sizeof(struct perf_event *)); + if(!wait_unregister_bp_arr || !g_hwbp_handle_info_arr) { + return; + } + mutex_lock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(g_hwbp_handle_info_arr); iter != cvector_end(g_hwbp_handle_info_arr); iter = cvector_next(g_hwbp_handle_info_arr, iter)) { + struct HWBP_HANDLE_INFO * hwbp_handle_info = (struct HWBP_HANDLE_INFO *)iter; + if(hwbp_handle_info->sample_hbp) { + cvector_pushback(wait_unregister_bp_arr, &hwbp_handle_info->sample_hbp); + hwbp_handle_info->sample_hbp = NULL; + } + if(hwbp_handle_info->hit_item_arr) { + cvector_destroy(hwbp_handle_info->hit_item_arr); + hwbp_handle_info->hit_item_arr = NULL; + } + } + cvector_destroy(g_hwbp_handle_info_arr); + g_hwbp_handle_info_arr = NULL; + mutex_unlock(&g_hwbp_handle_info_mutex); + for (iter = cvector_begin(wait_unregister_bp_arr); iter != cvector_end(wait_unregister_bp_arr); iter = cvector_next(wait_unregister_bp_arr, iter)) { + struct perf_event * bp = *(struct perf_event **)iter; + x_unregister_hw_breakpoint(bp); + } + cvector_destroy(wait_unregister_bp_arr); +} + +static int hwBreakpointProc_release(struct inode *inode, struct file *filp) { + if (g_hwBreakpointProc_devp->cur_dev_open_count > 0) { + g_hwBreakpointProc_devp->cur_dev_open_count--; + } + if (g_hwBreakpointProc_devp->cur_dev_open_count < 1) { + if (g_hwBreakpointProc_devp->is_already_hide_dev_file) { + g_hwBreakpointProc_devp->is_already_hide_dev_file = false; + + g_Class_devp = class_create(THIS_MODULE, DEV_FILENAME); + device_create(g_Class_devp, NULL, g_hwBreakpointProc_devno, NULL, "%s", DEV_FILENAME); + } + } + + clean_hwbp(); + mutex_lock(&g_hwbp_handle_info_mutex); + g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); + mutex_unlock(&g_hwbp_handle_info_mutex); + return 0; +} + +static const struct file_operations hwBreakpointProc_fops = +{ + .owner = THIS_MODULE, + .open = hwBreakpointProc_open, + .release = hwBreakpointProc_release, + .read = hwBreakpointProc_read, + .write = hwBreakpointProc_write, + .llseek = hwBreakpointProc_llseek, + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) + .ioctl = hwBreakpointProc_ioctl, +#else + .compat_ioctl = hwBreakpointProc_ioctl, + .unlocked_ioctl = hwBreakpointProc_ioctl, +#endif +}; + +#ifdef CONFIG_MODULE_GUIDE_ENTRY +static +#endif +int __init hwBreakpointProc_dev_init(void) { + int result; + int err; + +#ifdef CONFIG_KALLSYMS_LOOKUP_NAME + if(!init_kallsyms_lookup()) { + printk(KERN_EMERG "init_kallsyms_lookup failed\n"); + return -EBADF; + } +#endif + + g_hwbp_handle_info_arr = cvector_create(sizeof(struct HWBP_HANDLE_INFO)); + if(!g_hwbp_handle_info_arr) { + printk(KERN_EMERG "cvector_create failed\n"); + return -ENOMEM; + } + + mutex_init(&g_hwbp_handle_info_mutex); + +#ifdef CONFIG_ANTI_PTRACE_DETECTION_MODE + start_anti_ptrace_detection(&g_hwbp_handle_info_mutex, &g_hwbp_handle_info_arr); +#endif + + result = alloc_chrdev_region(&g_hwBreakpointProc_devno, 0, 1, DEV_FILENAME); + g_hwBreakpointProc_major = MAJOR(g_hwBreakpointProc_devno); + + if (result < 0) { + printk(KERN_EMERG "hwBreakpointProc alloc_chrdev_region failed %d\n", result); + return result; + } + + g_hwBreakpointProc_devp = __kmalloc(sizeof(struct hwBreakpointProcDev), GFP_KERNEL); + if (!g_hwBreakpointProc_devp) { + result = -ENOMEM; + goto _fail; + } + memset(g_hwBreakpointProc_devp, 0, sizeof(struct hwBreakpointProcDev)); + + g_hwBreakpointProc_devp->pcdev = __kmalloc(sizeof(struct cdev) * 3/*大些兼容性强*/, GFP_KERNEL); + cdev_init(g_hwBreakpointProc_devp->pcdev, &hwBreakpointProc_fops); + g_hwBreakpointProc_devp->pcdev->owner = THIS_MODULE; + g_hwBreakpointProc_devp->pcdev->ops = &hwBreakpointProc_fops; + err = cdev_add(g_hwBreakpointProc_devp->pcdev, g_hwBreakpointProc_devno, 1); + if (err) { + printk(KERN_EMERG "Error in cdev_add()\n"); + result = -EFAULT; + goto _fail; + } + + g_Class_devp = class_create(THIS_MODULE, DEV_FILENAME); + device_create(g_Class_devp, NULL, g_hwBreakpointProc_devno, NULL, "%s", DEV_FILENAME); + +#ifdef DEBUG_PRINTK + printk(KERN_EMERG "Hello, %s debug\n", DEV_FILENAME); +#else + printk(KERN_EMERG "Hello, %s\n", DEV_FILENAME); +#endif + return 0; + +_fail: + unregister_chrdev_region(g_hwBreakpointProc_devno, 1); + return result; +} + +#ifdef CONFIG_MODULE_GUIDE_ENTRY +static +#endif +void __exit hwBreakpointProc_dev_exit(void) { + +#ifdef CONFIG_ANTI_PTRACE_DETECTION_MODE + stop_anti_ptrace_detection(); +#endif + + clean_hwbp(); + + mutex_destroy(&g_hwbp_handle_info_mutex); + + device_destroy(g_Class_devp, g_hwBreakpointProc_devno); + class_destroy(g_Class_devp); + + cdev_del(g_hwBreakpointProc_devp->pcdev); + kfree(g_hwBreakpointProc_devp->pcdev); + kfree(g_hwBreakpointProc_devp); + unregister_chrdev_region(g_hwBreakpointProc_devno, 1); + printk(KERN_EMERG "Goodbye, %s\n", DEV_FILENAME); +} + +#ifndef CONFIG_MODULE_GUIDE_ENTRY +//Hook:__cfi_check_fn +unsigned char* __check_(unsigned char* result, void *ptr, void *diag) +{ + printk_debug(KERN_EMERG "my__cfi_check_fn!!!\n"); + return result; +} + +//Hook:__cfi_check_fail +unsigned char * __check_fail_(unsigned char *result) +{ + printk_debug(KERN_EMERG "my__cfi_check_fail!!!\n"); + return result; +} +#endif + +unsigned long __stack_chk_guard; + +#ifdef CONFIG_MODULE_GUIDE_ENTRY +module_init(hwBreakpointProc_dev_init); +module_exit(hwBreakpointProc_dev_exit); +#endif + +MODULE_AUTHOR("Linux"); +MODULE_DESCRIPTION("Linux default module"); +MODULE_LICENSE("GPL"); diff --git a/code/hwbp_proc.h b/code/hwbp_proc.h new file mode 100644 index 00000000..88801c5f --- /dev/null +++ b/code/hwbp_proc.h @@ -0,0 +1,34 @@ +#ifndef _HWBP_PROC_H_ +#define _HWBP_PROC_H_ +#include "ver_control.h" + +#pragma pack(1) +struct my_user_pt_regs { + uint64_t regs[31]; + uint64_t sp; + uint64_t pc; + uint64_t pstate; + uint64_t orig_x0; + uint64_t syscallno; +}; +struct HWBP_HIT_ITEM { + uint64_t task_id; + uint64_t hit_addr; + uint64_t hit_time; + struct my_user_pt_regs regs_info; +}; +#pragma pack() + +struct HWBP_HANDLE_INFO { + uint64_t task_id; + struct perf_event * sample_hbp; + struct perf_event_attr original_attr; + bool is_32bit_task; +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + struct perf_event_attr next_instruction_attr; +#endif + size_t hit_total_count; + cvector hit_item_arr; +}; + +#endif \ No newline at end of file diff --git a/code/kallsyms_lookup_api.h b/code/kallsyms_lookup_api.h new file mode 100644 index 00000000..f3592579 --- /dev/null +++ b/code/kallsyms_lookup_api.h @@ -0,0 +1,64 @@ +#ifndef _KALLSYMS_LOOKUP_API_H_ +#define _KALLSYMS_LOOKUP_API_H_ +#include "ver_control.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned long (*kallsyms_lookup_name_sym)(const char *name); +static struct perf_event* (*register_user_hw_breakpoint_sym)(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context, struct task_struct *tsk); +static void (*unregister_hw_breakpoint_sym)(struct perf_event *bp); +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE +static int (*modify_user_hw_breakpoint_sym)(struct perf_event *bp, struct perf_event_attr *attr); +#endif + +static int _kallsyms_lookup_kprobe(struct kprobe *p, struct pt_regs *regs) { return 0; } +static unsigned long get_kallsyms_func(void) { + int ret; + unsigned long addr = 0; + struct kprobe probe = {0}; + probe.pre_handler = _kallsyms_lookup_kprobe; + probe.symbol_name = "kallsyms_lookup_name"; + ret = register_kprobe(&probe); + if (ret == 0) { + addr = (unsigned long)probe.addr; + printk_debug(KERN_EMERG "get_kallsyms_func(kallsyms_lookup_name):%px\n", addr); + unregister_kprobe(&probe); + } + return addr; +} + +static unsigned long generic_kallsyms_lookup_name(const char *name) { + if (!kallsyms_lookup_name_sym) { + kallsyms_lookup_name_sym = (void *)get_kallsyms_func(); + printk_debug(KERN_EMERG "get_kallsyms_func:%px\n", kallsyms_lookup_name_sym); + if(!kallsyms_lookup_name_sym) + return 0; + } + return kallsyms_lookup_name_sym(name); +} + +static bool init_kallsyms_lookup(void) { + register_user_hw_breakpoint_sym = (void *)generic_kallsyms_lookup_name("register_user_hw_breakpoint"); + printk_debug(KERN_EMERG "register_user_hw_breakpoint_sym:%px\n", register_user_hw_breakpoint_sym); + if(!register_user_hw_breakpoint_sym) { return false; } + + unregister_hw_breakpoint_sym = (void *)generic_kallsyms_lookup_name("unregister_hw_breakpoint"); + printk_debug(KERN_EMERG "unregister_hw_breakpoint_sym:%px\n", unregister_hw_breakpoint_sym); + if(!unregister_hw_breakpoint_sym) { return false; } + +#ifdef CONFIG_MODIFY_HIT_NEXT_MODE + modify_user_hw_breakpoint_sym = (void *)generic_kallsyms_lookup_name("modify_user_hw_breakpoint"); + printk_debug(KERN_EMERG "modify_user_hw_breakpoint_sym:%px\n", modify_user_hw_breakpoint_sym); + if(!modify_user_hw_breakpoint_sym) { return false; } +#endif + + return true; +} +#endif diff --git a/code/proc_pid.h b/code/proc_pid.h new file mode 100644 index 00000000..58123ce8 --- /dev/null +++ b/code/proc_pid.h @@ -0,0 +1,16 @@ +#ifndef _PROC_PID_H_ +#define _PROC_PID_H_ +#include +#include +#include "ver_control.h" +static inline struct pid * get_proc_pid_struct(int nPid) { + return find_get_pid(nPid); +} +static inline int get_proc_pid(struct pid* proc_pid_struct) { + return proc_pid_struct->numbers[0].nr; +} +static inline void release_proc_pid_struct(struct pid* proc_pid_struct) { + put_pid(proc_pid_struct); +} + +#endif /* _PROC_PID_H_ */ diff --git a/code/ver_control.h b/code/ver_control.h new file mode 100644 index 00000000..474e9163 --- /dev/null +++ b/code/ver_control.h @@ -0,0 +1,57 @@ +#ifndef VER_CONTROL_H_ +#define VER_CONTROL_H_ +#include + +// 独立内核模块入口模式 +#define CONFIG_MODULE_GUIDE_ENTRY + +// 生成proc用户层交互节点文件 +#define CONFIG_USE_PROC_FILE_NODE +// 隐蔽通信密钥 +#define CONFIG_PROC_NODE_AUTH_KEY "dce3771681d4c7a143d5d06b7d32548e" + +// 调试打印模式 +//#define CONFIG_DEBUG_PRINTK + +// 动态寻址模式 +#define CONFIG_KALLSYMS_LOOKUP_NAME + +// 精准命中记录模式 +#define CONFIG_MODIFY_HIT_NEXT_MODE + +// 反PTRACE侦测模式 +#define CONFIG_ANTI_PTRACE_DETECTION_MODE + +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif +#ifndef MY_LINUX_VERSION_CODE +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,10,0) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,10,84) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,18,71) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(3,18,140) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,21) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,78) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,153) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,4,192) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,9,112) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,9,186) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,83) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,117) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,14,141) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,19,81) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(4,19,113) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,4,61) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,10,43) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(5,15,41) +//#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,1,75) +#define MY_LINUX_VERSION_CODE KERNEL_VERSION(6,6,30) +#endif + +#ifdef CONFIG_DEBUG_PRINTK +#define printk_debug printk +#else +static inline void printk_debug(char *fmt, ...) {} +#endif + +#endif /* VER_CONTROL_H_ */ From 2c4405e78bc9aa5850ec2de227ab16e501a7ee61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 3 Feb 2026 13:19:52 +0800 Subject: [PATCH 32/35] Add files via upload --- code/ver_control.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/ver_control.h b/code/ver_control.h index 474e9163..b9c39501 100644 --- a/code/ver_control.h +++ b/code/ver_control.h @@ -6,9 +6,11 @@ #define CONFIG_MODULE_GUIDE_ENTRY // 生成proc用户层交互节点文件 -#define CONFIG_USE_PROC_FILE_NODE +//关闭进城隐藏 +//#define CONFIG_USE_PROC_FILE_NODE + // 隐蔽通信密钥 -#define CONFIG_PROC_NODE_AUTH_KEY "dce3771681d4c7a143d5d06b7d32548e" +#define CONFIG_PROC_NODE_AUTH_KEY "aurorakey07123456789" // 调试打印模式 //#define CONFIG_DEBUG_PRINTK From ab0e52b5ce521651c0410b55cbfba350ca03071d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:40:33 +0800 Subject: [PATCH 33/35] Update ver_control.h --- code/ver_control.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/ver_control.h b/code/ver_control.h index b9c39501..a368bf6c 100644 --- a/code/ver_control.h +++ b/code/ver_control.h @@ -6,8 +6,7 @@ #define CONFIG_MODULE_GUIDE_ENTRY // 生成proc用户层交互节点文件 -//关闭进城隐藏 -//#define CONFIG_USE_PROC_FILE_NODE +#define CONFIG_USE_PROC_FILE_NODE // 隐蔽通信密钥 #define CONFIG_PROC_NODE_AUTH_KEY "aurorakey07123456789" From a8ee2c3783425114d84bbb49065187c3d639cd7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:41:31 +0800 Subject: [PATCH 34/35] Enable debug print mode in ver_control.h --- code/ver_control.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ver_control.h b/code/ver_control.h index a368bf6c..103e4ebe 100644 --- a/code/ver_control.h +++ b/code/ver_control.h @@ -12,7 +12,7 @@ #define CONFIG_PROC_NODE_AUTH_KEY "aurorakey07123456789" // 调试打印模式 -//#define CONFIG_DEBUG_PRINTK +#define CONFIG_DEBUG_PRINTK // 动态寻址模式 #define CONFIG_KALLSYMS_LOOKUP_NAME From 55b56b4248d978f719056739ea4f03a3a274cd8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E4=BE=9D=E6=B6=B5?= <114746884+vesirvit@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:19:17 +0800 Subject: [PATCH 35/35] Add files via upload --- code/hide_procfs_dir.h | 4 ++-- code/hwBreakpointProc_module.c | 4 ++-- code/ver_control.h | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/code/hide_procfs_dir.h b/code/hide_procfs_dir.h index 8fc38a57..066e2562 100644 --- a/code/hide_procfs_dir.h +++ b/code/hide_procfs_dir.h @@ -60,7 +60,7 @@ static struct kprobe kp_hide_procfs_dir = { .pre_handler = handler_pre, }; -static bool start_hide_procfs_dir(const char* hide_dir_name) +static __maybe_unused bool start_hide_procfs_dir(const char* hide_dir_name) { //这里原理上可以换成SKRoot的汇编写法。避免kprobe。 int ret; @@ -74,7 +74,7 @@ static bool start_hide_procfs_dir(const char* hide_dir_name) return true; } -static void stop_hide_procfs_dir(void) +static __maybe_unused void stop_hide_procfs_dir(void) { unregister_kprobe(&kp_hide_procfs_dir); printk_debug("[hide_procfs_dir] kprobe removed\n"); diff --git a/code/hwBreakpointProc_module.c b/code/hwBreakpointProc_module.c index e20edc7d..4a7eaf45 100644 --- a/code/hwBreakpointProc_module.c +++ b/code/hwBreakpointProc_module.c @@ -517,7 +517,7 @@ static int hwBreakpointProc_dev_init(void) { g_hwBreakpointProc_devp->proc_parent = proc_mkdir(CONFIG_PROC_NODE_AUTH_KEY, NULL); if(g_hwBreakpointProc_devp->proc_parent) { g_hwBreakpointProc_devp->proc_entry = proc_create(CONFIG_PROC_NODE_AUTH_KEY, S_IRUGO | S_IWUGO, g_hwBreakpointProc_devp->proc_parent, &hwBreakpointProc_proc_ops); - start_hide_procfs_dir(CONFIG_PROC_NODE_AUTH_KEY); + //start_hide_procfs_dir(CONFIG_PROC_NODE_AUTH_KEY); } #endif @@ -553,7 +553,7 @@ static void hwBreakpointProc_dev_exit(void) { proc_remove(g_hwBreakpointProc_devp->proc_parent); g_hwBreakpointProc_devp->proc_parent = NULL; } - stop_hide_procfs_dir(); + //stop_hide_procfs_dir(); #endif kfree(g_hwBreakpointProc_devp); printk(KERN_EMERG "Goodbye\n"); diff --git a/code/ver_control.h b/code/ver_control.h index 103e4ebe..9a02db02 100644 --- a/code/ver_control.h +++ b/code/ver_control.h @@ -7,12 +7,11 @@ // 生成proc用户层交互节点文件 #define CONFIG_USE_PROC_FILE_NODE - // 隐蔽通信密钥 #define CONFIG_PROC_NODE_AUTH_KEY "aurorakey07123456789" // 调试打印模式 -#define CONFIG_DEBUG_PRINTK +//#define CONFIG_DEBUG_PRINTK // 动态寻址模式 #define CONFIG_KALLSYMS_LOOKUP_NAME