私の知る限り、カーネルモードコードは利用可能な任意のアドレス(高い特権)にアクセスできますが、ユーザーモードポインターをカーネルモード関数に渡すと、使用する前に変更されますか?つまり、ユーザーモードの場合と同じように、ページング/セグメンテーションシステム(またはロングモードのページング)で解決されますか?
1 に答える
まず第一に、「カーネルモード関数へのポインタを提供する」ことはしません。カーネル呼び出しは単純なジャンプではなく、特別な命令またはソフトウェア割り込みのいずれかです。カーネル関数の呼び出し規約も、通常の関数呼び出しとは異なります。
いずれにせよ、カーネルコンテキストからユーザーメモリにアクセスする方法は、問題のオペレーティングシステムによって異なります。カーネルには通常、独自の(仮想)アドレス空間があります。これは、ユーザープロセススペース(32ビットOSXなど)から完全に独立したアドレススペースにすることも、特別な領域(多くのOSで高/低アドレス分割)に配置することもできます。高/低モデルでは、カーネルは通常、そのプロセスのコンテキストで実行されている間、ユーザースペースへのポインターを逆参照できます。一般的なケースでは、カーネルは、ユーザーの仮想アドレスが参照する基礎となる物理メモリを明示的に検索し、それを独自の仮想アドレス空間にマップできます。
ユーザースペースは悪意を持って不正なポインターを提供する可能性があるため、最初に有効性を確認せずにカーネルがそれらを使用してはなりません。これ以降のアクセスは、ユーザープロセスのメモリマップに関してアトミックである必要があります。そうでない場合、プロセスはmunmap()
、カーネルのポインタの有効性チェックから実際にメモリの読み取り/書き込みまでの時間範囲になる可能性があります。このため、ほとんどのカーネルにはmemcpy
、ユーザー空間とカーネル空間の間で本質的に安全なヘルパー関数があり、安全であることが保証されているか、無効なポインターの場合にエラーを返します。
いずれにせよ、カーネルコードはこれらすべてを明示的に実行する必要があり、「自動」なものは何もありません。もちろん、システムコールは、カーネルモジュールに到達する前にこれを自動化する抽象化レイヤーを通過する場合があります。
更新:最新のハードウェアは、カーネルからユーザーアドレス空間へのポインターの偶発的/悪意のある逆参照を防ぐように設計されたSMAP(スーパーバイザーモードアクセス防止)をサポートしています。さまざまなオペレーティングシステムがこの機能を有効にし始めているため、そのような場合は、ユーザーメモリにアクセスするための特別なカーネル機能を絶対に実行する必要があります。