形式検証アドベントカレンダー1日目の記事です。 形式検証された OS である seL4 の検証アプローチに関する話です。 使われているツールの詳細にはあまり踏み込まず全体的な指針をまとめたものです。

以下の記述は概ね[compverif]に基づいているので詳しくはそちらを読んでください。

seL4 が検証しないもの

まず、seL4 における形式検証の対象外となるものがいくつかある。 seL4 は, 以下に関する幾つかの条件を仮定してコードベースの正当性を検証する。[sel4_assumptions]

  1. アセンブリ言語で書かれたコードベース

  2. ハードウェア

  3. 起動処理

  4. 仮想メモリ

  5. DMA

  6. サイドチャネル攻撃による情報漏えい

seL4 verification architecture

seL4カーネルの検証は、抽象的な設計レベル・ソースコードレベル・バイナリレベルの3レイヤに分割されて行われる。 設計レベルの抽象度に対して、ソースコード、バイナリが設計の要求を満たしているか(refinement) [1] を検証する。

seL4 の設計・開発プロセスとその形式検証は密接に関わっている。 これは、ボトムアップなアプローチをとるOS開発者とトップダウンで考える形式手法の専門家がスムーズに情報を共有しながら進まなくてはならない。 以下、seL4の設計開発プロセスの流れに沿って説明する。

seL4 verification architecture

runnable abstract specification

まず、抽象的な仕様をHaskellで記述する。[hs_spec] [2] [run_spec]この記述から、Isabelleによる形式仕様へ自動的に変換することが出来る。 また、この形式仕様を参考に手動でC言語によるカーネルの実装がされる。

さらに、Haskellで形式仕様を書くことで、OSで開発者と形式手法専門家の間で前述の情報共有が達成される。

また、この形式仕様は_実行でき_[run_spec]設計プロセスでのプロトタイピングの役割も果たす。 [3] seL4では,これを用いて高速にプロトタイピングを行いつつ、C言語による実装を進めるといった設計開発プロセスが出来る。 [4]

c refinement proof

次に、C言語による実装が実際に前述の形式仕様の要求を満たすことを検証する。 これは、上の形式仕様から導かれるIsabelleのコードとCのソースコードを変換したIsabelleのコード [5] を合わせて必要な条件を命題として立てて証明することで達成される。

C言語からIsabelleへの変換は[c_parser]によってなされる。 変換器はC99の大体に対応しているが、検証に不都合な機能には対応していないこともある。 (e.g.自動化のためローカル変数への & を許容しない([compverif], 4.3) [bytes_seplog]) 変換器は Isabelle 上で形式化された言語である Simpl[simpl]のコードに変換され [6] 対話的に証明することができる。

binary verification

最後に、カーネルがコンパイル・リンクされた後のバイナリがC言語による実装を適切に反映しているかを検証する。 これも前述のC言語と抽象仕様との場合と同様に、バイナリとC言語の共通の論理的な表現に変換[bin_verif]した後に妥当性を検証する。

バイナリの検証は、実装後の工程(e.g.コンパイル、リンク)の問題を防ぐためである。 このような問題には、コンパイラ・リンカのバグなどがあり、バイナリを検証することでコンパイラやリンカの出力を信用しなくても良くなる。 [7]

おわりに

ここで取り上げた機能の正当性(functionalcorrectness)の他にも、 seL4の形式検証プロジェクトでは,マクロカーネルとしてfastpathの実装や、機密性に関する性質ついて検証しています。 すべての証明・実装は[l4verified][sel4_src]で見ることが出来るので是非眺めてみてください。

References


1. 段階的な詳細化[step_refn]によるソフトウェア開発における意味とは少々異なる
2. literate programming の実践例初めて見たかもしれない
3. しかし、形式仕様の実行に利用されるシミュレータとのインタフェースの実装がout of dateとなっており、現在ドキュメントとしての役割しか果たしていない(2022年現在 )[hs_spec]
4. 実際にこの方式で運用されていたのかは知らない
5. https://github.com/seL4/l4v/tree/master/spec/cspec (c-parser によって変換された結果がそのままコミットされている。)
6. C 言語のメモリ操作に関する検証を行うために分離論理が用いられている。ま た、ここでは仮想メモリや MMIO などは考慮されていないが seL4 への適用を想定してい る例として[msl],別のプロジェクトではあるが Nova hypervisor の開発での知見で [nova_verif],最近のもので[baby_vmm]などがある。
7. 当初は CompCert を用いてコンパイラのバグ減らす方向だったが、リンカ周り で問題が起きた末 binary verification を採用したらしい