web-dev-qa-db-ja.com

OSがメモリアクセス違反を検出する方法

オペレーティングシステム(できればLinux)は、許可されていないメモリ位置にアクセスしたことをどのようにして認識しますか?

この質問は、それらのいまいましいポインタに触発されました!私の見方では、コンピューターのすべては、速度、セキュリティ、整合性などの間の妥協点です。

Linuxのメモリマップについてはよく知っていますが、アクセスしようとする場所が有効な範囲内にあるかどうかをカーネルがチェックするのは、アクセスするたびに少しばかげているように思えます。非常に多くの時間を浪費するように思われ、より生産的な何かを行うために費やされる可能性があります(ただし、チェックしないと安全性が低下する可能性があります!)。または、最近のすべてのアクセスを記憶し、ハードウェアタイマーのティックごとにチェックしますか? (しかし、それは安全ではないように聞こえますが、やはり遅いです。)

この質問はどこにも答えられていないように見えることに私は驚いた。それは私がいつも疑問に思っていたものです。 OSに代わってこれを行うハードウェアのセクションがあり、便利な抽象化レベルになっていると思います。しかし、それでも、すべてのコンテキストスイッチで次のプロセスのメモリマップをロードする必要がある可能性があり、これもまた遅いように聞こえます。

そうです、とにかく、私は少し進んでいます:OSはどのようにしてメモリ違反を検出しますか?

ありがとう

13
Doddy

(次の回答は、「最新の」デスクトップ、サーバー、または上位の組み込みプラットフォーム(スマートフォン、およびますます小規模なシステムなど)を想定しています。x86システムの場合、最新は386以上を意味します。 。次の回答も、ほぼすべてのUNIXなどの「最新の」OS、または95以降のWindowsを想定しています。)

これはOSでは発生していません。プロセッサ、特に [〜#〜] mmu [〜#〜]で発生しています。 (メモリ管理ユニット 。 MMUは仮想アドレス指定をサポートしているため、ポインタを構成するビットは、メモリ内のビットの物理的な場所を直接示しません。

典型的なMMUでは、ポインタが逆参照されると、MMUはビットを2つのグループに分解します。上位ビットはページ番号、および下位ビットがページ内のアドレスを構成します。ほとんどのデスクトップおよびサーバーマシンは4kBページを使用します。MMUは、仮想ページ番号を検索します。 [〜#〜] tlb [〜#〜] というテーブル(これを「プロセスメモリマップ」と呼びます)。TLBは、この仮想ページに対応する物理ページの番号を示します。 MMUは、メモリ内の物理ページからデータをフェッチします。

TLBにこの特定の仮想ページ番号のエントリが含まれていない場合、MMUは、無効なアクセスが発生したことをプロセッサに通知します。これは通常、例外と呼ばれます。

これまでOSについては触れていません。これは、このすべての操作がOSから独立しているためです。 OSは、次の2つの方法で構成するために機能します。

  • OSはタスクの切り替えを担当します。そうすると、ご想像のとおり、現在のTLBが保存され、次にスケジュールされたタスクのために保存されたTLBに置き換えられます。このように、各プロセスにはTLBがあるため、プロセスXのアドレス0x123456は、プロセスYの同じアドレスと同じRAM)の実際の場所を指していないか、単に無効である可能性があります。 。プロセスがアドレス空間外のポインタを逆参照しようとすると、別のプロセスの空間に到達せず、nowhereに到達します。

  • OSは、例外が発生したときに何が起こるかを決定します。無効なメモリアクセス(セグメンテーション違反、一般保護違反など)を実行するプロセスを終了する可能性があります。これは、スワッピングを実装する方法でもあります。例外ハンドラーは、スワップスペースからデータをフェッチし、それに応じてTLBを更新して、アクセスを再実行することを決定する場合があります。

MMUは、プロセスが独自のTLBを変更できないため、セキュリティを提供することに注意してください。TLBを変更できるのはOSカーネルのみです。TLB変更権限がどのように機能するかは、この回答の範囲を超えています。

1)セグメンテーション違反は、メモリ管理ユニットによって検出されます。メモリを要求すると、OSはメモリ管理ユニットにハードウェアからメモリを取得するように要求します。 OSが提供するすべての大きなメモリブロックを追跡するものが必要です。 OSはそれをMMUに渡します。提供されたすべてのメモリを認識しているため、割り当てから取得できなかったメモリの場所にアクセスしようとしたときにも通知されます。OSには、このためのイベント、つまり所有していないメモリがあります。最終的に、OSはアプリを強制終了し、他のOSでセグメンテーション違反または同等のものをトリガーします。

すべてのOSがこの保護を備えているわけではありません。 MMUはこれをサポートしていましたが、9までのMacOSにはこれがありませんでした。Win3.1もサポートしていませんでした。Win95は保護なしと追加の間で移行したため、ある程度の保護がありました。 。

2)OSはこれ以外の詳細を知りません。割り当てたことのないメモリにアクセスする漂遊ポインタがある場合は、それがわかります。アプリケーションの別の部分に入るものがある場合、それはもちろんわかりません。これを壊すことができます。これは、アプリからの漂遊ポインターがアプリの他の部分を上書きして、破損したスタックを取得する場所です。

だから、はい、あなたはあなた自身のデータを台無しにすることができます。自分のアプリを上書きする迷いポインターがある場合は、スタックにヒットすることを望んでいます。スタックから戻ろうとすると別の違反が発生する可能性があるためですが、自分のデータにヒットした場合はわかりません。

「保護なし」よりも厳密にしようとすることができます。電気柵( http://perens.com/FreeSoftware/ElectricFence/ )と呼ばれるツールがあり、MMUもう少し機能し、より多くの障害を検出するようにします。

6
Rich Homolka