当给定受保护内存时,如何使系统调用调用我的 SIGSEGV 处理程序?
我正在开发一个内存跟踪库,我们使用 mprotect 来删除对程序大部分内存的访问,并使用 SIGSEGV 处理程序在程序接触各个页面时恢复对各个页面的访问。 这在大多数情况下都非常有效。
我的问题是,当程序使用我的库标记为不可访问的内存调用系统调用(例如 read
)时,系统调用仅返回 -1 并将 errno 设置为EFAULT
。 这以奇怪的方式改变了正在测试的程序的行为。 我希望能够在系统调用实际进入内核之前恢复对系统调用的每个内存页的访问。
我当前的方法是为每个涉及内存的系统调用创建一个包装器。 每个包装器在将其交给真正的系统调用之前都会接触分配给它的所有内存。 看起来这适用于直接从程序进行的调用,但不适用于 libc 进行的调用(例如,fread
将直接调用 read
而不使用我的包装器)。 有没有更好的方法? 怎么可能得到这种行为?
I'm working on a memory tracking library where we use mprotect
to remove access to most of a program's memory and a SIGSEGV handler to restore access to individual pages as the program touches them. This works great most of the time.
My problem is that when the program invokes a system call (say read
) with memory that my library has marked no access, the system call just returns -1 and sets errno
to EFAULT
. This changes behavior of the programs being tested in strange ways. I would like to be able to restore access to each page of memory given to a system call before it actually goes to the kernel.
My current approach is to create a wrapper for each system call that touches memory. Each wrapper would touch all the memory given to it before handing it off to the real system call. It seems like this will work for calls made directly from the program, but not for those made by libc (for instance, fread
will call read
directly without using my wrapper). Is there any better approach? How is it possible to get this behavior?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以使用
ptrace(2)
来实现此目的。 它允许您监视进程并在发生某些事件时得到通知。 出于您的目的,请查看PTRACE_SYSCALL
,它允许您在系统调用进入和退出时停止进程。但是,您必须更改一些内存跟踪基础设施,因为 ptrace 的运行方式是让父进程监视子进程,并且就子进程而言,它无法了解何时发生发生受监视的事件。 话虽如此,您应该能够执行以下操作:
PTRACE_SYSCALL
。SIGUSR1
或类似的信号来告诉控制父内存工作已完成。SIGUSR
,使用PTRACE_SETREGS
恢复之前保存的系统调用信息并恢复子级。You can use
ptrace(2)
to achieve this. It allows you to monitor a process and get told whenever certain events occur. For your purposes, look atPTRACE_SYSCALL
which allows you to stop the process upon syscall entry and exit.You will have to change some of your memory tracking infrastructure, however, as
ptrace
operates such that a parent process monitors a child process, and as far as the child is concerned it doesn't have visibility of when a monitored event occurs. Having said that, you should be able to do something along the lines of:PTRACE_SYSCALL
.PTRACE_GETREGS
andPTRACE_SETREGS
to change child state so instead of calling the syscall; the child process calls the 'memory unprotect' routine.SIGUSR1
or similar to tell controlling parent that the memory work is complete.SIGUSR
, usesPTRACE_SETREGS
to restore the previouly-saved syscall info and resumes the child.