(57)【要約】【課題】  攻撃者からの入力を受けとったプログラムが、動的コンパイラの生成した機械コードや、機械コードへのポインタなど、制御に関係するデータを書き換え、結果として攻撃者にコンピュータの制御を奪われることを防ぐ。【解決手段】  動的コンパイルをおこなう言語処理系を起動する際に、動的コンパイラを、プログラムの実行を担当するプロセスとは別のプロセスとして起動し、それぞれのプロセス間を共有メモリ領域で接続する。そして、該共有メモリ領域に対して、プログラムの実行を担当するプロセスから書込みができないよう保護し、保護した領域に、動的コンパイラが生成する機械コードやデータを書き込む。【選択図】  図３
2006048186.tif 000002
【特許請求の範囲】
【請求項１】
プログラムを実行時にコンパイルする言語処理系において、プログラムの実行とコンパイルを実行するプロセスを主記憶上に個別に生成し、それぞれのプロセスを、共有メモリ領域で連結し、前記共有メモリ領域を、前記コンパイルをおこなうプロセスがコンパイルの結果生成するコードやデータの配置先とする方法。
【請求項２】
請求項１において、前記共有メモリ領域を、前記のプログラムの実行をおこなうプロセスから書込不可の領域とする方法。
【請求項３】
請求項１に記載の方法を使う言語処理系。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、ソフトウェアの一種である言語処理系に関する。
【背景技術】
【０００２】
本発明の目的は、コンピュータシステムを不正な利用から守ることにある。コンピュータシステムを不正に利用しようと試みる者（攻撃者）が、コンピュータに任意の動作を実行させる手順の例を示す。
【０００３】
攻撃者はコンピュータシステム上で動作しているソフトウェアに対して、攻撃のための入力を与える。このとき、入力先のソフトウェアに脆弱性（欠陥）があると、ソフトウェアの設計者が想定しなかった記憶領域を書き換えられる。攻撃者は、この書き換えによって、機械コードなど、コンピュータの制御に関する情報を書き換えるよう、ソフトウェアに与える入力に細工する。静的にコンパイルされたプログラムでは、ＯＳがプログラムの機械コードを書込不可の領域に配置するので、機械コードを上書きすることは困難だが、Ｊａｖａ（登録商標：以下同様）仮想機械（Ｊａｖａ  Ｖｉｒｔｕａｌ  Ｍａｃｈｉｎｅ，ＪａｖａＶＭと略す）のように、プログラムを動的にコンパイルする言語処理系では、１つのプロセスの内部で、プログラムの実行を担当するスレッドと、コンパイルを担当するスレッドが並行動作する構成をとる場合が多く、このとき機械コードは、コンパイルを担当するスレッドからはもちろん、プログラムの実行を担当するスレッドからも書込可能な記憶領域に配置される。このような状況下では、プログラムの実行を担当するスレッドが、攻撃者からの入力を受けとった際に、機械コードを書き換え、結果として攻撃者の望む動作をしてしまいうる。
【０００４】
機械コードや、動的コンパイラが生成するさまざまな制御にかかわるデータを、攻撃者による書換えから保護する従来技術にＭＶＭがある（非特許文献１）。ＭＶＭはＪａｖａＶＭの一種で、複数のＪａｖａアプリケーションを同時に実行できるが、Ｊａｖａで記述したプログラムからＣ言語で記述したプログラムを呼び出す場合、Ｃ言語で記述したプログラムの実行は、個々のＪａｖａアプリケーションに対応するプロセスが実行する。攻撃者が利用する脆弱性は、多くの場合、Ｃ言語で記述したプログラムの内部に存在し、従ってＣ言語で記述したプログラムの実行を、ＪａｖａＶＭとは別のプロセスで実行すれば、Ｃ言語で記述したプログラムの脆弱性をついて、ＪａｖａＶＭの動的コンパイラが生成した機械コードを書き換えることは困難になる。
【０００５】
ただしＭＶＭには問題点がある。それは実行にともなうオーバヘッドが大きいという点である。ＭＶＭでは、Ｊａｖａで記述したプログラムからＣ言語で記述したプログラムを呼び出すのにプロセス間通信が必要になるが、ここから大きなオーバヘッドが生じ、プログラムの実行が数倍のオーダで遅くなりうる。
【０００６】
【非特許文献１】Czajkowski et al.: Code Sharing between Virtual Machines, In the Proceedings of the 16th European Conference on Object-Oriented Programming, pp. 155-177 (2002).
【発明の開示】
【発明が解決しようとする課題】
【０００７】
動的コンパイラが生成する機械コードやデータ構造を、小さなオーバヘッドで保護する。
【課題を解決するための手段】
【０００８】
プログラムを実行時にコンパイルする言語処理系において、プログラムの実行を担当するプロセスと、コンパイルを担当するプロセスを個別に設ける。そして、コンパイルを担当するプロセスが生成した機械コードや制御にかかわるデータを配置するメモリ領域を、コンパイルを担当するプロセスからは書込可能だが、実行を担当するプロセスからは読込可能であっても書込可能でない領域にする。具体的には、それぞれのプロセスで共有するメモリ領域を設け、ＯＳが提供するメモリ保護の機能を使って、該領域を、コンパイルを担当するプロセスから書込可能にし、実行を担当するプロセスからは読込可、書込不可に指定する。
【発明の効果】
【０００９】
本発明を適用すると、プログラムの実行を担当するプロセスが、攻撃者からの入力を受けとったとしても、動的コンパイラが生成した機械コードなどを上書きすることは困難になる。また、本発明はＭＶＭとは異なり、プロセスを、Ｊａｖａで記述したプログラムの実行担当（およびＪａｖａで記述したプログラムの動的コンパイル担当）と、Ｃ言語で記述したプログラムの実行担当に分割する訳ではないので、Ｊａｖａで記述したプログラムからＣ言語で記述したプログラムを呼び出す際に、プロセス間通信が必要になって大きなオーバヘッドが生じることはない。
【００１０】
本発明の適用によって生じるオーバヘッドは，プログラムの実行を担当するプロセスと、コンパイルを担当するプロセス間の通信にある。この通信はプログラムの起動時に頻発するものの、プログラムの恒常的な実行状態においては、ほとんど発生しない。なぜなら、プログラムのコンパイルは、プログラムの起動時に多発するが、プログラムの定常的な実行状態においては、すでに必要なコンパイル処理が終了しているため、ほとんどコンパイルをおこなう必要がないからである。このため、本発明の適用による実行速度の低下は極めて小さい。
【発明を実施するための最良の形態】
【００１１】
ＪａｖａＶＭなど、プログラムを実行時にコンパイルする言語処理系に本発明を適用し、プログラムの実行を担当するプロセスと、コンパイルを担当するプロセスを分離する。
【実施例１】
【００１２】
本発明を適用したＪａｖａＶＭの実行イメージを図１に示す。図１において、ＪａｖａＶＭ１０１はハードディスク１０２にインストールされており、実行時にバス１０３を通じて主記憶１０４に読み込まれ、プロセッサ１０５で実行される。ＪａｖａＶＭは、バス１０３を通じてハードディスク１０２からＪａｖａアプリケーション１０６を読み込み、動的コンパイラでコンパイルして実行する。
【００１３】
本発明のＪａｖａＶＭ１０１は、図１にあるように、実行時に、Ｊａｖａアプリケーションの実行を担当するプロセス１０７と動的コンパイラ１０８の、２つのプロセスに分かれて動作する。それぞれのプロセスは共有メモリ領域１０９によって接続されている。共有メモリ領域１０９は、メモリマップトファイルなどとして実現できる。共有メモリ領域１０９の中には、通信用領域１１０と、保護領域１１１がある。通信用領域１１０には、２つのプロセスが通信をおこなうために用いるデータ構造を配置し、保護領域１１１には、動的コンパイラ１０８が生成したコンパイル済コード１１２や、コンパイル済コードのアドレス１１３を登録する表であるディスパッチ表１１４を配置する。ディスパッチ表１１４に登録してあるデータである、コンパイル済コードのアドレス１１３は、動的コンパイラが生成するデータの実施例である。保護領域１１１はＪａｖａアプリケーションの実行を担当するプロセス１０７から書込不可に指定されており、したがって、攻撃者がＪａｖａＶＭに入力を与えても、入力を受けとって処理するのは実行を担当するプロセス１０７であるため、保護領域１１１の中にあるコンパイル済コード１１２やディスパッチ表１１４を書き換えることはできない（実行時スタック１１５やインスタンス用ヒープ領域１１６は書き換えられる）。また、動的コンパイラが機械コードを一時的に保存するコードバッファなどのワーク領域１１７は、動的コンパイラのプロセスのみが参照可能な領域に確保されており、実行を担当するプロセス１０７から読書きできない。したがって、ワーク領域１１７を攻撃対象とすることもできない。
【００１４】
本発明の適用対象である言語処理系（本実施例においてはＪａｖａＶＭ）の実施例を図２に示す。ＪａｖａＶＭは、図２にあるように、まず起動に伴う初期化処理２０１を実施し、次に処理２０２で、ｍａｉｎ（）メソッドから先にあるＪａｖａアプリケーション本体の実行をおこない、最後に終了処理２０３を実施する。
【００１５】
本発明の適用対象は処理２０１の内部にある。処理２０１の実施例を図３に示す。図３では、処理３０１で、共有メモリ領域１０９を読み書き可能な領域として確保し、その内部に通信用領域１１０と保護領域１１１を確保する。続く処理３０２で、通信用領域１１０の中に、プログラムを実行するプロセスがコンパイル対象として指定するメソッドの待ち行列３０３を生成し、空の待ち行列として初期化する。処理３０２が終了したら、処理３０４に進み、動的コンパイラを子プロセス１０８として起動する。処理３０４以降、親プロセスはプログラムの実行を担当するプロセス１０７となる。親プロセスは処理３０４が終了したら、処理３０５に進み、処理３０１で確保した領域のうち、保護領域１１１を書込不可に指定して保護する。
【００１６】
本発明を適用しない場合における、処理２０１の実施例を図４に、図４の処理２０１を使う従来のＪａｖａＶＭの実行イメージを図５に示す。図４では、処理４０１でヒープ領域４０２を確保し、その内部に通信用領域１１０とコード領域４０３を確保する。続く処理３０２で、通信用領域１１０の中に、プログラムを実行するプロセスがコンパイル対象として指定するメソッドの待ち行列３０３を生成し、空の待ち行列として初期化する。処理３０２が終了したら、処理４０４に進み、動的コンパイラをスレッドとして起動する。図４では、コード領域４０３に保護をかけることはしない。なぜなら、一般的なスレッドの実装では、特定のスレッドのみ書込可能なメモリ領域を設定することは不可能であり、処理４０４で起動する動的コンパイラのスレッドがコード領域４０３に書込可能である必要がある以上、コード領域４０３を書込不可に設定できないからである。図５を参照すると、実行担当のスレッド５０１と動的コンパイラのスレッド５０２が同一のプロセス５０３内で動作しており、コード領域４０３が、実行担当のスレッド５０１からも書込可能になっていることが判る。
【００１７】
図３と図４を比較すると、処理３０１と処理３０４、処理３０５が本発明の適用対象となっていることが判る。すなわち、処理３０１は、従来の処理４０１とは異なり、動的コンパイラが参照しうる領域を、ただのヒープ領域４０２ではなく、共有メモリ領域１０９として確保する。また、処理３０４は、従来の処理４０４とは異なり、動的コンパイラをスレッドではなく、子プロセス１０８として起動し、処理３０５は保護領域１１１を書込不可と指定して保護する。この結果、図２の処理２０２を実行している過程で、Ｊａｖａアプリケーションの実行を担当するプロセス１０７が、攻撃者からの入力を受けとっても、動的コンパイラの生成した機械コードやデータを書き換えることは困難になる。これに対し、図４では動的コンパイル済みコードを配置するための領域４０３を書込不可としないので、動的コンパイル済みコードが書き換えられ、攻撃者に任意のコードを実行される可能性がある。
【産業上の利用可能性】
【００１８】
本発明をＪａｖａＶＭのように、プログラムを動的にコンパイルする言語処理系に適用することにより、実行速度をほとんど低下させることなく、動的コンパイラが生成する機械コードやデータへの攻撃（書換え）によって、制御を奪うことを困難にできる。
【図面の簡単な説明】
【００１９】
【図１】本発明を適用したＪａｖａＶＭの実行イメージ
【図２】ＪａｖａＶＭの実施例
【図３】本発明を適用済の処理２０１の実施例
【図４】本発明を未適用の処理２０１の実施例
【図５】従来のＪａｖａＶＭの実行イメージ
【符号の説明】
【００２０】
１０９  共有メモリ領域
１１０  通信用領域
１１１  動的コンパイラが生成した機械コードやデータを配置する領域
３０１  共有メモリ領域を確保する処理
３０２  コンパイル待ち行列を生成する処理
３０３  コンパイル待ち行列
３０４  動的コンパイラを子プロセスとして起動する処理
３０５  動的コンパイラの出力先領域を書込不可にする処理
【図１】
2006048186.tif 000003
【図２】
2006048186.tif 000004
【図３】
2006048186.tif 000005
【図４】
2006048186.tif 000006
【図５】
2006048186.tif 000007