【问题标题】:Hijacking sys calls劫持系统调用
【发布时间】:2013-03-30 11:22:35
【问题描述】:

我正在编写一个内核模块,我需要劫持/包装一些系统调用。我正在暴力破解 sys_call_table 地址,并且我正在使用 cr0 禁用/启用页面保护。到目前为止一切顺利(一旦完成,我会公开整个代码,所以如果有人愿意,我可以更新这个问题)。

无论如何,我注意到如果我劫持__NR_sys_read,当我卸载内核模块时,我会收到内核错误,并且所有 konsoles (KDE) 都会崩溃。请注意,__NR_sys_open__NR_sys_write 不会发生这种情况。

我想知道为什么会这样。有什么想法吗?

PS:请不要走 KProbes 的方式,我已经知道了,我不可能使用它,因为最终产品应该可以在无需重新编译整个内核的情况下使用。

编辑:(添加信息)

我在卸载前恢复了原来的功能。此外,我还创建了两个测试用例,一个仅使用_write,一个使用_read。带有_write 的那个可以正常卸载,但是带有_read 的那个会卸载然后导致内核崩溃。

编辑:(源代码)

我现在在家,所以我现在不能发布源代码,但是如果有人想要,我可以在我开始工作后立即发布示例代码。 (约 5 小时)

【问题讨论】:

  • 卸载模块时是否恢复旧处理程序?
  • 是的,我恢复它。 (我可以成功恢复所有 3 个,但 恢复 _read 后失败)

标签: c linux kernel kernel-module system-calls


【解决方案1】:

这可能是因为内核线程当前位于 read 中 - 如果调用您的读取钩子不会锁定模块,则无法安全卸载它。

这可以解释“konsoles”(?)崩溃,因为它们可能当前正在执行read 系统调用,等待数据。当它们从实际的系统调用返回时,它们会跳转到您的函数曾经所在的位置,从而导致问题。

卸载会很乱,但是需要先把钩子去掉,然后等待所有调用者退出钩子函数,再卸载模块。

我最近一直在玩 linux syscall hooking,但我绝不是内核专家,所以如果这不正常,我很抱歉。

PS: This technique 可能比暴力破解 sys_call_table 更可靠。如果sys_close 已经被钩住,我见过的蛮力技术往往会导致内核恐慌。

【讨论】:

  • github 链接看起来很有趣!我需要更好地阅读它,但我想我将通过蛮力方法切换到它。关于另一个问题,我怎样才能等待所有来电者退出?我的意思是,我可以写一些糟糕的方法来计算读取/关闭,但也许你知道有更好的方法?问候
  • 我希望我有一个更好的答案。可以看到一个example of really dodgy looking locking here和一个discussion of try_module_get/module_put here,大体思路要么是unhook,然后在unload函数中等待,直到锁被释放,然后return。我不确定正确的锁定结构是什么,但我想在 SO 上有很好的并发人员。它也可能使卸载需要很长时间。
  • 这些链接看起来也很有趣(顺便说一句,我在您的第一个答案中尝试了链接中的代码,并且我已经切换到它)。也许我应该提出另一个关于如何安全卸载模块的问题?
  • +1 用于安全卸载和引用计数,因为在读取系统进程时可能会被长时间阻塞。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-10
  • 2019-05-16
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多