現状考えうる最良のext3ファイル復元ツールを実装した

ext3ファイルシステムの復元の代表的なツールとしてextundeleteがあります。

しかし、extundeleteは「ext3ファイルシステムとファイルの削除・復元について」のエントリにおける正確なファイルの紐付けやその検知ができていません。extundeleteで復元してしまうと、「ext3ファイルシステムとファイルの削除・復元について」で述べた通り、復元対象ファイルのinodeが以前にも違うファイルで使われていて、そのinodeの以前の情報がディレクトリエントリから抽出できてしまった場合、先に見つかったファイル名でinodeの指し示すデータブロックを復元してしまいます。そのため、意図していないファイル名とデータブロックのファイルが復元される可能性があります。

そこで、そういった問題を解決した現状考えうる最良の復元ツールをextundeleteをベースに実装してみました。やっぱり理論だけでは面白くないなぁと思ったのです。コードはGitHubに置いているので自己責任で試してみて下さい。ext4もできるんじゃないかなぁと思っていますが試していません。機能としては、以下になります。

  • ファイル復元
  • 復元の際はディレクトリエントリ上でinodeの重複をチェック
  • 重複していた場合は、inodeから得られる複数のファイル名でファイルを復元
  • 重複していたファイルとinodeの組み合わせをリストで生成

使い方

まずは、GitHubのコードをビルドします。

[program lang=’bash’ escaped=’true’]

git clone https://github.com/matsumoto-r/ext3_salvage_tool.git
cd ext3_salvage_tool
cd tools
yum -y install e2fsprogs-devel
aclocal
automake
autoconf
./configure --prefix=`pwd`
make
make install

[/program]

次に、「削除されたファイルがどの時点以降のものなのかを時間で指定」「復元対象のディレクトリ」「復元対象のデバイス」を指定します。

[program lang=’bash’ escaped=’true’]

vi salvage_data.pl

[/program]

[program lang=’perl’ escaped=’true’]

# salvage parameter
# 2013/7/09 12:00 == 1373338800
# $salvage_after: only process entries deleted on or after 'dtime'.
# $salvage_dir:   target directory for undelete
# $salvage_dev:   target device-file
my $salvage_after   = '1373338800';
my $salvage_dir     = '/tmp';
my $salvage_dev     = '/dev/sdb1';

[/program]

例えば、僕のサーバにはディスクが2つ積んであるので、その片方で復元できるか試してみます。

まず、以下のように/mntにマウントされている/dev/sdb1の/tmpにファイルを作成・修正・削除を行います。

[program lang=’bash’ escaped=’true’]

touch hoge

ls -li hoge
136303 -rw-r--r-- 1 root root 9  7月 10 01:40 hoge

echo hoge > hoge
rm hoge

[/program]

上記のように一応inodeをチェックしておきましょう。

そして、以下のように一応syncしてからRead Onlyマウントして復元を試みます。

[program lang=’bash’ escaped=’true’]

sync
mount -o remount,ro /dev/sdb1

./salvage_data.pl
INFO    : output=(main salvage_data.pl(0.01) start)
INFO    : output=(main salvage_data.pl locked)
INFO    : output=(main salvage start)
INFO    : output=(main prepared recovered directory start)
INFO    : output=(main create duplicate log start)
INFO    : output=(main create duplicate inode list start)
INFO    : output=(main create suspect list start)
INFO    : output=(main create client data start)
INFO    : output=(main clean up recovered files start)
INFO    : output=(main salvage_data.pl(0.01) end)

[/program]

すると復元が終わって、カレントディレクトリの「SALVAGED_DATA/RECOVERED_FILES」以下にファイルがフルパスで復元されており、「SALVAGED_DATA/SUSPECT_LIST.txt」には、所謂あやしいリストとして、inodeが重複しているディレクトリエントリが2個以上あった場合は、それをリスト化しています。復元ファイルには、重複しているinodeとファイル名の組み合わせは一応重複している分だけ復元しています。

[program lang=’bash’ escaped=’true’]

cd SALVAGED_DATA/
ls -l
合計 16
drwxr-xr-x 3 root root 4096  7月 10 01:43 ./
drwxr-xr-x 6 root root 4096  7月 10 01:43 ../
drwxr-xr-x 3 root root 4096  7月 10 01:43 RECOVERED_FILES/
-rw-r--r-- 1 root root  124  7月 10 01:43 SUSPECT_LIST.txt

cat SUSPECT_LIST.txt
136303 5 tmp/hoge
136303 5 tmp/qos-control.pl.log
132876 4096 tmp/.hoge.swp
132876 4096 tmp/iotop_for_virtuozzo.pl-root.log

ls -laR RECOVERED_FILES/
RECOVERED_FILES/:
合計 4
drwxr-xr-x 2 root root 4096  7月 10 01:43 tmp

RECOVERED_FILES/tmp:
合計 556432
-rw-r--r-- 1 root root      4096  7月 10 01:43 .hoge.swp
-rw-r--r-- 1 root root         5  7月 10 01:43 hoge
-rw-r--r-- 1 root root      4096  7月 10 01:43 iotop_for_virtuozzo.pl-root.log
-rw-r--r-- 1 root root    274022  7月 10 01:43 mod_request_dumper.log
-rw-r--r-- 1 root root         5  7月 10 01:43 qos-control.pl.log

[/program]

上記の結果の場合は、「tmp/hoge」と「tmp/qos-control.pl.log」というファイルが、別の時点で同じinode136303で使われていたため、それを検出しています。また「tmp/.hoge.swp」と「tmp/iotop_for_virtuozzo.pl-root.log」というファイルも同様です。

ですので、「ファイル名」と「inode」の組み合わせで正しく検出できたのは、「mod_request_dumper.log」ということになりますね。

また、「tmp/hoge」と「tmp/qos-control.pl.log」の中身をみるとテキストで「hoge」となっているので、実験で作成・修正・削除したファイルである事は予想がつきます。中身を主導で判定する事ができない場合は、重複しているファイルは不完全なものとして、復元対象に入れないという手もあるかもしれません。

最後に

以上のように、extundeleteでは考慮されていなかったinodeとファイル名の組み合わせの重複による誤ったファイル復元を検出して復元できるようにしました。

現状では、公開されているもの中では、これよりきちんと復元できているツールはないんじゃないでしょうか。

ファイル復元で困っている人は、一度試してみると良いかもしれません。