5

Linuxプロセスのアドレス空間内のすべてのページを(プロセス自体の内部から)書き込み保護する方法があるかどうか疑問に思っています mprotect()。「すべてのページ」とは、実際には、ユーザーモードで実行されている通常のプログラムによって書き込まれる可能性のあるプロセスのアドレス空間のすべてのページを意味します。つまり、プログラムテキスト、定数、グローバル、およびヒープですが、私は定数、グローバル、ヒープだけで満足するでしょう。スタックを書き込み保護したくない-それは悪い考えのようです。

1つの問題は、書き込み保護メモリをどこから始めればよいかわからないことです。特定のpidで使用されているメモリのセクションを示すを見ると/proc/pid/maps、それらは常にアドレス 0x08048000とプログラムテキストで始まっているように見えます。(Linuxでは、私が知る限り、プロセスのメモリは、下部にプログラムテキストがあり、その上に定数があり、次にグローバル、次にヒープ、そしてサイズに応じてさまざまなサイズの空きスペースが配置されています。ヒープまたはスタックの先頭に移動し、スタックが仮想アドレスのメモリの先頭から下に向かって成長します0xffffffff。)ヒープの先頭がどこにあるかを確認する方法があります(を呼び出すとsbrk(0)、現在の「ブレーク」へのポインタが返されます。つまり、ヒープの最上部)ですが、実際にはヒープがどこから始まるかを知る方法ではありません。

休憩まですべてのページを保護しようとすると0x08048000、最終的にmprotect: Cannot allocate memoryエラーが発生します。とにかくなぜメモリを割り当てるのかわかりませんmprotect-そしてGoogleはあまり役に立ちません。何か案は?

ちなみに、これをやりたいのは、プログラムの実行中に書き込まれるすべてのページのリストを作成したいからです。これを行うために考えられる方法は、すべてを書き込み保護することです。ページを作成し、書き込みを試行すると書き込み障害が発生するようにしてから、ページをリストに追加して書き込み保護を削除する書き込み障害ハンドラーを実装します。保護するページとその方法を理解できれば、ハンドラーの実装方法を知っていると思います。

ありがとう!

4

2 に答える 2

6

マップされていないページでそれを呼び出そうとすると、ENOMEMから受け取ります。mprotect()

最善の策は、を開き/proc/self/maps、一度に1行ずつ読んで、fgets()プロセス内のすべてのマッピングを見つけることです。スタック(最後のフィールドに示されている)ではない書き込み可能なマッピング(2番目のフィールドに示されている)ごとにmprotect()、正しいベースアドレスと長さ(最初のフィールドの開始アドレスと終了アドレスから計算)を使用して呼び出します。

この時点で、フォールトハンドラーを既に設定しておく必要があることに注意してください。これは、mapsファイル自体を読み取る動作によって、アドレス空間内に書き込みが発生する可能性があるためです。

于 2010-08-10T00:14:03.817 に答える
0

簡単に始めましょう。いくつかのページを書き込み保護し、シグナルハンドラがこれらのページで機能することを確認します。次に、保護の範囲を拡大することを心配します。たとえば、コードセクションを書き込み保護する必要はおそらくありません。オペレーティングシステムは、メモリに書き込みまたは実行保護セマンティクスを実装して、コードセクションが次の場所に書き込まれないようにすることができます。

于 2010-08-09T21:08:16.597 に答える