OSECPUの基本設計思想

  • (by K, 2013.03.20)

基本思想

  • (1) ソフトウェアに脆弱性が生まれてしまうのは、人間の不注意に由来する。もし人間の注意力が無限大であれば、現在のOSでも脆弱性が生まれる余地はない。・・・と僕は仮定する。
    • 現実では脆弱性はなくなっていないが、これは不注意を責めて結局は開発者やユーザに注意を要求するばかりであり、それだけでは限界に来ていることを示している。・・・と僕は仮定する。
  • (2) したがってOSECPUにおける「セキュアなOS」としての取り組みは、不注意によるミスが起きることを前提とし、これをできるだけ予防したり早期に発見することを目指す。逆に言うならば単純な不注意そのものを責めない。それを予防できなかったことを責めるのである。
  • (3) あるソフトウェアがあったとする。これに不適切なパラメータを与え、意図しない結果になった場合、「そんな使い方をするやつが悪い」というのが現代の一般的な考え方だと思うが、僕の場合は、なぜ悲惨な結果を引き起こすかもしれないのにundoができないのか、のように考える。不適切なパラメータであるとチェックできなかったのはなぜか?ソフトウェアはチェックできたのではないか?
  • (4) (3)のソフトウェアを「ライブラリ」と読み替えてみよう。そうすると具体的になって分かりやすいかもしれない。プログラムは不正な引数を渡してしまう。そのせいでライブラリはより下位のライブラリに対し不正な引数を渡してしまう。こういうことは珍しいことではない。・・・このケースに対して、一番悪いのは誰かといえば、最初に不正な引数を渡した「プログラム」ではない。間違いは起きてしまうものなのだから、それはやむをえないと考える。悪いのはライブラリである。ライブラリはその気になれば引数をチェックすることができたはずだ。そうすればすぐに「不正な引数で呼び出されました」と報告できる。そうすればどこが悪いのかも早期に発見できる。
    • 下位のライブラリで引数の不正が発覚した場合、その原因がどこにあるか分からない。この場合は上位のプログラムのほうであるが、OSECPUにおいては、そもそも上位のライブラリが不正な引数を「素通り」させてしまった時点で「脆弱性」だと考える。つまり全てのライブラリは自分がおかしな引数を受け取っていないかチェックする義務があり、チェックせずに下位に渡してはいけないのである。
    • これはライブラリに限らない。ユーザが使うようなツールでも同様のチェックはできるはずであり、すべきであると考えるのがOSECPUである。
    • もちろん綿密なチェックには余計な処理時間がかかることは避けられない。したがって以下の指標を持つ。与えられたパラメータの規模Nに対してO(N)程度のチェックは全てすべきだというのがOSECPUである。それよりコストのかかるチェックについては、怠ったとしてもそれを脆弱性としてとがめられることはない。
  • (5) 速度は落ちる。当然落ちる。しかしそれが何だというのだ。今やCPUは異様に速く、速度よりもセキュリティのほうが深刻なのではないか?そうなのであれば、我々は本来すべきテストを怠ってきたというわけであり、遅くなるのはやむをえないのだ。我々の注意力がその程度しかない以上は、それに見合った負担は甘んじてうけなければならない。OSECPUではそのように考えて、このコストだけを理由にチェックを怠ることを正当化はしない。
  • (6) OSECPUでは権限という概念を極力廃する。僕が言うところの権限による管理とは、目の前に全てが陳列されているものの、アクセスするには権限なるものが必要で、それによってシステムを守るという手法のことである。root権限といったら分かりやすいだろうか。もしくはCPUにおけるユーザモードとカーネルモードといってもよい。こういうやりかたは人間の管理能力では管理しきれないと考える。
    • 結局権限モデルでは、権限を何とかして得るとか、権限のある人になりすますか、権限のある人をだまして悪事に加担させるという攻撃手法をとることになり、これは一定の成功を見ている。
  • (7) OSECPUでは、権限ではなくて、そもそも存在を教えないという手法をとる。アプリは与えられた引数以外には何も見えず、自由にディレクトリの構成を知ることがそもそもできない。アクセスできるとかできないとか以前の問題で、どこをどう攻めるべきなのかが分からない。誰かに成りすまそうにも、誰に成りすませばいいのかが分からない。つまりユーザ一覧みたいな情報は、OSから情報提供することはなく、ユーザがわざわざ教えてやらない限りえられない。こういう設計を徹底する。
  • (8) 全てのリソースは有限であり、「デフォルトで」規制がかかっている。これらのリミットを解除するにはユーザによる明示的な操作を必要とする。デフォルトが無制限で、オプションで制限がかけられる、なんてものではない。
    • ユーザプログラムは規制を受けて起動するが、これらの貴重なリソースを下位のライブラリに分け与えて動作する。この規制値をオーバーライドする方法はない。そんな抜け道を作ればまた今までの歴史が繰り返されてしまう。
  • (9) malloc()はメモリがないときにNULLを返す、fopenはオープンに失敗したらNULLを返す、などという仕様になっているが、これはOSECPUでは不適切な仕様である。OSECPUでは失敗したら勝手にエラーメッセージを出して終了してしまう。これがデフォルトである。必要であれば、「それでは困る、自前でエラー処理をするからNULLを使って教えてくれ」とわざわざ言わなければいけない。こうすることで、プログラマがエラー処理をし忘れることを防ぐ。予期せぬNULLがコードの中を駆けめぐってさまざまな問題を起こすケースがあるが、それを防ぐためのアイデアである。これはmallocやfopenのみに限定されるものではなく、エラーがありうる状況全てで徹底される。
  • (10) レイヤがむやみに多層構造になることを阻止する。OSECPUはこんなにオーバヘッドが大きなものなのに、これが何層にもなったら大変なことになる。それゆえに過剰な多層構造をとらなくてもいいように設計を工夫する。
    • これにより結果的に従来のOSよりも快適になる可能性もある。
  • (11) OSECPUの仮想CPUは、以上のことを効率よく実現するために必要だと考えて導入されている。
  • (12) このような文化があれば、人間の不注意はかなり早期に根絶できるはずである。完全になくすことはこれでも不可能かもしれないが、とにかく減らせることは間違いないと思われる。これらによる性能低下が、このメリットを上回るのか下回るのかは、とにかく実際作ってみて使ってみなければわからないだろう。

基本思想よりも些末なこと

  • (13) OSECPUには翻訳単位ごとに通常モードと高速危険モードを選択できる。翻訳単位というのはアプリとDLLでは別々の指定をするとかそういうことを許すということである。高速危険モードでは各種のセキュリティチェックのためのコードがJIT時のネイティブコードに反映されない。これは主に、「この速度低下はそもそもこのプログラムがタコなのか、それとも過剰で用心深いセキュリティチェックのせいなのか」を判定するために使われる。高速危険モードをリリースモード的な扱いにして通常に利用するというやり方は基本的には想定していない(もちろんそういう使い方をしてもかまわないが)。
    • ちなみにOSECPUのバイトコード体系にはアサートのための構文があり、これは高速危険モードを選択したときは翻訳されず、それゆえに実行されない。したがって悪意あるアプリが「通常モードのときは一切悪さをしないが、高速危険モードになったら悪さを試みる」という挙動を取ることは可能である(フラグへの代入文をアサートでくくっておけば、このフラグを見ることで容易に自分がどちらのモードにおかれているかを判断できる)。
    • もちろんアプリが高速危険モードでも、周囲が通常モードなら、周囲が予防に成功するかもしれない。しかし周囲のチェック体制が甘いかどうかはわざと変なパラメータを渡してみて実行できてしまうかどうかを見ればよく、やはり悪意あるプログラムはガードがゆるいことを発見できてしまう。・・・それゆえ「高速危険モード」は通常使用にも耐えられるようなリリースモードの別名などではなく、あくまでもテスト用のものであると考えるべきだ。

こめんと欄

  • このページにこめんと欄はありません。このページの内容にコメントしたいときはimpressionsにお願いします。

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-04-03 (水) 15:46:17 (3371d)