resume2

実装について
前田俊行
実装の特徴
• 最小限の労力で実装した
– 既存のLinuxカーネルの機能をフル活用する
– Linuxカーネル本体を改造せずにすんだ
実装した2つの仕組み
• カーネル内でプログラムを実行する仕組み
• カーネル内からシステムコールを実行する
仕組み
カーネル内でプログラムを実行
する仕組み
• Linuxのカーネルモジュールの機構を利用
• 安全性はTALの型チェックにより保証され
る
– メモリ安全性と制御フロー安全性を保証
Linuxカーネルモジュール機構
の仕組み
• 任意のプログラムをカーネル空間にロード
する機能
• シンボル管理機能
任意のプログラムをカーネル空
間にロードする機能
カーネル空間
プログラム
プログラム
Linuxでは任意のメモリイメージを
カーネル空間にロードすることができる
参考 :
create_module(2)
init_module(2)
シンボル管理機能
プログラム
カーネル空間
load
tableA
load
0xe000
jmp
routineB
jmp
0xc000
3 : プログラムのロード時に
「穴」が埋められる
1 :プログラム中のメモリアドレスを
「穴」としておき
さらに名前をつけておく
2 : カーネルは
名前とアドレスの対応表
を用意しておく
プログラム
tableA
routineB
0xe000
0xc000
参考 :
procfs(5)
カーネル内でプログラムを実行
する仕組みの全体像
1 : TALでプログラムを作成
型チェッカ
2 : TALの型チェッカで安全性チェック
3 : 安全ならばLinuxの
カーネルモジュール機能を
用いてロード
カーネル内からシステムコール
を実行する仕組み
• Linuxシステムコールのシステム関数を直
接呼び出すことで実現
Linuxシステムコールの仕組み
その1 : 割り込み発生
• ユーザプログラムはシステムコールを実行
するために割り込みを発生させる
プログラム … // 引数の準備
… // システムコール番号の
… // 指定など
int 0x80
割り込み発生!
ユーザモード
カーネルモード
システムコール実行のために
特権モードへ遷移
Linuxシステムコールの仕組み
その2 : システム関数の実行
• カーネルはユーザプログラムから指定され
た番号をもとにシステム関数をシステム関
数表から探し出し、実行する
システム関数表
システムコール
番号
0
1
2
3
4
5
6
システム関数
sys_read
システム関数
sys_write
システム関数
sys_open
システム関数
sys_execve
Linuxシステムコールの仕組み
その3 : 割り込み終了
• システム関数の実行が終了したら割り込
み処理を終了し、ユーザプログラムへ帰る
カーネル
… // 返り値やエラー値の
… // 指定
iret
割り込み処理終了
カーネルモード
ユーザモード
一般モードへ遷移
カーネル内からシステムコール
を呼び出す仕組みの全体像
• 直接システム関数を呼び出す
カーネル空間
プログラム
システム関数
sys_open
… // 引数の準備
…
jmp sys_open
直接呼び出し
…
安全性はTALの型チェックで保証
細かい話 :システム関数の
直接呼出について
• 現在の実装では、Linuxのそのままのシス
テム関数を利用しているので、直接呼び出
す前(後)に前(後)処理を行っている
– 引数のマーシャリング、アンマーシャリング
• CとTALの配列のデータ表現間の相互変換
• PopcornとCの呼び出し規約の違いの吸収
– ただし、これは最新のPopcornでは解決されている
現在の実装の問題
• 実行できるユーザプログラムのサイズ、数
に制限がある
– ユーザプログラムがカーネルに常駐するため
• スタックオーバーフローを考慮していない
– スタックがオーバーフローしたら、さようなら
新しい実装方式の模索
• プログラムを通常のユーザプロセスで実行
する
• ただし、プロセスの特権レベルをカーネル
と同じレベルにする
– Linuxなどではカーネル空間がユーザ空間の
一部としてマップされていることを利用
新しい実装方式の問題
• スタックの扱いが複雑
– 特に割り込みスタック
• 細かい話は長くなるので省略
– IA32の仕様がまずい
• IA32以外なら容易に実装できそうである
まとめ
• 既存のLinuxの機能を利用してカーネルを
改造することなく実装した
– カーネルモジュールのロード機能を利用
– システムコール関数を利用