有没有办法预先避免段错误?
情况如下:
我正在使用挂钩 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
打开一个文件描述符到
/dev/null
并尝试write(null_fd, ptr, size)
。如果它返回 -1 并且errno
设置为EFAULT
,则内存无效。如果它返回size
,则内存可以安全读取。可能有一种更优雅的方法来通过某些 POSIX 发明来查询内存有效性/权限,但这是经典的简单方法。Open a file descriptor to
/dev/null
and trywrite(null_fd, ptr, size)
. If it returns -1 witherrno
set toEFAULT
, the memory is invalid. If it returnssize
, 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.如果您的嵌入式 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
据我所知没有这种可能性。但你也许能够实现类似的目标。正如
man 7 signal
提到的,SIGSEGV
可以被捕获。因此,我认为您可以SIGSEGV
SIGSEGV
的处理程序中,标记步骤 2 的循环中检查的变量这有几个问题。
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 couldSIGSEGV
SIGSEGV
's handler, mark a variable that is checked in the loop of step 2There's several problems with that.
LD_PRELOAD
ing 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.Untested.
你不能只检查段边界吗? (我猜段边界是指页边界吗?)
如果是这样,页边界就被很好地界定了(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.