在给定受保护的内存时,如何使系统调用调用我的SIGSEGV处理程序?

Jay*_*rod 2 linux memory system-calls segmentation-fault

我正在开发一个内存跟踪库,mprotect用于删除对大多数程序内存的访问,以及一个SIGSEGV处理程序,以便在程序触及时恢复对各个页面的访问.这在大多数情况下都很有效.

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

我目前的方法是为每个触及内存的系统调用创建一个包装器.在将其交给真实系统调用之前,每个包装器将触摸给它的所有内存.看起来这对于直接从程序进行的调用是有效的,但不适用于由libc进行的fread调用(例如,read不使用我的包装器直接调用).有没有更好的方法?怎么可能得到这种行为?

Dav*_*veR 5

你可以用它ptrace(2)来实现这一目标.它允许您监视进程并在发生某些事件时得到通知.为了您的目的,请查看PTRACE_SYSCALL哪个允许您在系统调用进入和退出时停止进程.

但是,您必须更改某些内存跟踪基础结构,因为ptrace父进程会监视子进程,并且就子进程而言,它不会查看受监视事件发生的时间.话虽如此,你应该能够做到以下几点:

  • 设置ptrace父和子,监控(至少)PTRACE_SYSCALL.
  • 子进程执行系统调用; 和父母通知.
  • 父保存请求的系统调用信息; 并使用PTRACE_GETREGSPTRACE_SETREGS更改子状态,而不是调用系统调用; 子进程调用'memory unprotect'例程.
  • 孩子取消保护它的记忆; 然后提升SIGUSR1或类似告诉控制父母内存工作完成.
  • Parent catch SIGUSR,用于PTRACE_SETREGS恢复之前保存的系统调用信息并恢复孩子.
  • 孩子恢复并执行原始系统调用.