#navi(../) * メモリリークなどを探すツール・Electric Fenceを使ってみる [#o5c63b95] mallocのフリー忘れやサイズ0のメモリアロケートなどを検出してくれるElectric Fenceを使ってみました。~ 以下にElectric Fenceの使用例を記します。 使用したOSはCentOS5のx86_64になります。 #contents #htmlinsertpcsp(c-top.html,c-sp.html) * 関連資料・関連記事 [#u9c171aa] -[[EFBIG(errno=27)対処方法>DEBUG/EFBIG(errno=27)対処方法]] -[[メモリリークなどを探すツール・Electric Fence>DEBUG/メモリリークなどを探すツール・Electric Fence]] -[[errnoエラー番号に対する説明を表示する方法・strerror>DEBUG/errnoエラー番号に対する説明を表示する方法・strerror]] -[[C言語ソースコードの行番号を表示する方法>DEBUG/ソースコードの行番号を表示する方法]] -[[Cプログラムが異常終了したときにコアダンプを出力するように設定する>DEBUG/異常終了したときにコアダンプを出力するように設定する]] * Electric Fenceのインストール [#b4ede7fe] Electric Fenceは以下のパッケージになります。 -x86_64版 ElectricFence.x86_64 : メモリ割り当ての侵略を検出するデバッガ -i386版 ElectricFence.i386 : メモリ割り当ての侵略を検出するデバッガ ともに以下のコマンドでインストールすることができます。~ rootユーザでインストールしてください。 yum -y install ElectricFence * Electric Fenceを使ってみる [#dbb77ba5] 早速、Electric Fenceを使ってみます。 ** Electric Fenceの使う順序 [#s62cbc87] 以下の手順でElectric Fenceを使うことができます。 + デバッグするプログラムを準備 + Electric Fenceように環境変数を設定(検出項目の設定) + 環境変数LD_PRELOADにlibefence.soを設定 + デバッグプログラムの実行 ** バッファーオーバーフローを試す [#tee8ceef] 使用したバッファーオーバーフローのCソースは以下の通りです。 #ref(over.c) #include <stdio.h> #include <stdlib.h> int main(void) { char *c; c = malloc(4); c[4] = 0; free(c); exit(0); } 上記のプログラムはバッファーオーバーフローしていますが、実行するとなにもエラーなく終了してしまいます。 Electric Fenceを使って実行してみます。 + プログラムを準備(gccでコンパイルし実行ファイルoverを出力します) $ gcc -g -O0 over.c -o over + オーバーフロー(オーバーラン)を調べる環境変数EF_PROTECT_BELOWに0を設定 $ export EF_PROTECT_BELOW=0 + EF_ALIGNMENTに0を設定 $ export EF_ALIGNMENT=0 + libefence.soを環境変数LD_PRELOADに設定 --x86_64 $ export LD_PRELOAD=/usr/lib64/libefence.so --i386 $ export LD_PRELOAD=/usr/lib/libefence.so + プログラムを実行 $ ./over Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com> セグメンテーション違反です (core dumped) 上記のようにElectric Fenceを使うとセグメンテーション違反が発生します。~ 出力されたcore dumpをgdbで調べるとバッファーオーバーフローしている場所でSegmentation faultしているのが確認できます。~ (Electric Fenceを使用した状態でgdbを使うとセグメンテーション違反が発生したので、以下の手順で確認しました。) $ unset LD_PRELOAD $ gdb -c core.5705 over GNU gdb (GDB) CentOS (7.0.1-42.el5.centos.1) Copyright (C) 2009 Free Software Foundation, Inc. <snip> warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7fff9b54f000 Core was generated by `./over'. Program terminated with signal 11, Segmentation fault. #0 0x0000000000400546 in main () at over.c:8 8 c[4] = 0; ** バッファーアンダーフローを試す [#z924d78d] アンダーフローも上記のオーバーフロート同様の手順ですが、EF_PROTECT_BELOWが異なります。 使用したバッファーアンダーフローのCソースは以下の通りです。 #ref(under.c) #include <stdio.h> #include <stdlib.h> int main(void) { char *c; c = malloc(4); c[-1] = 0; free(c); exit(0); } 上記のプログラムはバッファーアンダーフローしていますが、実行するとなにもエラーなく終了してしまいます。 Electric Fenceを使って実行してみます。 + プログラムを準備(gccでコンパイルし実行ファイルunderを出力します) $ gcc -g -O0 under.c -o under + アンダーフロー(アンダーラン)を調べる環境変数EF_PROTECT_BELOWに1を設定 $ export EF_PROTECT_BELOW=1 + libefence.soを環境変数LD_PRELOADに設定 --x86_64 $ export LD_PRELOAD=/usr/lib64/libefence.so --i386 $ export LD_PRELOAD=/usr/lib/libefence.so + プログラムを実行 $ ./under Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com> セグメンテーション違反です (core dumped) 上記のようにElectric Fenceを使うとセグメンテーション違反が発生します。~ 出力されたcore dumpをgdbで調べるとバッファーアンダーフローしている場所でSegmentation faultしているのが確認できます。~ (Electric Fenceを使用した状態でgdbを使うとセグメンテーション違反が発生したので、以下の手順で確認しました。) $ unset LD_PRELOAD $ gdb -c core.5757 under GNU gdb (GDB) CentOS (7.0.1-42.el5.centos.1) Copyright (C) 2009 Free Software Foundation, Inc. <snip> warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7fffabffd000 Core was generated by `./under'. Program terminated with signal 11, Segmentation fault. #0 0x0000000000400546 in main () at under.c:8 8 c[-1] = 0; ** サイズ0のmallocを検出する [#gc67e5d9] サイズ0をmallocをするサンプルソースを準備しました。 #ref(zero.c) #include <stdio.h> #include <stdlib.h> int main(void) { char *c; c = malloc(0); free(c); exit(0); } + プログラムを準備(gccでコンパイルし実行ファイルzeroを出力します) $ gcc -g -O0 zero.c -o zero + libefence.soを環境変数LD_PRELOADに設定 --x86_64 $ export LD_PRELOAD=/usr/lib64/libefence.so --i386 $ export LD_PRELOAD=/usr/lib/libefence.so + プログラムを実行 $ ./zero Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com> ElectricFence Aborting: Allocating 0 bytes, probably a bug. 不正な命令です (core dumped) 上記のようにElectric Fenceを使うと「不正な命令です (core dumped)」が発生します。~ 出力されたcore dumpをgdbで調べるとバッファーアンダーフローしている場所が確認できます。~ (Electric Fenceを使用した状態でgdbを使うとセグメンテーション違反が発生したので、以下の手順で確認しました。) $ unset LD_PRELOAD $ gdb -c core.5845 zero GNU gdb (GDB) CentOS (7.0.1-42.el5.centos.1) Copyright (C) 2009 Free Software Foundation, Inc. <snip> warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7fff8e8a7000 Core was generated by `./zero'. Program terminated with signal 4, Illegal instruction. #0 0x0000003dbd630717 in kill () from /lib64/libc.so.6 (gdb) bt #0 0x0000003dbd630717 in kill () from /lib64/libc.so.6 #1 0x00002b16158e7005 in ?? () from /usr/lib64/libefence.so #2 0x00002b16158e755d in EF_Abort () from /usr/lib64/libefence.so #3 0x00002b16158e6bfe in memalign () from /usr/lib64/libefence.so #4 0x000000000040053a in main () at zero.c:7 bt(バックトレース)コマンドを実行するとzero.cの7行目(c = malloc(0);)が原因なのが確認できます。 サイズ0のチェックを行わない場合は、以環境変数EF_ALLOW_MALLOC_0に1を設定してください。 $ export EF_ALLOW_MALLOC_0=1 * その他環境変数 [#rc7beca9] Electric Fenceの環境変数に関しては、manコマンドで調べることができます。 man libefence #htmlinsertpcsp(c-btm.html,c-sp.html)