有没有办法预先避免段错误?

发布于 2024-10-04 10:46:52 字数 415 浏览 8 评论 0原文

情况如下:

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

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

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

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

Here's the situation:

I'm analysing a programs' interaction with a driver by using an LD_PRELOADed module that hooks the ioctl() system call. The system I'm working with (embedded Linux 2.6.18 kernel) luckily has the length of the data encoded into the 'request' parameter, so I can happily dump the ioctl data with the right length.

However quite a lot of this data has pointers to other structures, and I don't know the length of these (this is what I'm investigating, after all). So I'm scanning the data for pointers, and dumping the data at that position. I'm worried this could leave my code open to segfaults if the pointer is close to a segment boundary (and my early testing seems to show this is the case).

So I was wondering what I can do to pre-emptively check whether the current process owns a particular offset before trying to dereference? Is this even possible?

Edit: Just an update as I forgot to mention something that could be very important, the target system is MIPS based, although I'm also testing my module on my x86 machine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不知在何时 2024-10-11 10:46:52

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

Open a file descriptor to /dev/null and try write(null_fd, ptr, size). If it returns -1 with errno set to EFAULT, the memory is invalid. If it returns size, the memory is safe to read. There may be a more elegant way to query memory validity/permissions with some POSIX invention, but this is the classic simple way.

一紙繁鸢 2024-10-11 10:46:52

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

If your embedded linux has the /proc/ filesystem mounted, you can parse the /proc/self/maps file and validate the pointer/offsets against that. The maps file contains the memory mappings of the process, see here

晚风撩人 2024-10-11 10:46:52

据我所知没有这种可能性。但你也许能够实现类似的目标。正如man 7 signal提到的,SIGSEGV可以被捕获。因此,我认为您可以

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

这有几个问题。

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

未经测试。

I know of no such possibility. But you may be able to achieve something similar. As man 7 signal mentions, SIGSEGV can be caught. Thus, I think you could

  1. Start with dereferencing a byte sequence known to be a pointer
  2. Access one byte after the other, at some time triggering SIGSEGV
  3. In SIGSEGV's handler, mark a variable that is checked in the loop of step 2
  4. Quit the loop, this page is done.

There's several problems with that.

  • Since several buffers may live in the same page, you might output what you think is one buffer that are, in reality, several. You may be able to help with that by also LD_PRELOADing electric fence which would, AFAIK cause the application to allocate a whole page for every dynamically allocated buffer. So you would not output several buffers thinking it is only one, but you still don't know where the buffer ends and would output much garbage at the end. Also, stack based buffers can't be helped by this method.
  • You don't know where the buffers end.

Untested.

南巷近海 2024-10-11 10:46:52

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

如果是这样,页边界就被很好地界定了(4K 或 8K),因此简单的地址屏蔽应该可以处理它。

Can't you just check for the segment boundaries? (I'm guessing by segment boundaries you mean page boundaries?)

If so, page boundaries are well delimited (either 4K or 8K) so simple masking of the address should deal with it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文