可能なすべてのアドレスでメモリを読み取ろうとするプログラムを作成し、それを「完全な」Unixで実行すると、すべての物理RAMにアクセスできなくなります。しかし、オペレーティングシステムはそれをどのようにして防止していますか?
私は、任意のアセンブリコードがすべてにアクセスできる小さなCPUアーキテクチャに慣れています。プログラム(カーネル)がこのような悪意のある操作を検出する方法を理解していません。
可能なすべてのアドレスでメモリを読み取ろうとするプログラムを作成し、それを「完全な」Unixで実行すると、すべての物理RAMにアクセスできなくなります。しかし、オペレーティングシステムはそれをどのようにして防止していますか?
私は、任意のアセンブリコードがすべてにアクセスできる小さなCPUアーキテクチャに慣れています。プログラム(カーネル)がこのような悪意のある操作を検出する方法を理解していません。
回答:
不正なメモリアクセスを防止しているのはカーネルではなく、CPUです。カーネルの役割は、CPUを正しく構成することだけです。
より正確には、不正なメモリアクセスを防止するハードウェアコンポーネントはMMUです。プログラムがメモリアドレスにアクセスすると、そのアドレスはMMUの内容に基づいてCPUによってデコードされます。MMUは、仮想アドレスから物理アドレスへの変換を確立します。CPUが特定の仮想アドレスでロードまたはストアを実行すると、MMUの内容に基づいて対応する物理アドレスを計算します。カーネルは、各プログラムが資格のあるメモリにのみアクセスできるようにMMU構成を設定します。他のプログラムのメモリとハードウェアレジスタは、プログラムのメモリにまったくマップされません。これらの物理アドレスには、そのプログラムのMMU構成に対応する仮想アドレスがありません。
異なるプロセス間のコンテキストスイッチでは、カーネルはMMU構成を変更して、新しいプロセスに必要な変換が含まれるようにします。
一部の仮想アドレスはまったくマップされません。つまり、MMUはそれらを特別な「そのようなアドレスなし」の値に変換します。プロセッサがマップされていないアドレスを逆参照すると、これによりトラップが発生します。プロセッサはカーネルコード内の事前定義された場所に分岐します。一部のトラップは正当です。たとえば、仮想アドレスはスワップ空間にあるページに対応する可能性があります。その場合、カーネルコードはスワップからページコンテンツをロードし、メモリアクセス命令が再度実行されるように元のプログラムに切り替えます。他のトラップは正当ではありません。この場合、プロセスはデフォルトでプログラムを強制終了するシグナルを受け取ります(プログラム内のシグナルハンドラーに分岐しない場合は、メモリアクセス命令は完了しません)。