JVNVU#162289
ある種の範囲チェックを破棄するC コンパイラの最適化の問題
C コンパイラの中には、最適化処理において、ポインタ演算のオーバーフローチェックを行うコードブロックを省略することがあります。従って、こうしたコンパイラを使ってコンパイルしたアプリケーションは、バッファオーバーフローの影響を受ける可能性があります。
gcc 4.2 およびそれ以降のバージョンで本問題が確認されていますが、他のベンダが提供するコンパイラにも同様の問題が存在する可能性があります。
C 言語で次のような型が与えられたとき
char *buf;
int len;
C コンパイラの中には buf+len >= buf が成立すると仮定するものが存在します。その結果、次に示すような長さチェックを行うコードがコンパイラの最適化によって省かれてしまうことがあります。
len = 1<<30;
[...]
if(buf+len < buf) /* 長さチェック */
[...オーバーフローに対処するコード...]
長さチェックを行うコードが最適化により省略された場合、それに続く len を扱うコードがオーバーフローを引き起こす可能性があります。その結果、この手のチェックを行うプログラムはバッファオーバーフローに対して脆弱になる可能性があります。
上述のような長さチェックの手法はC言語の仕様上は未定義となっている部分の動作に依存しています。 コンパイラが行うこのような最適化は、1999 C specification (§6.5.6p8) の定める未定義の動作に該当するため、C 言語の仕様に沿った実装であると考えられます。コンパイラは、たとえ現時点では該当部分のオブジェクトコードを生成していたとしても、将来にわたってそうする義務はありません。むしろそのような箇所は、将来、最適化の対象となる可能性があります。コンパイラに対するこうした変更がプログラム上の想定される動作を無効にしないためにも、開発者は CERT C Secure Coding Standard の MSC15-C および ARR30-C を参考にエラーを回避するべきです。コンパイラは未定義の動作に対して警告メッセージを出力する義務はないため、多くの場合、問題となる動作を発見することは困難であると考えられます。
この問題はコンパイラ自身の脆弱性ではない点に注意してください。むしろ、上述のようなコードを含み、かつ本問題の影響を受けるコンパイラを使ってコンパイルされたプログラムに脆弱性が作りこまれる可能性があることが問題です。
影響の種類は、上述のようなコードがどう用いられているかにより異なります。
キャストを使う
Cast objects of type 比較を行う前に、オブジェクトの型を char* から uintptr_t にキャストする。上述の長さチェックのコードを例に取ると、
#include
[...]
if((uintptr_t)buf+len < (uintptr_t)buf)
[...]
uintptr_t 型を提供しないプラットフォームでは、size_t を使う方法があります。
新しいバージョンの gcc を避ける
gcc バージョン 4.2 およびそれ以降のバージョンで本問題が発生することが確認されています。
コンパイラフラグを使用する
例えば gcc では -ftrapv フラグを使用することで、符号付き演算のオーバーフロー発生時にプログラムを abort させることが可能です。
-
US-CERT Vulnerability Note VU#162289
C compilers may silently discard some wraparound checks -
MSC15-C
Do not depend on undefined behavior -
ARR30-C
Do not form or use out of bounds pointers or array -
Catching Integer Overflows in C
JPCERT 緊急報告 | |
JPCERT REPORT |
JPCERT-WR-2008-1403 gccがオーバフロー検査のコードを省略する問題 |
CERT Advisory | |
CPNI Advisory | |
TRnotes | |
CVE | |
JVN iPedia |
JVNDB-2008-001324 |
- 2008/08/25
- 関連文書に JVN iPedia へのリンクを追加しました。
- 2012/08/16
- 参考情報等のリンクを更新しました。