f1fff234be2e8bbeacaf3658f5aeab1b.ppt
- Количество слайдов: 50
POPLミーティング 10/12 修士研究進捗報告 米澤研 M 2 吉野 寿宏 <tossy-2@yl. is. s. u-tokyo. ac. jp>
Agenda n n 研究テーマについて 進捗報告 ¡ ¡ n 現状 現在考えている問題点 Survey ¡ Program Verification Techniques on Java VM /. NET CLI
研究テーマについて
研究テーマ n An Implementation of Typed Assembly Language for Multiple Architectures ¡ 型付きアセンブリ言語の汎用的な実装 要するに ¡ TAL 検証器を構成するための統一的な 手法の確立
型付きアセンブリ言語 (TAL) n 実マシンのアセンブリ言語に型を導入 ¡ ¡ ¡ [1] レジスタの型・メモリの中身の型などを静的 に検証 メモリ安全性(範囲外のメモリをアクセス しないこと)などを保証 Java VM のバイトコード検証機構と類似 G. Morrisett, et al. From System F to Typed Assembly Language. In 1998 ACM SIGPLAN-SIGACT Symposium on Principles of Programming Language.
研究の着想 n TAL はアーキテクチャ(= CPU)に強く依存した言語 ¡ ¡ n アーキテクチャ ごとに処理系を用意する必要 既存の処理系を移植する作業はコストが高い しかし、どの CPU も中でやっていることは一緒 ¡ ¡ レジスタ・メモリにデータを格納 算術演算、論理演算、関数呼び出し… → 型システム・検証器などは大部分が共通に 使用できるのでは
研究の着想 n Formal に書けば、命令実行とは、 r 1=0, … n r 1=1, … したがって一般的に型を導入することが できる いずれも型環境
型検証の手順 n コードの各所に annotation を挿入 ¡ ¡ n 「これ以下ではこの前提の下実行される」と いう意味の制約 基本的には各基本ブロックごとに挿入 全ての実行遷移について annotation を 満たしているかどうかを検査 ¡ 分岐・関数呼び出しなどで飛び込んでくる 場合
型検証の手順 ラベル 1: 型情報 命令 … 制 御 フ ロ ー ラベル 2: 型情報 命令 … 流入可能 条件 基本ブロック
型検証の手順 ブロックに流入す る際には入口の 条件をチェック ラベル 1: 型情報 命令 A A 実行後の状態 命令 B B 実行後の状態 命令 C C 実行後の状態 … ラベル 2: 型情報 各命令の意味論に よって、実行後の 命令 状態を求める 命令 …
アプローチ n 意味論記述用の言語を設計 ¡ 基本的な操作をカバーするシンプルな言語 n ¡ n 算術演算や論理演算、分岐、メモリの参照 その上に型システムを導入 実アーキテクチャのアセンブリ言語からの 変換規則を記述 ¡ ¡ 変換ルールの記述方法の設計 ソース言語の読み込みインターフェイス n 抽象化することにより、アセンブリでもオブジェクト コードでも対応可能なようにする
アプローチ 型 型 高級言語 プログラム コ ン パ イ ラ プ ロ アーキテクチャ A グ ラ 実行ファイル ム 変 型 換 アーキテクチャ B 実行ファイル 型 意味論言語 ↑ この上で 型を検証
なぜアセンブリ言語か? n Java 等の言語で書けばいいのでは? ¡ 確かに。しかし実際の機械が実行するのは あくまでそのアーキテクチャの機械語 n ¡ いわば水際作戦 システムソフトウェアなどにも応用がきく n ただし OS 自体を安全な言語で書くという研究も ある
進捗状況
全体の 程 n 意味論記述部 ¡ ¡ ¡ n 抽象機械の定義 (その上の)意味論言語 (さらにその上の)型システム 命令マッピング機構 ¡ Unification によるマッチング
関連研究 n Foundational TAL ¡ 目指すシステムは本研究と類似 n n ¡ [2] 「一般的な TAL」を開発することにより TCB (Trusted Computing Base) を小さくする 目的 抽象アーキテクチャと型システムを設計し、 Progress, Preservation を定理証明器で 自動証明 K. Crary. Toward a Foundational Typed Assembly Language. CMU Technical Report CMU-CS-02 -196.
関連研究 n Foundational TAL ¡ Pointer arithmetic が入っていない n ¡ レジスタベースなので途中の計算結果を 保存できない n n ¡ かわりに、メモリ参照のところで即値のオフセット をとることができる 複雑な命令の記述性 ただ、「複雑な命令」と一口に言ってもいろいろ 処理系は未公開?
関連研究 n LLVM ¡ ¡ ¡ もともとは最適化目的で作成された VM C ライクな構文を持っている 弱い型付けがされている n n ¡ [2] [3] キャストが許可されている Formal な証明が与えられているわけではない Subset を定義して formal に型システムを 導入すれば使えるかも C. Lattner. LLVM: An Infrastructure for Multi-Stage Optimization. Master Thesis at Computer Science Dept. , Univ. of Illinois at Urbana-Champaign, 2002.
抽象機械を定義する n 抽象機械 = 状態を保持する部分 ¡ 実アーキテクチャを包含できるような 一般性が必要 ¡ いくつかのレジスタ n ¡ 抽象化するアーキテクチャと対応させる メモリ
抽象機械を定義する データ定義 n データはすべてバイト単位に分割して そのタプルで記述
抽象機械を定義する データ定義 n データはすべてバイト単位に分割して メモリアドレスは そのタプルで記述 内部的に fat pointer で扱う
抽象機械を定義する データ定義 n データはすべてバイト単位に分割して そのタプルで記述 アドレス値の n バイト目 未定義値
抽象機械を定義する 抽象機械の持つ状態 n レジスタは名前で識別 ¡ n レジスタ r 1 の幅を w 1, … とする メモリへはラベル(とオフセット)でアクセス ¡ ラベルの異なるメモリ領域同士は「独立」 n 境界チェックができる
意味論言語 n 要件 ¡ 実行フロー関係の構文はほとんど必要ない n ¡ if による分岐と jump の組み合わせで記述可能 演算の類は正確に記述できる必要がある n 型システムが値に依存する可能性が高い ¡ n 詳しくは後述 意味論言語に変換されたプログラムと元の実 プログラムとで結果が同一になることを検査可能 → 記述の正しさの検証につながると思われる
意味論言語 言語構文 n Left value とは、C 言語でいうところの左辺値 ¡ つまりは代入可能な箇所
意味論言語 言語構文 n goto と call/ret が分かれている理由について は後述
意味論言語 型システム n 基本的な型 ¡ Junk … 不明瞭な型
命令マッピング n アセンブリ命令 = オペコード(命令種別) + 0 個以上のオペランド 関数にたとえて言えば… ¡ オペコードは関数本体を指定する ¡ オペランドは関数への引数 n 入力引数だけでなく、結果代入先も指定
命令マッピング テンプレートの記述 inc r 1 : inc REG : inc r 2 : { r 1 : = r 1 + 1; } { REG r 2 + 1; } { r 2 : = REG + 1; } inc というテンプレートで一般化される } r 3 : { r 3 : = r 3 + 1; . . . mov R 1, R 2 : { R 1 : = R 2 ; } add R 1, R 2 : { R 1 : = R 1 + R 2 ; }
命令マッピング テンプレートの適用 n テンプレート mov R 1, R 2 : { R 1 : = R 2 ; } n 実際の命令 mov r 2, r 5 要するに unification → テンプレートパラメータ部分との対応 R 1 = r 2, R 2 = r 5
命令マッピング アドレッシングモードの問題 n 大抵のプロセッサは、いろいろな アドレッシングモードがある ¡ ¡ レジスタ+定数オフセットの指すメモリ レジスタ+レジスタ×定数云々 これらをテンプレート引数として統一的に 扱うにはどうしたらよいか? n 考え中
現在考えている問題点 n Architecture-Specific Feature の扱い ¡ Delayed Branch の解決 n Pointer Arithmetics 関数呼び出し n 等々 n
Architecture-Specific Feature の取り扱い n Delayed Branch ¡ ¡ Delay なしの semantics に変換して扱う 問題: annotation のないラベルができる 可能性. . . bge lbl_ge bl temp mov r 1, r 2 lbl_lt: . . . ba lbl_ge temp: mov r 1, r 2 lbl_lt: . . .
問題点 Pointer Arithmetics n 次のような C コードをコンパイルしたと する struct foo { int id; char *name; } bar = { 1, “bar” }; void func() {. . . bar. name. . . } &bar + sizeof(int) という風な記述になる
問題点 Pointer Arithmetics n ラベル “bar” の型 B 4 0 n B* ptr 4 Dependent type が必要 ¡ ¡ ¡ *(bar + 4) のような記述に なる + のオペランドは e なので 計算する必要がある static に決まらないものも指 定できてしまう… struct foo { int id; char *name; } bar = { 1, “bar” }; void func() {. . . bar. name. . . }
問題点 Pointer Arithmetics n Static な解析で追いつかない場合に どうする? ¡ たとえばレジスタ+レジスタ おそらく非決定的だということで検証が失敗 することになる ¡ 記述できなくする手もある ¡ n n TALT では、メモリ参照は即値オフセットをとる ことができる しかしレジスタ値と足したりした場合には型付け ルールがない
問題点 関数呼び出し n call, ret どちらも無条件分岐として扱える ¡ ¡ call の戻り先アドレスは、関数の返り値の型 をとるようなコード列 それを callee 側の precondition として記述 すればよい n n たとえばスタックに戻り先を積む場合、 {引数…, sp: <戻り値をとるコードへのポインタ, …> } のように
問題点 関数呼び出し Callee の precondition として記述したとして… n 戻り先のコードが実際にその条件を満たすか どうか検証の必要 単純な jump として捉えた場合、この一致を記述す るのが難しい ¡ たとえば、「次の命令のラベルの型」といった記法を 導入する必要 → 複雑化してしまう ¡
問題点 関数呼び出し n call, ret を jump とは別に用意することで 解決できるかどうか ¡ call については、関数のシグネチャから実行 後状態を取り出してくればよい ¡ 問題: アセンブリ言語では関数構造が見えな いこと n 関数から必ず戻っているか… fall through して いないかどうかが簡単にはわからない
Survey: Program Verification Techniques on Java VM /. NET CLI
信用できないコード n 基本的にクライアント側で実行させる ¡ n しかしネットワーク上のコードは基本的に 信用できない可能性がある ¡ ¡ n たとえば、ブラウザ用の Java Applet 悪意のあるコードが混じっているとか スパイウェア、トロイの木馬… 不正なコードを実行して影響を蒙るのは 実行したクライアントである
Java におけるセキュリティ確保 n Java のコアクラスと外部のクラスを分別 システムクラスを置き換えるなど悪意のある 動作を防ぐ → サンドボックスの仕組み ¡ ¡ しかし不正なコードによって VM の動作がお かしくなってしまうことは防げない n たとえばメソッド呼び出しの型があってないとか また、動的検査ではコストが高い → バイトコード検証 ¡
Java VM n Java バイトコードを実行する仮想機械 ¡ アーキテクチャとしてはスタックマシン n 計算はスタックに対して行われる ¡ ローカル変数・メソッドの引数用の記憶領域 が別に与えられている ¡ 扱う値は、プリミティブ型(int など)か参照 (Object 型のサブクラス)の 2 種類
Java VM method func() iconst_1 iconst_2 iadd istore_0 スタック 3 1 記憶領域 3 0 2
バイトコード検証によって 保証できること n 命令の型が一致していること ¡ n 足し算に Object を持ってきたりしていない か? スタックをはみださないこと ¡ ¡ アンダーフローしていないか? または最大使用量をオーバーしていないか ? n 最大使用量はメソッドのシグネチャに含まれる
バイトコード検証によって 保証できること n プログラムカウンタが正当であること ¡ ¡ n Java の場合、分岐は必ず同一メソッド内 バイトコードの命令の途中を指したりして いないか? 値の初期化 ¡ ¡ 記憶領域を使う前に初期化しているか? オブジェクトにアクセスするより前に コンストラクタを呼んでいるか?
Type-Level Abstract Interpreter n あたかも”普通の” Java VM のように バイトコードの semantics に沿って計算 ¡ n 計算過程で、バイトコードの安全性を保証 するために必要な点を検証 取り扱う値は全て型 ¡ バイトコードは型情報を含んでいるので容易 に検証ができる
. NET CLI n CIL (Common Intermediate Language) と呼ばれる言語を実行する仮想機械 ¡ ¡ アーキテクチャはスタックマシン メソッド引数用・ローカル変数用の記憶領域 が別に与えられている n ¡ Java とは異なり、これらは別々である 整数型・浮動小数点型(F)・ポインタ(&)・ 参照(O)を持つ
CLI のプログラム検証 n CIL の命令セット定義には検証可能性に ついても含めて書かれている ¡ n 基本的には Java の場合と同様にやる ポインタは鬼門 ¡ ポインタ演算があると検証可能でなくなる n n ポインタ+整数、ポインタ-ポインタ の演算が有効 (ただし検証不可能) Java はポインタを見せない(配列かオブジェクト に全てカプセルする)ので検証性は落ちない
参考文献 n n X. Leroy. Java Bytecode Verification: Algorithms and Formalizations. Journal of Automated Reasoning 30(3 -4): 235 -269, 2003. Sun. The Java Cirtual Machine Specification. http: //java. sun. com/docs/books/vmspec/ n Microsoft. The CLI Specification. http: //msdn. microsoft. com/netframework/programming/clr/default. aspx
f1fff234be2e8bbeacaf3658f5aeab1b.ppt