実装について 前田俊行 実装の特徴 • 最小限の労力で実装した – 既存の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の機能を利用してカーネルを 改造することなく実装した – カーネルモジュールのロード機能を利用 – システムコール関数を利用
© Copyright 2024 ExpyDoc