Posted at

Linux - 保護機能

More than 3 years have passed since last update.

Linux kernel における保護機能について基礎的な内容を整理する。


特権レベル

特権レベルに関する用語を次にまとめる。


  • CPL: Current Priviledge Level


    • Linux においてはコードセグメントの DPL と同じ

    • CS/SS の下位 2bit から確認できる



  • DPL: Descriptor Priviledge Level


    • セグメントデスクリプタに記載

    • そのセグメントへのアクセスに必要とされる特権レベル



  • RPL: Requested Priviledge Level


    • 特権レベルを下げるために利用する



特権レベルはコードセグメントに対して割り当てられる。

基本的にプロセスはそのセグメントの DPL に応じた特権レベルを持つ。


  • Lv. 3 ... User Space

  • Lv. 2 ... VM

  • Lv. 1 ... VM

  • Lv. 0 ... Kernel Space

CPU が実行しているプロセスの特権レベルは CPL と呼ぶ。

これは CS セグメントレジスタの下位 2bit から参照することができる。

この値をプロセスから切り替えることはできない。

ユーザプロセスが CPL を変更してシステムコールを呼び出すための仕掛けとしてはゲートが用意される。

また CPU にはその動作を制御する命令(特権命令)があるが、CPL 1-3 のプロセスがこれを実行しようとした場合は一般保護例外(Global Protection Fault)が発生する。


セグメント保護


リミットチェック


  • セグメント範囲を超えた領域にアクセスしないようにする

  • Linux では基本フラットモデルを採用しているためこの保護違反は発生しない


タイプチェック


  • セグメントレジスタに謝ったタイプのセグメントセレクタを読み込まないようにする

  • セレクタがロードされたあとは、そのセグメントに対して謝った操作がなされないようにする


    • たとえば読み込みオンリーのセグメントに書き込もうとした場合など



  • チェック項目


    • CS


      • コードセグメントセレクタのみロード可能(4-7)

      • セグメント無効化セレクタ(0)はロードできない



    • DS/ES/FS/GS


      • データセグメントセレクタのみロード可能(0-3)



    • SS


      • 書き込み可能なセレクタのみロード可能

      • セグメント無効化セレクタ(0)はロードできない






特権レベルチェック


DS/ES/FS/GS/SS セグメントレジスタ更新保護

プログラムはメモリから読み書きするときに DS/ES/FS/GS/SS を利用する。

これのためにセグメントレジスタを更新してセレクタをロードしておく必要が有る。

このロードにおいて誤った特権レベル関係にならないようにするのがこの保護機能。

たとえば CS の DPL=3 のプログラムのために DPL=0 のセグメントをロードすることはできない。

セレクタの RPL には通常は CPL と同じ値を入れる。

たとえば DPL=3 のセグメントに対して CPL3 のプログラムがアクセスしたい場合は RPL=3 としてセレクタをレジスタにロードする。

これは DPL=CPL=RPL となるので OK。

RPL の役割は Linux ではあまり重要ではない。


CS セグメントレジスタ更新保護

CS セグメントレジスタの更新は CPL が変更される可能性を伴う(特権レベルの移行)

移行先セグメントの DPL が CPL と同じ場合のみ更新可能となる。

この規則だけだと特権レベルの移行が不可能になるが、これに対しては CPU の用意するゲートを用いて実現する。

トラップゲートと割り込みゲートについては別稿で述べる。

64bit mode は syscall 命令で移行する。


ページ保護

ページング機能が有効な状態ではページテーブルの内容に基づいてアクセス保護が行われる。

保護フラグはページディレクトリなどの上位にも適用される。

ディレクトリとテーブルで内容が異なる場合はリーフに近いほう(この場合はテーブル)が優先される。

つまり IA-32 の場合は、メモリにアクセスするために最大で3回の保護チェックをパスしないといけない(PSE が有効な場合は2回)

ページ保護に使われるのは U/S と R/W の2つのフラグになる。


U/S フラグ保護

U/S の単語それぞれは User/Supervisor の頭文字をとっており、つまりページフレームにアクセス可能な特権レベルを指す。

User は CPL=3 であり、Supervisor は CPL=0-2 である。

Supervisor は全てのページフレームにアクセスできるが、User は U/S フラグがセットされているページフレームでなければアクセスできない。

たとえばカーネルメモリなどは U/S フラグがリセットされていて User からアクセスすることはできない。


R/W フラグ保護

ページフレームの読み出しと書き込みの権限を保護する。

R/W フラグがリセットされているページフレームに対しては書き込みを行うことができない。

ただし CR0 レジスタの WP フラグがリセットされている場合は、Supervisor のみ、この保護が無効化されて R/W がセットされている User のページフレームにも書き込むことができる。

R/W フラグ保護機能は Copy on Write 機能を実現するために用いられる。

2つ以上のプロセスに共有されているページフレームに共有のマーキングとして R/W フラグをセットしておくことで書き込み発生時に例外を起こせるため。