diff --git a/README.md b/README.md index 14b76ea..86bb660 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编译。 +由于本人还是初学者,所以会不定期学习新内容并更新 diff --git a/README_zh.md b/README_zh.md deleted file mode 100644 index 70cadf9..0000000 --- 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) -- 请提供工作流日志和输入参数 diff --git a/code/Makefile b/code/Makefile index 1ed512a..20d191c 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1 +1 @@ -obj-m += rwProcMem_module.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 0000000..d315865 --- /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 index 083a53d..9349e95 100644 --- a/code/api_proxy.h +++ b/code/api_proxy.h @@ -1,54 +1,43 @@ -#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_ */ - - +#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 0000000..2a13517 --- /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 0000000..ef5d4eb --- /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 index bf1aa95..066e256 100644 --- a/code/hide_procfs_dir.h +++ b/code/hide_procfs_dir.h @@ -1,82 +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 = 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_ +#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 __maybe_unused 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 __maybe_unused 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 0000000..4a7eaf4 --- /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 0000000..fe2422c --- /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 0000000..3b80df6 --- /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 0000000..88801c5 --- /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 0000000..f359257 --- /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/linux_kernel_api.h b/code/linux_kernel_api.h deleted file mode 100644 index ab693e7..0000000 --- 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 4d6c6d8..0000000 --- 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 dfebcf7..0000000 --- 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 f6885f5..0000000 --- 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 e7ba159..0000000 --- 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 9786b7a..0000000 --- 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 68f2398..0000000 --- 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 56360f7..0000000 --- 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 d0cc77f..0000000 --- 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_pid.h b/code/proc_pid.h new file mode 100644 index 0000000..58123ce --- /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/proc_root.h b/code/proc_root.h deleted file mode 100644 index dff6134..0000000 --- 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 df23a43..0000000 --- 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 35d6c30..0000000 --- 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 ef42d7f..0000000 --- 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 4909c9f..0000000 --- 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 0cc9378..0000000 --- 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 index c6cc986..9a02db0 100644 --- a/code/ver_control.h +++ b/code/ver_control.h @@ -1,47 +1,57 @@ -#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_ */ +#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 "aurorakey07123456789" + +// 调试打印模式 +//#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_ */