为什么某些 Linux x86_64 系统调用需要存根?

7
如果尝试通过sys_call_table-hooking挂钩某些系统调用,例如sys_execve,则会失败,因为它们是由存根间接调用的。对于sys_execve,这是stub_execve(请参见LXR上的汇编代码)。
但是这些存根有什么用呢?为什么只有像execve(2)和fork(2)这样的特定系统调用需要存根,这与x86_64有什么关系?是否有一种方法可以在可加载内核模块中挂钩存根化的系统调用?

1
从此文件顶部开始 http://lxr.free-electrons.com/source/arch/x86/kernel/entry_64.S,普通系统调用和中断不保存完整的堆栈帧,仅在系统调用跟踪、信号或fork/exec等情况下才会这样做。因此,基本上答案是:考虑到这些函数在跟踪和调试中所起的关键作用,我们需要在每个事件期间保存并查看尽可能多的寄存器。 - user2485710
http://courses.cms.caltech.edu/cs124/lectures/CS124Lec09.pdf 中的幻灯片21和22清晰地介绍了大多数操作系统中这个存根,基本上,“允许操作系统的中断服务程序更加统一”,“操作系统经常使用短的汇编代码存根调用它们的中断服务程序(ISR)” ~ 这张幻灯片对我很有帮助,希望对你有帮助 :) - simomo
1个回答

3
这里可以看到:

“某些特殊的系统调用需要保存完整的堆栈帧。”

我认为execve只是其中之一。
stub_execve的代码中,如果你想要hook它,至少有两种方法:
  1. 理解这些汇编代码的含义并自己完成,然后在自己的汇编代码中调用自己的函数。
  2. 在汇编代码中间部分,有一个“call sys_execve”,你可以将sys_execve的地址替换为你自己的hook函数。

第一个链接现在已经失效。 - Cel Skeggs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接