【HotOS XVIII】柔軟なOS分離を実現するFlexOS
TL;DR
LibOSを拡張し、区画化によるセキュリティとワークロードに応じたパフォーマンスを柔軟に選択可能とするアーキテクチャ
実現方法はメモリアクセス等に関するメタデータを付与し、同一区画にライブラリを配置可能か自動的に判断
はじめに
本文
一般のOS設計においては、セキュリティとパフォーマンスにはトレードオフの関係が存在する。SASOSes(Single Address Space OS)やモノリシックカーネルのアプリーチではパフォーマンスの長があり、きめ細やかな分離を提供するマイクロカーネルではセキュリティに優れる。さらにハードウェアに基づく保護(例: Intel MPK)は、特定のハードウェア上でしか堅牢性が提供できないといった制限が生じる。FlexOSはこのようなロックインなしに、分離プリミティブと保護プリミティブの柔軟な設定を可能とするアーキテクチャだ。
FlexOSはcompartmentalization(区画化)のアプローチを取る。Figure 2では、TCP Stack、Scheduler、残りのKernelとAppの3つに区画化されている。
https://gyazo.com/6ceccac294ab71f74a89741c7cf3370f
(論文中より引用)
各区画はそれぞれが公開するAPIで構成されるGateを介して分離されており、従来のマイクロカーネルよりも細かい粒度でOSソフトウェアモジュールを配置可能だ。Gateによって区画間の分離が実装されるとともに、区画ごとに利用可能なハードウェア・ソフトウェアの分離メカニズムを活用できる設計となっている。
osuke.iconここら辺あまり聞いたことないので新規性なのかな?
具体的な実装は、各ライブラリのAPIにFlexOSメタデータを指定する方式を取っている。メタデータにより、あるライブラリのメモリアクセス動作と、同じ区画で実行される他コンポーネントのメモリアクセス動作を解析し、安全性を保証する。例えば以下のスケジューラは、ライブラリが自身のメモリおよび共有メモリにアクセスすること、公開関数APIを介して他ライブラリが自身のメモリを読み取ることができることと共有メモリへの書き込みができること示している。(Memory access句とRequires句)
code:C
Memory access Read(Own,Shared); Write(Own,Shared)
Call alloc::malloc, alloc::free
API thread_add (. . . ); thread_rm(. . . ); yield(. . . )
Requires *(Read,Own), *(Write,Shared),
*(Call, thread_add), *. . .
一方で以下のようなライブラリは、自身が任意の読み取り/書き込みが可能なだけでなく、他ライブラリからもライブラリが所有するメモリへの読み取り/書き込みができてしまう(Requires句がないため)。
code:C
Memory access Read(*); Write(*)
Call *
このような2つのライブラリは同一区画に同居することができず、FlexOSはこれをメタデータを用いて自動的に判断する。なお、メタデータの付与は現状、開発者が手動で付与する必要があり、自動的な付与はfuture workとしている。外部ライブラリに対してもメタデータの付与が必要で、リンク時に自動的に付与される機構が不足している状態では一般の開発フローへの応用は難しそうだ。
laysakura.icon 自動付与、あんまりできる気がしないんですが実現方法は見えてるんでしょうか?👀
cipepser.icon 実現性は触れられておらずでした。しかし、メタデータ付与するときにミスするかもしれないから自動化は必要だという主張はありました。
laysakura.icon ライブラリコードの静的解析では無理ある(メモリアドレス計算を、コードに現れない乱数などの環境から取ってきたりするとおしまい)し、ランタイム解析でも珍しい特定条件でのみ他のライブラリのメモリ書き換える挙動するようなやつだと厳しそうだなって思いました。
本論文は、セキュリティとパフォーマンスについてワークロードごとに両立を目指すもので、iperfとredisを用いた測定も行っている。ここではredisの測定結果について紹介したい。以下は4種類の区分化それぞれについてのスループットを測定したものである。
分離なし(No Isol)
ネットワークスタックのみ分離(NW-only)
ネットワークスタック、スケジューラを分離(NW/Sched/Rest)←3区画
ネットワークスタックとスケジューラを分離(NW and sched/rest)←2区画
https://gyazo.com/27a4e8f888ac90d563bac75b9b731eae
(論文中より引用)
分離のオーバーヘッドは区画化の数と区画間のコミュニケーション量に依存しており、ネットワークスタックのみ分離した場合、分離なしに較べて平均17%のスループット低下となった。さらにスケジューラも分離するとshared stackでは1.4倍、switched stackでは2.25倍のオーバーヘッドとなった。これはネットワークスタック〜スケジューラの通信が頻繁に行われたことで、セマフォを介した待機キューの使用が集中したためだとしている。ただし、ネットワークスタックとスケジューラを同じ区画に配置してもパフォーマンスは向上しない(一番右の結果)。これはセマフォがlibcで実装されており、別区画になっているためで、コンポーネントのさらなる区画化や再設計が必要だとしている。
laysakura.icon shared stack, switched stack の説明がないかもです。ここのstackは(ネットワークスタックと違い)メモリのスタック領域のことですか?
cipepser.icon 本文長くなってしまったので、Appendixに書いてましたmm
laysakura.icon ほんまやありがとうございます!
最後に
本文中でも述べたが、自作のライブラリだけでなく、依存する外部ライブラリに対してもメタデータの付与が必要という点は開発者として使うハードルが高いように感じた。一方で特定のハードウェアに依存した保護プリミティブを使いたいユースケースは多く存在するので、きめ細やかな区画化が可能な点は一見るに値する。また筆者個人としては、ライブラリを頂点、互換性のないライブラリ同士をエッジで結んだときにできるグラフを考えたとき、非互換なライブラリペアをFlexOS内区画に配置する最小数を決定する問題が、古典的なグラフ彩色問題に帰着できるという点が興味深かった。(文責・恩田) Appendix
shared stack
heapとstatic memoryが分離
thread stackは全区画で共有
switched stack
heap、stack、static memoryがすべて分離
threadごとに1つのstack