【问题标题】:How to hook syscall table at runtime on PPC Linux?如何在 PPC Linux 上运行时挂钩系统调用表?
【发布时间】:2011-03-31 20:19:56
【问题描述】:

主题: PPC 汇编语言 - Linux 可加载内核模块

详情:在系统调用表钩子中从内核调用时如何访问本地 TOC 区域(r2)?

我为 Linux 编写了一个可加载的内核模块,它使用系统调用表挂钩来拦截系统调用并记录有关它们的信息,然后再将调用传递给原始处理程序。这是安全产品的一部分。我的模块运行良好,并且在生产代码中运行在各种 Linux 内核版本和发行版上,32 位和 64 位内核都在 x86 硬件上运行。

我正在尝试移植此代码以在 Linux 上为 PPC 处理器运行,但遇到了一些问题。使用 Linux 内核源代码,很容易看出系统调用表在 PPC 上的实现方式有何不同。我可以用我自己编译的处理程序中的函数地址替换表中的条目,没问题。

但是,这是我遇到的问题。 PPC ABI 使用称为目录 (TOC) 地址的东西,该地址存储在 CPU 的 R2 寄存器中,并希望通过使用该寄存器中包含的地址(TOC 地址)的偏移量来寻址模块的全局和本地数据。这在进行函数调用的正常情况下工作正常,因为编译器知道在进行调用之前将模块的 TOC 地址加载到寄存器中(或者它已经存在,因为通常您的函数是由您自己的代码调用的)。

但是,当我将自己的函数地址(在运行时从我加载的内核模块中)放入系统调用表时,内核调用我的处理程序时使用的 R2 值不是我编译的 C 代码所期望的值,所以我的代码在无法访问其数据的情况下获得控制权。

有人知道那里有任何示例代码来说明如何处理这种情况吗?我无法重新编译内核。这应该是运行时系统调用表挂钩的简单案例,但我还没有弄清楚,或者找到任何特定于 PPC 的示例。

想法包括:

手工编码一个汇编语言存根,它保存 R2 值,用我的本地 TOC 地址加载寄存器,执行我的代码,然后在调用原始处理程序之前恢复旧值。我没有 PPC 组装经验的深度来做这件事,我也不确定它会起作用。

一些神奇的 gcc 选项可以在不使用 TOC 的情况下生成我的代码。有一个记录在案的 gcc 选项 "-mno-toc" 在我的 PPC6 Linux 上不起作用。看起来它可能只是系统 V.4 和嵌入式 PowerPC 的一个选项。

非常感谢任何帮助!

谢谢!

【问题讨论】:

  • 恐怕我对解决方案没有任何建议,但您知道内核开发人员始终难以修改系统调用表吗?这不是他们想要通过内部 API 支持的东西。

标签: linux-kernel kernel-module system-calls powerpc hook


【解决方案1】:

您需要一个存根来加载r2。内核源码中有例子。

【讨论】:

    【解决方案2】:

    Linux 有一个通用的系统调用审计基础架构,可以在 powerpc 上运行,您可以从用户空间访问。您是否考虑过使用它而不是编写内核模块?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-23
      • 2011-01-07
      • 2015-09-16
      • 2021-04-14
      • 1970-01-01
      • 1970-01-01
      • 2021-01-08
      • 1970-01-01
      相关资源
      最近更新 更多