このエントリーをはてなブックマークに追加


メモリリークなどを探すツール・Electric Fenceを使ってみる

mallocのフリー忘れやサイズ0のメモリアロケートなどを検出してくれるElectric Fenceを使ってみました。
以下にElectric Fenceの使用例を記します。

使用したOSはCentOS5のx86_64になります。


スポンサーリンク

関連資料・関連記事

Electric Fenceのインストール

Electric Fenceは以下のパッケージになります。

  • x86_64版
    ElectricFence.x86_64 : メモリ割り当ての侵略を検出するデバッガ
  • i386版
    ElectricFence.i386 : メモリ割り当ての侵略を検出するデバッガ

ともに以下のコマンドでインストールすることができます。
rootユーザでインストールしてください。

yum -y install ElectricFence

Electric Fenceを使ってみる

早速、Electric Fenceを使ってみます。

Electric Fenceの使う順序

以下の手順でElectric Fenceを使うことができます。

  1. デバッグするプログラムを準備
  2. Electric Fenceように環境変数を設定(検出項目の設定)
  3. 環境変数LD_PRELOADにlibefence.soを設定
  4. デバッグプログラムの実行

バッファーオーバーフローを試す

使用したバッファーオーバーフローのCソースは以下の通りです。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  char *c;
  c = malloc(4);
  c[4] = 0;
  free(c);
  exit(0);
}

上記のプログラムはバッファーオーバーフローしていますが、実行するとなにもエラーなく終了してしまいます。

Electric Fenceを使って実行してみます。

  1. プログラムを準備(gccでコンパイルし実行ファイルoverを出力します)
    $ gcc -g -O0 over.c -o over
  2. オーバーフロー(オーバーラン)を調べる環境変数EF_PROTECT_BELOWに0を設定
    $ export EF_PROTECT_BELOW=0
  3. EF_ALIGNMENTに0を設定
    $ export EF_ALIGNMENT=0
  4. libefence.soを環境変数LD_PRELOADに設定
    • x86_64
      $ export LD_PRELOAD=/usr/lib64/libefence.so
    • i386
      $ export LD_PRELOAD=/usr/lib/libefence.so
  5. プログラムを実行
    $ ./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;

バッファーアンダーフローを試す

アンダーフローも上記のオーバーフロート同様の手順ですが、EF_PROTECT_BELOWが異なります。

使用したバッファーアンダーフローのCソースは以下の通りです。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  char *c;
  c = malloc(4);
  c[-1] = 0;
  free(c);
  exit(0);
}

上記のプログラムはバッファーアンダーフローしていますが、実行するとなにもエラーなく終了してしまいます。

Electric Fenceを使って実行してみます。

  1. プログラムを準備(gccでコンパイルし実行ファイルunderを出力します)
    $ gcc -g -O0 under.c -o under
  2. アンダーフロー(アンダーラン)を調べる環境変数EF_PROTECT_BELOWに1を設定
    $ export EF_PROTECT_BELOW=1
  3. libefence.soを環境変数LD_PRELOADに設定
    • x86_64
      $ export LD_PRELOAD=/usr/lib64/libefence.so
    • i386
      $ export LD_PRELOAD=/usr/lib/libefence.so
  4. プログラムを実行
    $ ./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を検出する

サイズ0をmallocをするサンプルソースを準備しました。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  char *c;
  c = malloc(0);
  free(c);
  exit(0);
}
  1. プログラムを準備(gccでコンパイルし実行ファイルzeroを出力します)
    $ gcc -g -O0 zero.c -o zero
  2. libefence.soを環境変数LD_PRELOADに設定
    • x86_64
      $ export LD_PRELOAD=/usr/lib64/libefence.so
    • i386
      $ export LD_PRELOAD=/usr/lib/libefence.so
  3. プログラムを実行
    $ ./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

その他環境変数

Electric Fenceの環境変数に関しては、manコマンドで調べることができます。

man libefence

スポンサーリンク

添付ファイル: fileover.c 642件 [詳細] fileunder.c 640件 [詳細] filezero.c 639件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-03-20 (金) 21:01:00