3

情况如下:

我正在通过使用挂钩 ioctl() 系统调用的 LD_PRELOADed 模块来分析程序与驱动程序的交互。我正在使用的系统(嵌入式 Linux 2.6.18 内核)幸运地具有编码到“请求”参数中的数据长度,因此我可以愉快地转储具有正确长度的 ioctl 数据。

然而,很多这些数据都有指向其他结构的指针,我不知道这些数据的长度(毕竟这是我正在调查的内容)。所以我正在扫描数据中的指针,并将数据转储到那个位置。我担心如果指针靠近段边界(我的早期测试似乎表明情况如此),这可能会使我的代码对段错误开放。

所以我想知道在尝试取消引用之前我可以做些什么来先发制人地检查当前进程是否拥有特定的偏移量?这甚至可能吗?

编辑:只是一个更新,因为我忘了提到一些可能非常重要的东西,目标系统是基于 MIPS 的,尽管我也在我的 x86 机器上测试我的模块。

4

4 回答 4

3

打开文件描述符/dev/null并尝试write(null_fd, ptr, size). 如果它返回 -1 并errno设置为EFAULT,则内存无效。如果返回size,则内存可以安全读取。使用一些 POSIX 发明可能有一种更优雅的方式来查询内存有效性/权限,但这是经典的简单方式。

于 2010-11-28T19:16:52.240 回答
1

如果您的嵌入式 linux 安装了 /proc/ 文件系统,您可以解析 /proc/self/maps 文件并验证指针/偏移量。maps 文件包含进程的内存映射,请参见此处

于 2010-11-28T18:56:25.800 回答
0

你不能只检查段边界吗?(我猜段边界是指页面边界?)

如果是这样,页面边界被很好地分隔(4K 或 8K),所以简单的地址掩码应该可以处理它。

于 2010-11-28T19:33:05.920 回答
0

我知道没有这种可能性。但是您也许可以实现类似的目标。如前所述man 7 signalSIGSEGV可以被抓住。因此,我认为你可以

  1. 从取消引用已知为指针的字节序列开始
  2. 一个接一个地访问,有时触发SIGSEGV
  3. SIGSEGV的处理程序中,标记在步骤 2 的循环中检查的变量
  4. 退出循环,这个页面就完成了。

这有几个问题。

  • 由于多个缓冲区可能存在于同一页面中,因此您可能会输出您认为是一个缓冲区的内容,但实际上是多个缓冲区。您可以通过电子围栏来帮助解决这个问题LD_PRELOAD,AFAIK 会导致应用程序为每个动态分配的缓冲区分配整个页面。所以你不会输出几个缓冲区,认为它只是一个,但你仍然不知道缓冲区在哪里结束,最后会输出很多垃圾。此外,此方法无法帮助基于堆栈的缓冲区。
  • 你不知道缓冲区在哪里结束。

未经测试。

于 2010-11-28T18:41:28.610 回答