2009-07-01 19 views
2

我正在研究一個內存跟蹤庫,我們使用mprotect來刪除對大部分程序內存的訪問以及一個SIGSEGV處理程序,以便在程序觸及時恢復對單個頁面的訪問。這在大多數情況下都很有效。如何在給定受保護的內存時使系統調用調用我的SIGSEGV處理程序?

我的問題是,程序調用系統調用(比如read)與我的圖書館沒有標明存取存儲器時,系統調用只是返回-1,並將errnoEFAULT。這以奇怪的方式改變了正在測試的程序的行爲。我希望在實際進入內核之前能夠恢復對系統調用的每個內存頁面的訪問。

我目前的做法是爲每個接觸內存的系統調用創建一個包裝。每個包裝器在將其交給真正的系統調用之前都會觸及給予它的所有內存。看起來這樣可以直接從程序中調用,但不適用於由libc創建的調用(例如,fread將直接調用read而不使用我的包裝)。有沒有更好的方法?怎麼可能得到這種行爲?

+0

那真是愚蠢。當系統調用無效內存時,誰期望EFAULT而不是段錯誤? :P看起來像系統調用和用戶空間函數之間的隨機不一致...... – 2012-03-07 16:08:51

回答

5

您可以使用ptrace(2)來實現此目的。它允許您監視進程並在發生特定事件時得到通知。出於您的目的,請查看PTRACE_SYSCALL,它允許您在系統調用進入和退出時停止進程。

但是,您必須更改一些內存跟蹤基礎結構,因爲ptrace的操作使得父進程監視子進程,並且就兒童而言,它無法識別受監視事件的時間發生。話雖如此,你應該可以做一些事情:

  • 安裝ptrace父母和孩子,監視(至少)PTRACE_SYSCALL
  • 子進程執行系統調用;並通知家長。
  • Parent保存請求的系統調用信息;並使用PTRACE_GETREGSPTRACE_SETREGS來更改子狀態,而不是調用系統調用;子進程調用'內存解除保護'例程。
  • 孩子不保護它的記憶;然後提出SIGUSR1或類似的告訴控制父母內存工作已完成。
  • 父級漁獲SIGUSR,使用PTRACE_SETREGS恢復以前保存的系統調用信息並恢復孩子。
  • 孩子恢復並執行原始系統調用。
+0

http://lkml.org/lkml/2008/8/25/40有一些實驗允許你自己使用ptrace來捕捉你自己的系統調用。 ..但是,這個多進程舞蹈通常是必要的。 – ephemient 2009-07-02 00:21:12

相關問題