Skip to Content
Shadow Cheat EngineDev HistoryPTE Breakpoint — 问题总结

PTE Breakpoint — 问题总结

已解决的问题

1. Kernel Text 写保护 Panic

  • 现象: insmod 直接 panic
  • 根因: *(u32*)addr = insn 直接写内核 .text 段,CONFIG_STRICT_KERNEL_RWX 禁止
  • 修复: 改用 kallsyms 解析 aarch64_insn_patch_text_nosync(内核函数,会临时关写保护)
  • 状态: ✅ 已修复,B-detour hook 安装成功

2. set_memory_x 未导出

  • 现象: insmod 报 Unknown symbol set_memory_x (err -2)
  • 根因: 编译环境 Module.symvers 有该符号,但设备运行内核未导出
  • 修复: 改为 kallsyms 解析 + __nocfi wrapper
  • 状态: ✅ 已修复

3. register_user_step_hook 未导出

  • 现象: 交叉验证发现之前 agent 幻觉称已导出
  • 根因: 源码确认无 EXPORT_SYMBOL_GPL,只有 break_hook 系列导出
  • 修复: 改为 kallsyms 解析 + __nocfi wrapper
  • 状态: ✅ 已修复

4. 首条指令是 PACIASP 不是 SCS push

  • 现象: dmesg first insn: 0xd503233f
  • 根因: SM8750 有 PAC 硬件,should_patch_pac_into_scs() 返回 false,不替换
  • 修复: 运行时读取实际指令保存到 trampoline,不硬编码
  • 状态: ✅ 已修复

5. CFI 拦截 kallsyms 间接调用

  • 现象: CONFIG_CFI_CLANG=y,通过函数指针调用会被 KCFI 类型检查拒绝
  • 修复: 所有 kallsyms 调用用 __nocfi wrapper 包装(同 kernel_patch.c 模式)
  • 状态: ✅ 已修复

6. cpuhp 回调 WARN_ON

  • 现象: ptebp_cpu_online 在 dmesg 打出大量 Call trace
  • 根因: enable_debug_monitors 内部 WARN_ON(preemptible()),cpuhp 回调上下文可能 preemptible
  • 影响: 只是 warning,不 panic,功能正常
  • 状态: ⚠️ 已知,可后续修复(在 callback 里加 preempt_disable)

当前卡住的问题

7. PTE=0 后 fault handler 没有命中

  • 现象: ptebp_set 返回 0(成功),PTE 确认被改为 0,但 3 秒后 poll 返回 0 hits
  • 已排除:
    • TLB flush:已改为 tlbi vmalle1is(全局刷新),仍无效
    • PTE 值:dmesg 确认 before=0x20000bcb50afc3, after=0x0(PTE=0 确实写入了)
    • fault handler 是否被调用:是的,加载时有 fault 进来,说明 B-detour 工作正常
    • 地址范围:delta=47MB,在 ±128MB B 指令范围内
  • 可能根因:
    1. contpte: 即使 PTE=0,contiguous PTE 优化可能让 TLB 仍使用相邻 PTE 的 contiguous 条目。需要在 set 时清除相邻 15 个 PTE 的 PTE_CONT bit
    2. __set_pte vs contpte_set_ptes: 这个内核的 __set_pte 可能被 contpte 层包装了,实际写入时被 contpte 逻辑”修复”回去
    3. PTE walk 返回的 ptep 指向 contpte 的折叠页表项: pte_offset_map 在 contpte 内核上返回的可能不是真正的硬件 PTE,而是 contpte 的软件映射
    4. mm 不匹配: fault handler 里 current->mm != slot->mm(不太可能,同一进程)
    5. FSC 过滤: PTE=0 应该产生 translation fault (FSC 0x04-0x07),fault handler 已处理这个范围
    6. server.c 的 ioctl 调用: 可能 server 端 ioctl 没有正确传递参数(但 dmesg 有 “ptebp set” 日志说明 ioctl 到达了内核)

8. 权限位方案被 contpte 阻挡(已放弃)

  • 现象: 设 PTE_UXN 后 PTE 确认改变(0x20→0x60),但无 fault
  • 根因: contpte 将 16 个连续 PTE 合并为一个 TLB 条目,修改单个 PTE 的权限位不影响 TLB 缓存的 contiguous 条目
  • 状态: ❌ 放弃权限位方案,改用 PTE=0(但 PTE=0 也不工作,见问题 7)

下一步调查方向

  1. 验证 contpte 对 PTE=0 的影响:在 do_ptebp_set 里打印 __ptep_get 返回值(contpte 可能让读回的值和写入的不同)
  2. contpte_try_unfold 先展开 contiguous 块再修改:通过 kallsyms 解析 __contpte_try_unfold
  3. 对比 shadow_pg.c 的做法:shadow_pg 在 patched kernel 里工作,它的 __set_pte 调用为什么能生效?可能因为 shadow_pg 通过 kernel_patch.ko 的 fault hook 工作,而 kernel_patch.ko 可能在 hook 点之前做了 contpte unfold
  4. 直接写物理地址:绕过 contpte 层,直接操作硬件 PTE(通过 phys_to_virt 或 fixmap)
  5. 用 ptep_clear_flush 内核函数:这是内核正规的清 PTE 路径,会正确处理 contpte

架构总结

[工作的部分] - kallsyms 解析 ✅ - B-detour hook 安装 ✅ (aarch64_insn_patch_text_nosync) - fault handler 被正确调用 ✅ - step hook 注册 ✅ - MDE 全局启用 ✅ (on_each_cpu + cpuhp) - server CMD 0xD0-0xD3 ✅ - 客户端 ce_client.py + settings.py + hwbp_window.py 分流 ✅ [不工作的部分] - PTE 修改不生效(contpte 问题)❌ - 因此整个 fault→hit→single-step→re-arm 链路未验证
Last updated on