(57)【要約】【課題】時間的・空間的オーバーヘッドを抑制しつつ、ドメイン間の実行制限を考慮して、非信頼ドメインからの関数コール時と関数リターン時のアドレスチェックを効率よく行う。【解決手段】ソフトウェア検査装置は、ソフトウェアに対して、第１レイヤから第２レイヤへの関数のコール先がコードセグメント内であるか否か、関数のコール先アドレスの所定バイト前のコールポイントＩＤに基づいて関数のコール許可があるか否か、を判定するためのチェックコードを、第１のレイヤの関数をコールする前の箇所に挿入し、各レイヤから第２レイヤへ関数をコールすることができるか否かを示すビット列を含むコールポイントＩＤを決定し、このコールポイントＩＤを第２レイヤの関数開始の所定バイト前に挿入する演算処理部１２を備えている。【選択図】図１
2011123658.tif 000002
【特許請求の範囲】
【請求項１】
非信頼ドメインである第１レイヤ及び信頼ドメインである第２レイヤを含むソフトウェアに対して、前記第１レイヤから第２レイヤへの関数のコール先がコードセグメント内であるか否か、前記関数のコール先アドレスの所定バイト前のコールポイントＩＤに基づいて前記関数のコール許可があるか否か、を判定するためのチェックコードを、前記第１のレイヤの前記関数をコールする前の箇所に挿入するチェックコード挿入手段と、
前記ソフトウェアを構成するレイヤ間で関数をコールすることができるか否かを示すデータに基づいて、前記ソフトウェアを構成する各レイヤから前記第２レイヤへ関数をコールすることができるか否かを示すビット列を含むコールポイントＩＤを決定するコールポイントＩＤ決定手段と、
前記コールポイントＩＤ決定手段により決定されたコールポイントＩＤを前記第２レイヤの前記関数開始の所定バイト前に挿入するコールポイントＩＤ挿入手段と、
前記チェックコード挿入手段により前記チェックコードが挿入された前記第１レイヤと、前記コールポイントＩＤ挿入手段により前記コールポイントＩＤが挿入された前記第２レイヤと、を含む前記ソフトウェアをコンパイルするコンパイル手段と、
を備えたソフトウェア検査装置。
【請求項２】
前記コールポイントＩＤ決定手段は、コードセグメントで使用されていないビット列であるコールポイントビットを更に含んだ前記コールポイントＩＤを決定する
請求項１に記載のソフトウェア検査装置。
【請求項３】
前記コンパイル手段によりコンパイルされたソフトウェアに含まれる前記チェックコードに基づいて、前記第１レイヤから第２レイヤへの関数のコール先がコードセグメント内であり、かつ、前記関数のコール許可がある場合に、前記ソフトウェアを実行するソフトウェア実行手段を更に備えた
請求項１に記載のソフトウェア検査装置。
【請求項４】
前記ソフトウェア実行手段は、更に、前記コンパイルされたソフトウェアに含まれる前記チェックコードのコールビットポイントが、前記コールポイントＩＤ決定手段により決定されたコールポイントＩＤのコールビットポイントと同じである場合に、前記ソフトウェアを実行する
請求項３に記載のソフトウェア検査装置。
【請求項５】
非信頼ドメインである第１レイヤ及び信頼ドメインである第２レイヤを含むソフトウェアに対して、前記第１レイヤから第２レイヤへの関数のリターン先がコードセグメント内であるか否か、前記関数のリターン先アドレスの所定バイト後のリターンポイントＩＤに基づいて前記関数のリターン許可があるか否か、を判定するためのチェックコードを、前記第１のレイヤの前記関数をリターンする前の箇所に挿入するチェックコード挿入手段と、
前記ソフトウェアを構成するレイヤ間で関数をリターンすることができるか否かを示すデータに基づいて、前記第２レイヤから前記ソフトウェアを構成する各レイヤへ関数をリターンすることができるか否かを示すビット列を含むリターンポイントＩＤを決定するリターンポイントＩＤ決定手段と、
前記リターンポイントＩＤ決定手段により決定されたリターンポイントＩＤを前記第１レイヤの前記関数コールの所定バイト後に挿入するリターンポイントＩＤ挿入手段と、
前記チェックコード挿入手段により前記チェックコードが挿入された前記第１レイヤと、前記リターンポイントＩＤ挿入手段により前記リターンポイントＩＤが挿入された前記第２レイヤと、を含む前記ソフトウェアをコンパイルするコンパイル手段と、
を備えたソフトウェア検査装置。
【請求項６】
前記リターンポイントＩＤ決定手段は、コードセグメントで使用されていないビット列であるリターンポイントビットを更に含んだ前記リターンポイントＩＤを決定する
請求項５に記載のソフトウェア検査装置。
【請求項７】
前記コンパイル手段によりコンパイルされたソフトウェアに含まれる前記チェックコードに基づいて、前記第１レイヤから第２レイヤへの関数のリターン先がコードセグメント内であり、かつ、前記関数のリターン許可がある場合に、前記ソフトウェアを実行するソフトウェア実行手段を更に備えた
請求項５に記載のソフトウェア検査装置。
【請求項８】
前記ソフトウェア実行手段は、更に、前記コンパイルされたソフトウェアに含まれる前記チェックコードのリターンビットポイントが、前記リターンポイントＩＤ決定手段により決定されたリターンポイントＩＤのリターンビットポイントと同じである場合に、前記ソフトウェアを実行する
請求項７に記載のソフトウェア検査装置。
【請求項９】
コンピュータを請求項１から請求項８のいずれか１項に記載のソフトウェア検査装置の各手段として機能させるためのソフトウェア検査プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、ソフトウェア検査装置及びプログラムに関する。
【背景技術】
【０００２】
宇宙機器、航空システム、車載システムなどの様々な制御ソフトウェアは、近年、高度の信頼性が要求され、ソフトウェアの大規模化・複雑化が顕著に進んでいる。そして、ソフトウェアの大規模化・複雑化に伴って、バグが残留する可能性が高まっている。
【０００３】
これに対して、実行時にセキュリティチェックを行うように、言語処理によってチェック処理を追加する方法が提案されている（特許文献１参照）。特許文献１の技術は、入力プログラム中の関数ポインタ変数を検出し、関数ポインタが指すことが可能な関数のリストを作成し、関数ポインタ変数を用いた関数呼出しの直前に、当該関数リストを使用して、関数ポインタ変数の値が不正な値でないか調べる。
【先行技術文献】
【特許文献】
【０００４】
【特許文献１】特開２００７−４１７７７号公報
【発明の概要】
【発明が解決しようとする課題】
【０００５】
しかし、特許文献１の技術は、実行時に関数リストと比較するために、呼び出す可能性のある関数の個数が多くなると、比較のためのオーバーヘッドが顕著になる問題が生じてしまう（時間的オーバーヘッドの増加）。また、呼び出す可能性のある関数の個数が多くなると、関数リストを保存しておくための領域も大きくなる問題もある（空間的オーバーヘッドの増加）。
【０００６】
さらに、残留するバグの１つとして、ソフトウェア内部に存在する、間接アドレッシング（関数ポインタ）を用いた非信頼ドメインからの不適切な関数コール、又は、非信頼ドメインからの不適切な関数リターンによって、設計者の意図しない命令列を実行してしまうことが挙げられる一方で、特許文献１の技術はこれを実行時に防止できない。
【０００７】
本発明は、上述した課題を解決するために提案されたものであり、時間的・空間的オーバーヘッドを抑制しつつ、ドメイン間の実行制限を考慮して、非信頼ドメインからの関数コール時と関数リターン時のアドレスチェックを効率よく行うことができるソフトウェア検査装置及びプログラムを提供することを目的とする。
【課題を解決するための手段】
【０００８】
本発明に係るソフトウェア検査装置は、非信頼ドメインである第１レイヤ及び信頼ドメインである第２レイヤを含むソフトウェアに対して、前記第１レイヤから第２レイヤへの関数のコール先がコードセグメント内であるか否か、前記関数のコール先アドレスの所定バイト前のコールポイントＩＤに基づいて前記関数のコール許可があるか否か、を判定するためのチェックコードを、前記第１のレイヤの前記関数をコールする前の箇所に挿入するチェックコード挿入手段と、前記ソフトウェアを構成するレイヤ間で関数をコールすることができるか否かを示すデータに基づいて、前記ソフトウェアを構成する各レイヤから前記第２レイヤへ関数をコールすることができるか否かを示すビット列を含むコールポイントＩＤを決定するコールポイントＩＤ決定手段と、前記コールポイントＩＤ決定手段により決定されたコールポイントＩＤを前記第２レイヤの前記関数開始の所定バイト前に挿入するコールポイントＩＤ挿入手段と、前記チェックコード挿入手段により前記チェックコードが挿入された前記第１レイヤと、前記コールポイントＩＤ挿入手段により前記コールポイントＩＤが挿入された前記第２レイヤと、を含む前記ソフトウェアをコンパイルするコンパイル手段と、を備えている。
【０００９】
本発明に係るソフトウェア検査装置は、非信頼ドメインである第１レイヤ及び信頼ドメインである第２レイヤを含むソフトウェアに対して、前記第１レイヤから第２レイヤへの関数のリターン先がコードセグメント内であるか否か、前記関数のリターン先アドレスの所定バイト後のリターンポイントＩＤに基づいて前記関数のリターン許可があるか否か、を判定するためのチェックコードを、前記第１のレイヤの前記関数をリターンする前の箇所に挿入するチェックコード挿入手段と、前記ソフトウェアを構成するレイヤ間で関数をリターンすることができるか否かを示すデータに基づいて、前記第２レイヤから前記ソフトウェアを構成する各レイヤへ関数をリターンすることができるか否かを示すビット列を含むリターンポイントＩＤを決定するリターンポイントＩＤ決定手段と、前記リターンポイントＩＤ決定手段により決定されたリターンポイントＩＤを前記第１レイヤの前記関数コールの所定バイト後に挿入するリターンポイントＩＤ挿入手段と、前記チェックコード挿入手段により前記チェックコードが挿入された前記第１レイヤと、前記リターンポイントＩＤ挿入手段により前記リターンポイントＩＤが挿入された前記第２レイヤと、を含む前記ソフトウェアをコンパイルするコンパイル手段と、を備えている。
【発明の効果】
【００１０】
本発明に係るソフトウェア検査装置及びプログラムは、ドメイン間の実行制限を考慮しつつ、非信頼ドメインからの関数コール時と関数リターン時のアドレスチェックを効率よく行うことができる。
【図面の簡単な説明】
【００１１】
【図１】本発明の実施形態に係るソフトウェア検査装置の構成を示すブロック図である。
【図２】検査対象であるソフトウェアの各レイヤの一例を示す図である。
【図３】ソフトウェア検査装置による検査内容の概要を示す図である。
【図４】本実施形態に係るコールリターン許可表を示す図である。
【図５】本実施形態のラベルの構成を示す図である。
【図６】コール部分のコンパイル実行ルーチンを示すフローチャートである。
【図７】コール部分のコンパイル実行ルーチンを示すフローチャートである。
【図８】コール部分のコンパイル実行ルーチンを示すフローチャートである。
【図９】コンパイル実行ルーチンによって変換されるＳＷ−Ｃを示す図である。
【図１０】コンパイル実行ルーチンによって変換されるＬｉｂを示す図である。
【図１１】リターン部分のコンパイル実行ルーチンを示すフローチャートである。
【図１２】リターン部分のコンパイル実行ルーチンを示すフローチャートである。
【図１３】リターン部分のコンパイル実行ルーチンを示すフローチャートである。
【図１４】コンパイル実行ルーチンによって変換されるＳＷ−Ｃを示す図である。
【図１５】コンパイル実行ルーチンによって変換されるＲＴＯＳを示す図である。
【図１６】ソフトウェアのコール部分のソフトウェア実行ルーチンを示すフローチャートである。
【図１７】ソフトウェアのリターン部分のソフトウェア実行ルーチンを示すフローチャートである。
【発明を実施するための形態】
【００１２】
以下、本発明の好ましい実施の形態について図面を参照しながら詳細に説明する。
【００１３】
［ソフトウェア検査装置の構成］
図１は、本発明の実施形態に係るソフトウェア検査装置１０の構成を示すブロック図である。ソフトウェア検査装置１０は、検査対象であるソフトウェア（オリジナルソースコード）をコンパイルし、コンパイルされたコードを検査しながら実行する。
【００１４】
ソフトウェア検査装置１０は、データが入力又は出力されるデータ入出力部１１と、ソフトウェアを検査するための演算処理を行う演算処理部１２と、入力されたデータを記憶するデータ記憶部１３と、データのワークエリアであるランダムアクセスメモリ（ＲＡＭ）１４と、演算処理部１２の制御プログラムが記憶されたリードオンリーメモリ（ＲＯＭ）１５と、ソフトウェアの検査結果を出力する検査結果出力部１６と、を備えている。
【００１５】
なお、データ記憶部１３には、データ入出力部１１を介して入力された、オリジナルソースコード、コールリターン許可表のデータが記憶される。また、検査結果出力部１６は、ソフトウェアを検査した結果、エラー（セグメント違反、不正なリターンなど）が見つけられた場合に、そのエラー内容を画像または音声により出力する。
【００１６】
図２は、検査対象であるソフトウェアの各レイヤの一例を示す図である。このソフトウェアは、信頼ドメインである複数のレイヤ（例えばオペレーティング・システム（ＯＳ））と、非信頼ドメインであるレイヤと、で構成されている。
【００１７】
信頼ドメインのレイヤとしては、ＲＴＯＳ（リアルタイム・オペレーティング・システム）、ＣＯＭ、Ｌｉｂ（ライブラリ）が該当する。非信頼ドメインのレイヤとしては、ＳＷ−Ｃ（ソフトウェア・コンポーネント）が該当する。
【００１８】
本実施形態では、コール／リターンについて次のようなレイヤ間実行ポリシー（レイヤ間の実行制限）が存在する。
【００１９】
１．ＳＷ−Ｃは、ＳＷ−Ｃ又はＬｉｂへのみコール可能である。
（ＳＷ−Ｃは、ＳＷ−Ｃ又はＬｉｂからのみリターン可能である。）
【００２０】
２．ＳＷ−Ｃは、ＳＷ−Ｃ又はＲＴＯＳからのみコール可能である。
（ＳＷ−Ｃは、ＳＷ−Ｃ又はＲＴＯＳへのみリターン可能である。）
【００２１】
３．上記以外の組合せは、すべてコール／リターン可能である。
【００２２】
図３は、ソフトウェア検査装置１０による検査内容の概要を示す図である。予め、オペレータは、ソフトウェアの各レイヤが信頼ドメインであるか非信頼ドメインであるかを示すソフトウェアレイヤ表と、レイヤ間のコール／リターンが可能か否かを示すレイヤ間実行ポリシーと、に基づいて、コールリターン許可表を作成する。
【００２３】
ここで、ソフトウェアレイヤ表は、検査対象のソフトウェアを構成する全レイヤについて、例えば、レイヤ１は信頼ドメイン、レイヤ２は非信頼ドメイン、・・・、レイヤｋは信頼ドメイン、であることを示している。レイヤ間実行ポリシーは、検査対象のソフトウェアを構成する各レイヤについて、例えば、レイヤ１はレイヤ１またはレイヤ２へのみコール可能（レイヤ１はレイヤ１またはレイヤ２からのみリターン可能）、レイヤ２は・・・、であることを示している。
【００２４】
このように、コールリターン許可表は、レイヤ間のコール／リターンの実行制限を記述したものであり、１行目のＣａｌｌｅｒはコールする側であり、一番左側の列のＣａｌｌｅｅはコールされる（リターンさせる）側である。
【００２５】
次に、ソフトウェア検査装置１０は、このコールリターン許可表のデータを用いてオリジナルソースコードのコンパイルを実行し、制御フロー保護コードであるオブジェクトを生成する。コンパイルの実行中では、ソフトウェア検査装置１０は、コール部分とリターン部分のそれぞれに所定の条件をチェックするためのコードを挿入し、ラベルを決定し、決定したラベルをバイナリへ埋め込む。
【００２６】
なお、ラベルとは、コールポイントＩＤ及びリターンポイントＩＤの総称である。コールポイントＩＤは、コール許可ビット（ｘビット）、コールポイントビット（ｙビット）で構成されている。リターンポイントＩＤは、リターン許可ビット（ａビット）、リターンポイントビット（ｂビット）で構成されている。
【００２７】
最後に、ソフトウェア検査装置１０は、コール／リターンの実行制限をチェックしながら制御フロー保護コードに基づいてソフトウェアを実行する。なお、本実施形態では、次のようなコールリターン許可表が使用される。
【００２８】
図４は、本実施形態に係るコールリターン許可表を示す図である。コールリターン許可表は、どのレイヤからどのレイヤへのコール／リターンが可能か不可能かを示している。
【００２９】
例えば、左から３列目の「Ｌｉｂ／０／１／１／１」によると、ＣａｌｌｅｒがＬｉｂの場合、Ｌｉｂは、ＳＷ−Ｃへのコール（及びＳＷ−Ｃからのリターン）が不可能であるが、Ｌｉｂ、ＣＯＭ、ＲＴＯＳへのコール（及びＬｉｂ、ＣＯＭ、ＲＴＯＳからのリターン）が可能である。また、上から３行目の「Ｌｉｂ／１／１／１／１」によると、ＣａｌｌｅｅがＬｉｂの場合、Ｌｉｂはすべてのレイヤからのリターンが可能（及びすべてのレイヤはＬｉｂへコールが可能）である。
【００３０】
そして、コールリターン許可表のデータは、ソフトウェア検査装置１０に入力され、コンパイル実行時に使用される。また、コンパイル実行時では、図４に示すコールリターン許可表に基づいて次のように構成されたラベルが決定される。
【００３１】
図５は、本実施形態のラベルの構成を示す図である。ラベルの１つであるコールポイントＩＤ（３２ビット）は、コール許可ビット（ｘ＝４ビット）、コールポイントビット（ｙ＝２８ビット）で構成されている。ラベルの残りの１つであるリターンポイントＩＤ（３２ビット）は、リターン許可ビット（ａ＝４ビット）、リターンポイントビット（ｂ＝２８ビット）で構成されている。
【００３２】
コール許可ビット及びリターン許可ビットは、コールリターン許可表に基づいて決定される。コールポイントビット及びリターンポイントビットは、ＲＯＭ１５のコード領域で使用されていないビット列であり、コンパイル時に静的に決定される。
【００３３】
以上のように構成されたソフトウェア検査装置１０では、次に示すコンパイル実行ルーチンが実行される。
【００３４】
［ソフトウェアのコール部分のコンパイル］
図６から図８は、コール部分のコンパイル実行ルーチンを示すフローチャートである。以下の各ルーチンでは、図４に示すコールリターン許可表、図５に示すラベルが使用される。また、コードセグメントは、ＲＯＭ１５の領域にあり、プログラム自身で書き換えできないものとする。よって、本ルーチン実行時に埋め込まれたコールポイントＩＤ及びリターンポイントＩＤは不変である。
【００３５】
また、本ルーチンでは、ＳＷ−Ｃ（非信頼ドメイン）からＬｉｂ（信頼ドメイン）のコールを例に挙げて説明する。なお、図９は、コンパイル実行ルーチンによって変換されるＳＷ−Ｃを示す図である。図１０は、コンパイル実行ルーチンによって変換されるＬｉｂを示す図である。
【００３６】
図６に示すステップＳ１では、演算処理部１２は、コールリターン許可表の行のビット数を“ｎ”に設定する。本実施形態ではｎ＝４に設定する。
【００３７】
ステップＳ２では、演算処理部１２は、コードセグメントで使用されていないビット列を用いて、命令ビット数からｎを除いたビット数でコールポイントビットをランダムに決定し、この決定したものを“ＣＰＢ”に設定する。本実施形態では、命令ビット数は図５に示すように３２であるので、命令ビット数３２からｎ（＝４）を除いた２８ビットのＣＰＢが設定される。
【００３８】
ステップＳ３では、演算処理部１２は、ランタイムチェック（チェックコード）を挿入しようとしている非信頼ドメインのレイヤを“Ｌ”に設定する。本実施形態では、非信頼ドメインであるＳＷ−Ｃが“Ｌ”に設定される。
【００３９】
ステップＳ４では、演算処理部１２は、図４に示すコールリターン許可表より“Ｌ”がＭＳＢ（最上位ビット）から何行目を示すかを“ｂ”に設定する。
【００４０】
ステップＳ５では、演算処理部１２は、命令ビット数３２のうちｂビット目のみを１にして残りを０としたビット列を“ｍａｓｋＢｉｔ１”に設定する。本実施形態では、“ｍａｓｋＢｉｔ１”に、例えば０ｘ８０００００００が設定される。
【００４１】
ステップＳ６では、演算処理部１２は、上位ｎビットを０にしてその他を１にしたビット列を“ｍａｓｋＢｉｔ２”に設定する。本実施形態では、“ｍａｓｋＢｉｔ２”に、例えば０ｘ０ｆｆｆｆｆｆｆが設定される。
【００４２】
ステップＳ７では、演算処理部１２は、コードセグメントの開始アドレスをＳＴ＿ＣＯＤＥＳＥＧに設定し、続くステップＳ８では、コードセグメントの終了アドレスをＥＤ＿ＣＯＤＥＳＥＧに設定する。
【００４３】
図７に示すステップＳ９では、演算処理部１２は、Ｌに属するコードの構文解析を行い、構文の全体集合をＧに設定する。本実施形態では、非信頼ドメインのレイヤであるＳＷ−Ｃに属するコードの構文解析が行われる。
【００４４】
ステップＳ１０では、演算処理部１２は、構文の全体集合Ｇが存在する（Ｇが空集合φではない）かを判定する。そして、Ｇが存在する場合はステップＳ１１へ進み、Ｇが存在しない場合はステップＳ１５へ進む。
【００４５】
ステップＳ１１では、演算処理部１２は、Ｇから構文を１つ取り出してｇに設定し、続くステップＳ１２では、ｇが関数ポインタを使用しているかを判定する。例えば、データ記憶部１３には多くの関数ポインタが記憶され、演算処理部１２は、これらの関数ポインタを参照して、ｇが関数ポインタを使用しているかを判定すればよい。ｇが関数ポインタを使用している場合はステップＳ１３へ進み、使用していない場合はステップＳ１０へ戻る。
【００４６】
ステップＳ１３では、演算処理部１２は、ｇで使用している関数ポインタの変数名をｆｐｔｒＮａｍｅに設定し、図９（Ａ）の（＊ｆｐｔｒＮａｍｅ）（）の部分を以下のものに置換する（ステップＳ１４）。
【００４７】
【数１】
2011123658.tif 000003
【００４８】
すなわち、演算処理部１２は、関数をコールする前（図９（Ａ）の下から２行目の“（＊ｆｐｔｒＮａｍｅ）（）；”の前）の部分に、２つのｉｆ文を含むチェックコードを挿入している。
【００４９】
一方、図７に示すステップＳ１５では、演算処理部１２は、検査対象のソフトウェアのすべての非信頼ドメインのレイヤに対してステップＳ１０〜Ｓ１４を実行したかを判定する。肯定判定の場合は図８に示すステップＳ１６へ進み、否定判定の場合は図６に示すステップＳ３へ戻る。
【００５０】
図８に示すステップＳ１６では、演算処理部１２は、非信頼ドメインのレイヤに対して、コードをコンパイルしバイナリを生成する。
【００５１】
ステップＳ１７では、演算処理部１２は、図４に示すコールリターン許可表のｂ行目を上位ｎ（＝４）ビットとしたコール許可ビットと、残りの２８ビットをＣＰＢとしたビット列とを用いて、図５に示すように、コールポイントＩＤを決定する。
【００５２】
ステップＳ１８では、演算処理部１２は、信頼ドメインのレイヤに対して、コードをコンパイルしバイナリを生成する。ここで、バイナリ生成時には、演算処理部１２は、信頼ドメインの関数の先頭に、ステップＳ１７で決定されたコールポイントＩＤを挿入する。
【００５３】
ステップＳ１９では、演算処理部１２は、コードセグメント全体で関数の先頭以外にＣＰＢのビット列が使われていないかを判定する。ＣＰＢのビット列が使われていない場合は本ルーチンを終了し、使われている場合はステップＳ２０へ進む。
【００５４】
ステップＳ２０では、演算処理部１２は、コードセグメント全体で使われていないビット列をＣＰＢに設定して、図６に示すステップＳ３に戻る。
【００５５】
この結果、図９（Ａ）に示すＳＷ−Ｃは、ステップＳ１３において、図９（Ｂ）に示すように、＃１及び＃２のコードが挿入される。ここで、＃１は、関数ポインタがコードセグメント内にあるかを判定し、ない場合はセグメント違反に対するルーチン（ｓｅｇＶｉｏｌａｔｉｏｎ（））へ移行することを示している。また、＃２は、コール許可ビットがコール許可を示し、かつ、コールポイントビットと等しいか、を判定し、これらの条件を満たさない場合は、不正なリターンに対処するエラールーチン（ｅｒｒｏｒＨｏｏｋ（））へ移行することを示している。＃３は、＃１及び＃２を満たす場合は、間接コールが実行されることを示している。そして、図９（Ｂ）がコンパイルされると、図９（Ｃ）に示す制御フロー保護コードが生成される。
【００５６】
また、図１０（Ａ）に示すＬｉｂがコンパイルされると、図１０（Ｂ）に示すように、ｌｉｂＦｕｎｃ１、ｌｉｂＦｕｎｃ２のそれぞれの関数の先頭にコールポイントＩＤ“ｆ１  ｆｂ  ３ａ  ２ｃ”が挿入される。
【００５７】
ここで、図１０（Ａ）及び（Ｂ）に示すＬｉｂはコールされる側であるので、ステップＳ１７において、図４に示すコールリターン許可表の３行目（Ｃａｌｌｅｅがｌｉｂの場合）の“１１１１”がコールポイントＩＤの上位４ビットとして選択される。“１１１１”は１６進数で“ｆ”であるので、図１０（Ｂ）に示すコールポイントＩＤの先頭は“ｆ”となる。コールポイントＩＤの残りの“１  ｆｂ  ３ａ  ２ｃ”はコールポイントビットである。
【００５８】
［ソフトウェアのリターン部分のコンパイル］
図１１〜図１３は、リターン部分のコンパイル実行ルーチンを示すフローチャートである。
【００５９】
本ルーチンでは、ＳＷ−Ｃ（非信頼ドメイン）からＲＴＯＳ（信頼ドメイン）へのリターンを例に挙げて説明する。なお、図１４は、コンパイル実行ルーチンによって変換されるＳＷ−Ｃを示す図である。図１５は、コンパイル実行ルーチンによって変換されるＲＴＯＳを示す図である。
【００６０】
図１１に示すステップＳ３１では、演算処理部１２は、コールリターン許可表の行のビット数を“ｎ”に設定する。本実施形態ではｎ＝４に設定する。
【００６１】
ステップＳ３２では、演算処理部１２は、コードセグメントで使用されていないビット列を用いて、命令ビット数からｎを除いたビット数でリターンポイントビットをランダムに決定し、この決定したものを“ＲＰＢ”に設定する。本実施形態では、命令ビット数３２からｎ（＝４）を除いた２８ビットのＲＰＢが設定される。そして、ステップＳ３３〜Ｓ３９は、ステップＳ３〜Ｓ９と同様に実行され、図１２に示すステップＳ４０へ進む。
【００６２】
ステップＳ４０では、演算処理部１２は、構文の全体集合Ｇが存在する（Ｇが空集合φではない）かを判定する。そして、Ｇが存在する場合はステップＳ４１へ進み、Ｇが存在しない場合はステップＳ４７へ進む。
【００６３】
ステップＳ４１では、演算処理部１２は、Ｇから構文を１つ取り出してｇに設定し、続くステップＳ４２では、ｇが関数の先頭を表しているかを判定する。ｇが関数の先頭を表している場合はステップＳ４３へ進み、それを表していない場合はステップＳ４０へ戻る。
【００６４】
ステップＳ４３では、演算処理部１２は、関数の先頭で、変数ｉｎｔ  ｄｕｍｍｙＮｕｍの宣言を挿入し、ステップＳ４４では、構文の全体集合Ｇから構文を１つ取り出してｇに設定する。
【００６５】
ステップＳ４５では、演算処理部１２は、ｇが関数の最後を表しているかを判定する。ｇが関数の最後を表している場合はステップＳ４６へ進み、それを表していない場合はステップＳ４４へ戻る。
【００６６】
ステップＳ４６では、演算処理部１２は、関数の最後に以下のコードを挿入する。
【００６７】
【数２】
2011123658.tif 000004
【００６８】
すなわち、演算処理部１２は、関数をリターンする前（図１４（Ａ）の“｝”の直前）の部分に、２つのｉｆ文を含むチェックコードを挿入している。
【００６９】
ステップＳ４７では、演算処理部１２は、すべての非信頼ドメインのレイヤに対してステップＳ４０〜Ｓ４６を実行したかを判定する。肯定判定の場合は図１３に示すステップＳ４８へ進み、否定判定の場合は図１１に示すステップＳ３３へ戻る。
【００７０】
ステップＳ４８では、演算処理部１２は、非信頼ドメインのレイヤに対して、コードをコンパイルしバイナリを生成する。
【００７１】
ステップＳ４９では、演算処理部１２は、図４に示すコールリターン許可表のｂ行目を上位ｎ（＝４）ビットとしたリターン許可ビットと、残りの２８ビットをＲＰＢとしたビット列とを用いて、リターンポイントＩＤを決定する。
【００７２】
ステップＳ５０では、演算処理部１２は、信頼ドメインのレイヤに対して、コードをコンパイルしバイナリを生成する。ここで、バイナリ生成時には、演算処理部１２は、信頼ドメインの関数コールの直後にリターンポイントＩＤを挿入する。
【００７３】
ステップＳ５１では、演算処理部１２は、コードセグメント全体で関数の先頭以外にＲＰＢのビット列が使われていないかを判定する。ＲＰＢのビット列が使われていない場合は本ルーチンを終了し、それが使われている場合はステップＳ５２へ進む。
【００７４】
ステップＳ５２では、演算処理部１２は、コードセグメント全体で使われていないビット列をＲＰＢに設定して、図１１に示すステップＳ３３に戻る。
【００７５】
この結果、図１４（Ａ）に示すＳＷ−Ｃは、ステップＳ４６において、図１４（Ｂ）に示すように、＃４及び＃５のコードが挿入される。ここで、＃４は、リターンアドレス（ステップＳ４３で最初に挿入したダミー変数を使用）がコードセグメント内にあるかを判定し、ない場合はセグメント違反に対するルーチンへ移行することを示している。また、＃５は、リターン許可ビットがリターン許可を示し、かつ、リターンポイントビットと等しいか、を判定し、これらの条件を満たさない場合は、不正なリターンに対処するエラールーチンへ移行することを示している。＃６は、リターンアドレスをインクリメントしてコードを指すようにすることを示している。そして、図１４（Ｂ）がコンパイルされると、図１４（Ｃ）に示す制御フロー保護コードが生成される。
【００７６】
また、図１５（Ａ）に示すＲＴＯＳがコンパイルされると、図１５（Ｂ）に示すように、関数コール（ＣＡＬＬ  ＳＷ＿Ｃ）の直後に、リターンポイントＩＤ“ｆ２  ｆａ  ３ｃ  ｂｄ”が挿入される。
【００７７】
ここで、図１５（Ａ）及び（Ｂ）に示すＲＴＯＳはコールする側であるので、ステップＳ４９において、図４に示すコールリターン許可表の４列目（ＣａｌｌｅｒがＲＴＯＳの場合）の“１１１１”がリターンポイントＩＤの上位４ビットとして選択される。“１１１１”は１６進数で“ｆ”であるので、図１５（Ｂ）に示すリターンポイントＩＤの先頭は“ｆ”となる。リターンポイントＩＤの残りの“２  ｆａ  ３ｃ  ｂｄ”はリターンポイントビットである。そして、ＳＷ−Ｃのコール直後のスタック内容は図１５（Ｃ）に示すようになる。
【００７８】
［ソフトウェアのコール部分の実行］
図１６は、ソフトウェアのコール部分のソフトウェア実行ルーチンを示すフローチャートである。本ルーチンでは、ステップＳ１〜Ｓ２０の処理によってコンパイルされたソフトウェア（図９及び図１０）を例に挙げて説明する。
【００７９】
ステップＳ６１では、演算処理部１２は、コンパイルされたソフトウェアのチェックコードに基づいて、関数ポインタ（ｆｐｔｒ）がコードセグメント内（セグメント開始アドレスからセグメント終了アドレスの間）を指しているかを判定する。
【００８０】
ここでは、例えば、図９（Ｂ）の＃１のチェックコードに基づいて、［ｆｐｔｒ＜コードセグメント開始アドレス］を満たすか否か、［ｆｐｔｒ＞コードセグメント終了アドレス］を満たすか否かが判定される。いずれも満たさない場合に、関数ポインタがコードセグメント内を指していると判定される。
【００８１】
そして、関数ポインタがコードセグメント内を指している場合はステップＳ６２へ進み、それを指していない場合はステップＳ６８へ進む。
【００８２】
ステップＳ６２では、演算処理部１２は、関数ポインタから１を引いた値（ｆｐｔｒ−１）について間接参照した値をコールポイントＩＤ（ｃａｌｌＰｏｉｎｔＩｄ）に設定する（ｃａｌｌＰｏｉｎｔＩｄ←ｆｐｔｒ−１）。そして、ステップＳ６３へ進む。
【００８３】
ステップＳ６３では、演算処理部１２は、コールポイントＩＤの上位ｘビットをコール許可ビット（ｃａｌｌＡｌｌｏｗｉｎｇＢｉｔ）に設定する。なお、本実施形態ではｘ＝４とし、（ｃａｌｌＡｌｌｏｗｉｎｇＢｉｔ←ｃａｌｌＰｏｉｎｔＩｄの上位４ビット）となる。そして、ステップＳ６４へ進む。
【００８４】
ステップＳ６４では、演算処理部１２は、コール許可ビットに基づいて当該ドメインのレイヤについてコール許可があるかを判定する。
【００８５】
ここでは、例えばコール許可ビット（ｃａｌｌＡｌｌｏｗｉｎｇＢｉｔ）の最上位ビットを取り出してビットが立っていないかが判定される。その最上位ビットが立っている場合、当該ドメインのコール許可があることを示すので、ステップＳ６５へ進む。ＳＷ−Ｃからのコール許可の有無はコールリターン許可表から分かるので、コールリターン許可表から求められたｃａｌｌＡｌｌｏｗｉｎｇＢｉｔの最上位ビットをみればコール許可の有無が分かる。一方、その最上位ビットが立っていない場合、当該ドメインのコール許可がないことを示すので、ステップＳ６９へ進む。
【００８６】
ステップＳ６５では、演算処理部１２は、コールポイントＩＤの下位ｙビットをコールポイントビットに設定する。なお、本実施形態ではｙ＝２８であり、（ｃａｌｌＰｏｉｎｔＢｉｔ←ｃａｌｌＰｏｉｎｔＩｄの下位２８ビット）となる。そして、ステップＳ６６へ進む。
【００８７】
ステップＳ６６では、演算処理部１２は、コールポイントビットとコンパイラ（コンパイル実行ルーチン）が定めたビット列であるＣＰＢが等しい（ｃａｌｌＰｏｉｎｔＢｉｔ＝ＣＰＢ）かを判定する。そして、それらが等しい場合はステップＳ６７へ進み、等しくない場合はステップＳ６９へ進む。
【００８８】
ステップＳ６７では、演算処理部１２は、関数ポインタの値を正当であるとみなし、間接コール（＊ｆｐｔｒ）（）を実行する。そして、本ルーチンが終了する。
【００８９】
なお、ステップＳ６１の否定判定の場合はステップＳ６８へ進み、演算処理部１２は、セグメント違反に対処するエラールーチンｓｅｇＶｉｏｌａｔｉｏｎ（）へ移行する。このエラールーチンは特に限定されるものではないが、例えば、検査結果出力部１６が、セグメント違反であることを示すエラーメッセージを音声または画像で出力する。そして、本ルーチンが終了する。
【００９０】
また、ステップＳ６４の否定判定の場合又はステップＳ６６の否定判定の場合はステップＳ６９へ進み、演算処理部１２は、不正なコールに対処するエラールーチンｅｒｒｏｒＨｏｏｋ（）へ移行する（ステップＳ６９）。このエラールーチンは特に限定されるものではないが、例えば、検査結果出力部１６が、不正なコールであることを示すエラーメッセージを音声または画像で出力する。そして、本ルーチンが終了する。
【００９１】
以上のように、ソフトウェア検査装置１０は、関数のコール先がコードセグメントで、コール許可があり、かつ関数のコールポイント（本実施形態では関数の先頭）であれば、正当なコールとみなして当該関数をコールする。また、ソフトウェア検査装置１０は、上記のいずれか１つの条件を満たさない場合は、不正なコールとみなしてエラーを発行する。
【００９２】
［ソフトウェアのリターン部分の実行］
図１７は、ソフトウェアのリターン部分のソフトウェア実行ルーチンを示すフローチャートである。ここでは、ステップＳ３１〜Ｓ５２の処理によってコンパイルされたソフトウェア（図１４及び図１５）が実行される。
【００９３】
ステップＳ７１では、演算処理部１２は、コンパイルされたソフトウェアのチェックコードに基づいて、リターンアドレス（ｒｅｔＡｄｒ）がコードセグメント内を指しているかを判定する。
【００９４】
ここでは、最初に、コード変換（コンパイル）時において関数の最初に挿入したダミー変数（ｄｕｍｍｙＮｕｍ）が使用されて、リターンアドレス（ｒｅｔＡｄｒ）が求められる。具体的には、ダミー変数のアドレスに１を加えて間接参照した値がリターンアドレスに設定される（ｒｅｔＡｄｒ←ｄｕｍｍｙＮｕｍのアドレス＋１を間接参照した値）。
【００９５】
次に、図１４（Ｂ）の＃４のチェックコードに基づいて、［ｒｅｔＡｄｒ＜コードセグメント開始アドレス］を満たすか否か、［ｒｅｔＡｄｒ＞コードセグメント終了アドレス］を満たすか否か、が判定される。いずれも満たさない場合に、関数ポインタがコードセグメント内を指していると判定される。
【００９６】
そして、リターンアドレスがコードセグメント内を指している場合はステップＳ７２へ進み、それを指していない場合はステップＳ７９へ進む。
【００９７】
ステップＳ７２では、演算処理部１２は、リターンアドレスの間接参照した値をリターンポイントＩＤ（ｒｅｔＰｏｉｎｔＩｄ）に設定する（ｒｅｔＰｏｉｎｔＩｄ←ｒｅｔＡｄｒの間接参照）。そして、ステップＳ７３へ進む。
【００９８】
ステップＳ７３では、演算処理部１２は、リターンポイントＩＤの上位ａビットをリターン許可ビット（ｒｅｔＡｌｌｏｗｉｎｇＢｉｔ）に設定する。なお、本実施形態ではａ＝４とし、（ｒｅｔＡｌｌｏｗｉｎｇＢｉｔ←ｒｅｔＰｏｉｎｔＩｄの上位４ビット）となる。そして、ステップＳ７４へ進む。
【００９９】
ステップＳ７４では、演算処理部１２は、リターン許可ビットに当該ドメインのリターン許可があるかを判定する。
【０１００】
ここでは例えば、ｒｅｔＡｌｌｏｗｉｎｇＢｉｔの最上位ビットを取り出してビットが立っていないかが判定される。その最上位ビットが立っている場合、当該ドメインのリターン許可があることを示すので、ステップＳ７５へ進む。ＳＷ−ＣからＲＴＯＳへのリターン許可の有無はコールリターン許可表から分かるので、コールリターン許可表から求められたｒｅｔＡｌｌｏｗｉｎｇＢｉｔの最上位ビットをみればリターン許可の有無が分かる。一方、その最上位ビットが立っていない場合、当該ドメインのリターン許可がないことを示すので、ステップＳ８０へ進む。
【０１０１】
ステップＳ７５では、演算処理部１２は、リターンポイントＩＤの下位ｂビットをリターンポイントビットに設定する。なお、本実施形態ではｂ＝２８であり、（ｒｅｔＰｏｉｎｔＢｉｔ←ｒｅｔＰｏｉｎｔＩｄの下位２８ビット）となる。そして、ステップＳ７６へ進む。
【０１０２】
ステップＳ７６では、演算処理部１２は、リターンポイントビットとコンパイラ（コンパイル実行ルーチン）が定めたビット列が等しい（ｒｅｔＰｏｉｎｔＢｉｔ＝ＲＰＢ）かを判定する。そして、それらが等しい場合はステップＳ７７へ進み、等しくない場合はステップＳ８０へ進む。
【０１０３】
ステップＳ７７では、演算処理部１２は、ステップＳ７１で説明したリターンアドレス（ｒｅｔＡｄｒ）をインクリメントして、リターン先のコードを指すように修正する。そして、ステップＳ７８に進む。
【０１０４】
なお、ステップＳ７７の実行前では、リターンアドレスがリターンポイントＩＤの領域を指している。そこで、ステップＳ７７において、スタックに格納されているリターンアドレスをインクリメントすることで、リターンアドレスが、リターンした後に実行すべきコードを指すようにしている。
【０１０５】
ステップＳ７８では、演算処理部１２は、リターンを実行する（ステップＳ７８）。そして、本ルーチンが終了する。
【０１０６】
なお、ステップＳ７１の否定判定の場合はステップＳ７９に進み、演算処理部１２は、セグメント違反に対処するエラールーチンｓｅｇＶｉｏｌａｔｉｏｎ（）へ移行する。そして、このエラールーチンが実行されて、本ルーチンが終了する。
【０１０７】
また、ステップＳ７４の否定判定の場合又はステップＳ７６の否定判定の場合はステップＳ８０へ進み、演算処理部１２は、不正なリターンに対処するエラールーチンｅｒｒｏｒＨｏｏｋ（）へ移行する。そして、このエラールーチンが実行されて、本ルーチンが終了する。
【０１０８】
以上のように、ソフトウェア検査装置１０は、関数のリターン先がコードセグメントで、リターン許可があり、かつ関数のリターンポイント（本実施形態ではコールの直後）であれば、正当なリターンとみなし、リターン先のアドレスをインクリメントしてコードを指すようにした後にリターンする。また、ソフトウェア検査装置１０は、上記のいずれか１つの条件を満たさない場合は、不正なリターンとみなしてエラーを発行する。
【０１０９】
この結果、ソフトウェア検査装置１０は、コール時／リターン時におけるソフトウェアのレイヤ間の実行制限を考慮して、設計者の意図する範囲内で、コール／リターンを実行することができる。
【０１１０】
また、ソフトウェア検査装置１０は、リターンアドレスの待避領域に意図しない書き込みができて破壊されるのを防止することで、アドレスチェックの妥当性を保証することができる。
【０１１１】
さらに、ソフトウェア検査装置１０は、コール可能な関数の個数が増加し、またはコールのネストが深くなっても、コール時及びリターン時のアドレスチェックにおける時間的・空間的オーバーヘッドを抑制することができる。
【０１１２】
なお、本発明は、上述した実施の形態に限定されるものではなく、特許請求の範囲に記載された範囲内で設計上の変更をされたものにも適用可能であるのは勿論である。
【符号の説明】
【０１１３】
１１  構文解析部
１２  演算処理部
１３  データ記憶部
１４  ＲＡＭ
１５  ＲＯＭ
１６  検査結果出力部
【図１】
2011123658.tif 000005
【図２】
2011123658.tif 000006
【図３】
2011123658.tif 000007
【図４】
2011123658.tif 000008
【図５】
2011123658.tif 000009
【図６】
2011123658.tif 000010
【図７】
2011123658.tif 000011
【図８】
2011123658.tif 000012
【図９】
2011123658.tif 000013
【図１０】
2011123658.tif 000014
【図１１】
2011123658.tif 000015
【図１２】
2011123658.tif 000016
【図１３】
2011123658.tif 000017
【図１４】
2011123658.tif 000018
【図１５】
2011123658.tif 000019
【図１６】
2011123658.tif 000020
【図１７】
2011123658.tif 000021