2009/08/08
こんな所に桁あふれの問題が潜んでいるとは
APRのセキュリティパッチです(Apache httpdには影響ありません。当然、AirOneも大丈夫です)。
バグの元凶は次のマクロです。
/* APR_ALIGN() is only to be used to align on a power of 2 boundary */ #define APR_ALIGN(size, boundary) \ (((size) + ((boundary) - 1)) & ~((boundary) - 1))
マクロの意図は、第1引数のsize以上かつboundaryの倍数を返すことです。実例の方が分かりやすいので、boundaryを8にして次のコードを動かしてみます。
#include <stdio.h> int main() { unsigned int i; for (i = 0; i < 24; i++) { printf("%u %u\n", i, APR_ALIGN(i, 8)); } return 0; }
結果は次のようになります。
0 0 1 8 2 8 3 8 4 8 5 8 6 8 7 8 8 8 9 16 10 16 11 16 12 16 13 16 14 16 15 16 16 16 17 24 18 24 19 24 20 24 21 24 22 24 23 24
第1引数(size)を入力、マクロの結果を出力と思えば意図は自明だと思います。普通に見ていると、出力は入力以上の数値になりそうです。しかし、セキュリティパッチは、出力が入力(size)より小さくなることがあることを示唆しています。
上のコードのループを次のように変更してみます。
for (i = 0; i < ~0; i++) { if (i > APR_ALIGN(i, 8)) { printf("%u %u\n", i, APR_ALIGN(i, 8)); } }
動かすと次のようになります。
4294967289 0 4294967290 0 4294967291 0 4294967292 0 4294967293 0 4294967294 0
実際に言われてみれば、という感じですが、Apacheのソースコードは相当数の目に晒されてきたはずなのに誰も気づきませんでした。
ここで注目したいのがqmailです。
似た目的のマクロを持っていますが、次のようにしっかりとオーバーフローの可能性を明記しています。さすがdjb、ひとりでASFを越えています。
n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */
- Category(s)
- カテゴリなし
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/inoue/overflow/tbping