vsyscall およびvDSO セグメントは、Linux で特定のシステム コールを高速化するために使用される 2 つのメカニズムです。たとえば、gettimeofday
通常、このメカニズムを通じて呼び出されます。最初に導入されたメカニズムは vsyscall でした これは、システム コールのオーバーヘッドを削減するために、実際の特権レベルを必要としない特定のシステム コールを実行する方法として追加されました。前の例に従って、すべての gettimeofday
行う必要があるのは、カーネルの現在の時刻を読み取ることです。 gettimeofday
を呼び出すアプリケーションがあります 頻繁に(たとえば、タイムスタンプを生成するため)、オーバーヘッドが少しでも気になるところまで。この問題に対処するために、カーネルは現在の時刻と高速な gettimeofday
を含むページをユーザー空間にマップします。 実装 (つまり、保存された時間を vsyscall に読み込む関数 )。この仮想システム コールを使用して、C ライブラリは高速な gettimeofday
を提供できます。 通常、従来のシステム コール モデル INT 0x80
によって導入される、カーネル空間とユーザー空間の間のコンテキスト スイッチによって導入されるオーバーヘッドはありません。 または SYSCALL
.
ただし、この vsyscall メカニズムにはいくつかの制限があります。割り当てられるメモリは小さく、システム コールは 4 つしか許可されません。さらに重要かつ深刻なのは、vsyscall ページは、vsyscall の場所から、各プロセスで同じアドレスに静的に割り当てられます。 ページはカーネル ABI で釘付けにされます。この vsyscall の静的な割り当ては、Linux で一般的に使用されるメモリ空間のランダム化によってもたらされる利点を損なうものです。攻撃者は、スタック オーバーフローを悪用してアプリケーションを侵害した後、vsyscall からシステム コールを呼び出すことができます。 任意のパラメータを持つページ。彼が必要とするのは、システム コールのアドレスだけです。これは静的に割り当てられるため、簡単に予測できます (別のアプリケーションでもコマンドを再度実行しようとすると、vsyscall このタイプの攻撃を阻止するために、vsyscall ページの場所を削除するか、少なくともランダム化するとよいでしょう。残念ながら、アプリケーションはそのページの存在と正確なアドレスに依存しているため、何もできません.
このセキュリティの問題は、固定アドレスにあるすべてのシステム コール命令を特別なトラップ命令に置き換えることで対処されています。 vsyscall を呼び出そうとするアプリケーション ページはカーネルにトラップされ、カーネル空間で目的の仮想システム コールをエミュレートします。その結果、仮想システム コールをエミュレートするカーネル システム コールが生成されます。このカーネル システム コールは、最初にカーネル システム コールを回避するために配置されました。結果は vsyscall です これは実行に時間がかかりますが、重要なことに、既存の ABI を壊しません。いずれにせよ、スローダウンは、アプリケーションが vsyscall を使用しようとしている場合にのみ見られます。 vDSO の代わりのページ .
vDSO その制限を克服しながら、vsyscall と同じ機能を提供します。 vDSO (Virtual Dynamically linked Shared Objects) は、ユーザー空間に割り当てられたメモリ領域であり、安全な方法で一部のカーネル機能をユーザー空間に公開します。これは、vsyscall
によって引き起こされるセキュリティ上の脅威を解決するために導入されました。 .vDSO は動的に割り当てられ、セキュリティの問題を解決し、4 つ以上のシステム コールを持つことができます。 vDSO リンクは glibc ライブラリ経由で提供されます。リンカーは glibc vDSO でリンクします ただし、そのようなルーチンに vDSO が付随している場合 gettimeofday
などのバージョン .プログラムの実行時、カーネルに vDSO がない場合 サポート、従来の syscall が行われます。
クレジットと便利なリンク:
- 素晴らしいチュートリアル、独自の vDSO の作成方法
- vsyscall と vDSO、素晴らしい記事
- 役に立つ記事とリンク
- linux-gate.so.1 とは?
新しいカーネル vDSO
にそれを追加したいだけです 「安全な」syscall だけに使用されるのではなく、システム上で syscall を呼び出すためにどの syscall メカニズムが優先されるかを決定するために使用されます。