x86-64架构下自定义Invalid opcode中断处理程序如何调用原内核处理程序
x86-64无效操作码自定义中断处理fallback实现方案
你需要先获取并保存原始无效操作码异常(中断向量号为6)的处理程序入口地址,再调整汇编逻辑即可实现fallback逻辑,具体操作如下:
前置准备
在注册自定义处理函数到IDT之前,先读取IDT中向量6对应的表项,提取出原始处理程序的入口地址,存储到一个全局变量中(比如命名为orig_ili_handler)。如果是Linux内核环境,也可以直接通过内核符号直接获取原生处理函数invalid_op的地址。
汇编代码调整
核心注意点是要完整保留异常栈帧结构,不能破坏原始处理程序需要的上下文:
- 不要用
call指令调用原始处理程序,call会额外向栈压入返回地址,破坏原有异常栈帧 - 跳转到原始处理程序前,必须将寄存器、栈指针恢复到刚进入自定义处理函数时的状态
修改后的代码示例:
.globl my_ili_handler .extern orig_ili_handler # 提前存储的原始处理程序地址的全局变量 .text .align 4, 0x90 my_ili_handler: # 先保存自定义处理逻辑会用到的寄存器,避免破坏异常上下文 push %rdi push %rsi push %rdx push %rcx push %r8 push %r9 push %rax # ---------------------- # 这里写你的自定义处理逻辑 # 处理成功就跳转到success分支,处理失败则走到failed分支 # ---------------------- failed: # 恢复之前保存的寄存器,回到异常刚触发时的寄存器状态 pop %rax pop %r9 pop %r8 pop %rcx pop %rdx pop %rsi pop %rdi # 直接跳转到原始处理程序,栈帧完全保留,原始处理程序执行完会自行执行iretq返回 jmp *orig_ili_handler(%rip) success: # 处理成功的返回逻辑 pop %rax pop %r9 pop %r8 pop %rcx pop %rdx pop %rsi pop %rdi iretq
注意事项
- 如果你的自定义处理逻辑有修改栈指针的操作,跳转前必须把栈指针恢复到进入自定义处理函数时的数值,否则原始处理程序读取的栈帧会出错
- 如果你是在用户态模拟IDT钩子,需要注意特权级切换带来的栈结构差异,要对应调整上下文恢复逻辑
内容的提问来源于stack exchange,提问作者yellowcard123
相关产品推荐
相关产品推荐

