アクセス権問題について
前提
- OSECPUのアプリは、持っているポインタ以外のところにはアクセスできない。
- システムコールをするとしても、システムは受け取った引数以外のところはアクセスできない。
- これを乗り越えるには、システムコールハンドラをOSECPUでは書かないか、もしくはシステムコールハンドラを書くために特権的な命令を作るしかない。
- しかしこのどちらの方法も受け入れがたい。システムコールハンドラをOSECPUで書けないということは、OSECPUでは書けないコードがあるということを意味して、それはつまり不完全なことの証ではないかと思う。それにOSECPUで書けないとなれば、機種依存するということにもなり、移植の妨げになる。
- 特権命令を作るとなれば、また特権を与えるかどうかの判定基準が必要になり、その権限を巡って攻撃者との攻防をすることになる。それも気に入らない。そういうモデルから脱したいのだ。
- つまりシステムはアプリにできることを手伝っているだけの存在になってしまう。ただの便利ツールだ。
- しかしだからと言って、アプリにハードウェアリソースにアクセス可能なポインタを与えていいものだろうか。・・・いやそれはダメだ。それじゃあアプリのバグでOSごと死んでしまう。
- しかしアプリにポインタを与えなければ、アプリはシステムコール時にシステムにアクセス権を与えることができない。
アイデア
- ここで僕はひらめいた。まずアクセス権がたくさんあるポインタ群を、一つの構造体にすべて書き込んでおいて、その構造体へのポインタを守ることだけを考える。そしてこの一つのポインタをハンドル形式でポインタレジスタに入れる。
- アクセス権がたくさんあるポインタ=いろいろなところにアクセスできちゃうポインタのこと
- ハンドル形式になると、そのままではメモリアクセスには使えない。
- それで、ハンドル形式のポインタから元のポインタを読み取る命令を用意する。この命令は、基本的には誰でも実行できるが、しかしこの命令の実行が成功するのは、あらかじめ決められたプログラムだけだ。・・・ここに特権めいたものを感じるかもしれないが、少し違う。
- ハンドルからポインタを取り出せるのは、そのハンドルの作者だけだと理解してほしい。つまり情報に鍵をかけることができる。この鍵はかけた者だけが解除できる。鍵が解除できない者でも、鍵がかかった状態のままでよければ、ハンドルとして自由に他の者に渡すことはできる。
- これを少し拡張すれば、ハンドルの作者はハンドルの開錠者を指定できる、という形式も可能かと思われる。
- ちなみに開錠者をOSECPUがどうやって判定するかだけど、それは簡単で関数呼び出しのリターンポインタP1Eを見る。これが指定されていた範囲に収まっていれば開錠する。
- もちろんアプリがP1Eに偽りの値を入れて(=手持ちのシステムへのポインタを入れて)開錠を要求することはできる。開錠そのものはおそらく成功するだろう。しかし開錠後、プログラムはP1Eのアドレスへ分岐してしまうので、アプリは開錠された情報を取得できない。さらにシステムに入った後もP1Eのアドレスがシステムを指しているので、仮にリターン命令があってもアプリへ帰ることができない。
- そもそもアプリが取得できるシステムのポインタなんて、システムコール用の物くらいしかなく、だからシステムコールエントリのところだけしっかり対策すればいい。
- ということで、システムコールに際しては、アプリは起動時にシステムからもらったシステムコール用のハンドルを引数に積んで呼び出す。
応用?
- この仕組みの場合、システムはこうしてアプリに対して情報を隠せるが、しかし逆にアプリもシステムに対して情報を隠すことができる。アプリが作ったハンドルはシステムによって開錠することはできない。したがって、システムに知られずにアプリが情報を保持することは可能である。
- ということで、仕組みとしてはアプリとシステムは対等であって、システムの優位性は単にアプリよりも多くの情報を握っているだけでしかない。
- もっともどのようなオブジェクトであれ、最初にそのメモリはシステムの管理下にあったものなので、システムは(ポインタを捨ててなければ)いつでも中身を見ることはできるのではあるが。
こめんと欄
- このページにこめんと欄はありません。このページの内容にコメントしたいときはimpressionsにお願いします。