2

我正在开发一个内存跟踪库,我们使用该库mprotect来删除对程序大部分内存的访问,并使用 SIGSEGV 处理程序在程序接触到单个页面时恢复对它们的访问。这在大多数情况下都很有效。

read我的问题是,当程序使用我的库标记为不可访问的内存调用系统调用(比如)时,系统调用只返回 -1 并设置errnoEFAULT. 这会以奇怪的方式改变正在测试的程序的行为。我希望能够在系统调用实际进入内核之前恢复对系统调用的每一页内存的访问。

我目前的方法是为每个涉及内存的系统调用创建一个包装器。在将其交给真正的系统调用之前,每个包装器都会触及给它的所有内存。这似乎适用于直接从程序发出的调用,但不适用于 libc 发出的调用(例如,freadread直接调用而不使用我的包装器)。有没有更好的方法?怎么可能得到这种行为?

4

1 回答 1

5

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 at PTRACE_SYSCALL which allows you to stop the process upon syscall entry and exit.

但是,您将不得不更改一些内存跟踪基础架构,ptrace以便父进程监视子进程,并且就子进程而言,它无法看到受监视事件何时发生。话虽如此,您应该能够执行以下操作:

  • 设置 ptrace 父母和孩子,监控(至少)PTRACE_SYSCALL
  • 子进程进行系统调用;并通知家长。
  • Parent 保存请求的系统调用信息;并使用PTRACE_GETREGSandPTRACE_SETREGS来更改子状态,而不是调用系统调用;子进程调用“内存解除保护”例程。
  • 孩子不保护它的记忆;然后引发SIGUSR1或类似的告诉控制父母记忆工作已经完成。
  • 父捕获SIGUSR,用于PTRACE_SETREGS恢复先前保存的系统调用信息并恢复子。
  • Child 恢复并执行原始系统调用。
于 2009-07-02T00:01:39.753 回答