2

私はmprotect、プログラムのほとんどのメモリへのアクセスを削除するために使用するメモリ追跡ライブラリと、プログラムがページにアクセスしたときに個々のページへのアクセスを復元するためのSIGSEGVハンドラーに取り組んでいます。これはほとんどの場合うまく機能します。

私の問題は、私のライブラリがアクセスをマークしていないメモリを使用してプログラムがシステムコール(たとえばread)を呼び出すと、システムコールは-1を返し、に設定errnoすることEFAULTです。これにより、テスト対象のプログラムの動作が奇妙な方法で変更されます。システムコールが実際にカーネルに送られる前に、システムコールに与えられたメモリの各ページへのアクセスを復元できるようにしたいと思います。

私の現在のアプローチは、メモリにアクセスする各システムコールのラッパーを作成することです。各ラッパーは、実際のシステムコールに渡す前に、与えられたすべてのメモリにアクセスします。これは、プログラムから直接行われた呼び出しでは機能するようですが、libcで行われた呼び出しでは機能しないようです(たとえば、ラッパーを使用せずに直接fread呼び出します)。readより良いアプローチはありますか?どうすればこの振る舞いを得ることができますか?

4

1 に答える 1

5

これを達成するために使用できますptrace(2)。これにより、プロセスを監視し、特定のイベントが発生するたびに通知を受けることができます。あなたの目的のために、PTRACE_SYSCALLあなたがsyscallの開始と終了時にプロセスを停止することを可能にするものを見てください。

ただし、親プロセスが子プロセスを監視するように動作するため、メモリ追跡インフラストラクチャの一部を変更する必要があります。ptrace子に関する限り、監視対象のイベントがいつ発生するかはわかりません。そうは言っても、次のようなことができるはずです。

  • ptraceの親と子を設定し、(少なくとも)監視しPTRACE_SYSCALLます。
  • 子プロセスはシステムコールを実行します。親に通知されます。
  • 親は要求されたシステムコール情報を保存します。syscallを呼び出す代わりに、とを使用PTRACE_GETREGSPTRACE_SETREGSて子の状態を変更します。子プロセスは「memoryunprotect」ルーチンを呼び出します。
  • 子供の保護を解除するのは記憶です。次にSIGUSR1、メモリ作業が完了したことを制御する親に通知するために発生します。
  • 親はキャッチし、以前に保存されたシステムコール情報を復元するためSIGUSRに使用し、子を再開します。PTRACE_SETREGS
  • 子は元のシステムコールを再開して実行します。
于 2009-07-02T00:01:39.753 に答える