コールゲート
コールゲートはx86 アーキテクチャのCPUに搭載されたセキュリティ機構である。CALL命令による呼び出しで上位の特権レベルのコードをあらかじめ登録されたものに限って実行することができる。
動作
このような上位の特権レベルのコードを実行するための仕組みは、ユーザアプリケーションからのカーネルのファンクションやシステムコールの呼び出しをOSが制御することができるので、メモリ保護を行う現在のOSに必須のメカニズムである。
コールゲートを使った呼び出しでは、GDT (Global Descriptor Table) や LDT (Local Descriptor Table) にある特権障壁を越える呼び出しに必要な情報が記載されている特別なエントリを指すセレクタを使用する。 ソフトウェア割り込みと似たようなメカニズムである。
ユーザプログラムからコールゲートを使ってカーネルの機能を利用する場合、CALL FAR (LCALL) 命令に呼び出したい関数のコールゲートをセグメントセレクタに指定して実行するだけでよい (オフセット指定は無視される)。 コールゲートエントリのチェックと呼び出す権限の有無を確かめられた後、CS/EIP がセグメントデスクリプタから読み出され、呼び出し側の継続が新しいスタックに積まれる。(呼び出し側のSS, ESP, CS, EIPが順に積まれる) 必要な引数も呼び出し側の(低い権限の)スタックから呼ばれた側の(高い権限の)スタックにコピーされる。コピーする引数の数はコールゲートのセグメントデスクリプタで指定されている。
カーネルプログラムからはRET FAR (LRET)によって元の権限レベルに戻る。
セグメントセレクタのフォーマット
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Selector Index | TI | RPL |
- Selector Index:セレクタの番号
- TI: Table Indicator: TI=0 はGDT, TI=1 はLDT
- RPL: Requestor Privilege Level(このセグメントセレクタを作成したプログラムの特権レベル)
32ビットコールゲートデスクリプタのフォーマット
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
行き先のオフセット(上位)[31:16] | |||||||||||||||
P | DPL | S=0 | TYPE=1100 | 0 | 0 | 0 | パラメータ数 | ||||||||
行き先のコードセグメントセレクタ[15:2] | X | X | |||||||||||||
行き先のオフセット(下位)[15:0] |
- P: Present ビット
- DPL: Descriptor Privilege Level(ディスクリプタ特権レベル)
- S: セグメントタイプ:S=0はシステムセグメント
- TYPE: 1100は32ビットコールゲート
現在の特権レベル(CPL:Current Privilege Level)からRPLを持つコードセグメントセレクタを使用して
DPLGのコールゲートで、行き先の特権レベル(DPLS)へ制御移行するときの条件
- (1)DPLG >= CPL かつ DPLG >= RPL
- (2)CPL >= DPLS
使用例
他のアーキテクチャではコールゲートはサポートされていなかったため、移植性の問題からソフトウェア割り込みを使用したカーネルが多かった。また、新しく導入されたSYSENTER/SYSEXIT命令 (Intel) や SYSCALL/SYSRET命令 (AMD)により、より多くの高速なメカニズムに移行している。
これらと比べた利点として、コールゲートでは任意の特権レベルから、それより高い任意の特権レベルを呼び出すことができることが挙げられる。sysenter/sysexit命令やsyscall/sysret命令では3 → 0と0 → 3レベルの移行しかサポートしていない。また、ソフトウェア割り込みと比較した場合、コールゲートの方がかなり高速である。
使用例にはSolaris/x86[1]がある。
セキュリティ問題
GDTのあるメモリ領域が適切に保護されなければ、ユーザプログラムからコールゲートを設定することで任意のコードを特権レベル0で実行できるというセキュリティ上の欠陥として利用されうる。2006年に出現したMicrosoft WindowsのE-mailワームGurong.Aは\Device\PhysicalMemoryを通じてGDTを操作し、コールゲートを作ることで特権の昇格を行っている。
参考文献
- IA-32 インテル® アーキテクチャー・ソフトウェア・デベロッパーズ・マニュアル、下巻: システム・プログラミング・ガイド (pdf)
- 金凡峻『作りながら学ぶOSカーネル - 保護モードプログラミングの基本と実践』秀和システム 2009年 (ISBN 978-4-7980-2254-3) - 入門書であるが、6章・7章でコールゲートによってカーネル関数を呼び出す仕組みが解説されている。
- ^ Daniel Pierre Bovet, Marco Cesatí "Understanding the Linux Kernel" O'Reilly Media, Inc., 2006 p.45