ddコマンドがshredを使用して削除されたファイルを回復できるのはなぜですか?

ddコマンドがshredを使用して削除されたファイルを回復できるのはなぜですか?

を使用してファイルのinodeを見つけましたls -li。その後、ディスク上のファイルの開始ブロックを見つけました。私はこのコマンドを使ってブロックの内容を別のディレクトリにコピーしますdd。その後、ユーティリティを使用してファイルを破砕しましたshred。同じコマンドを再実行してくださいshred -uvz -n=10 file1.txtddファイルが復元されました。ファイルが破砕されたら、00000を取得する必要があります。私は何を見逃していますか?

2回目の繰り返しでは、shred -vz -n=10 file2.txtファイルを削除せずに実行します。以前と同じ手順で、ddコマンドとブロックの場所を使用して元のファイルを復元することができました。ただし、破砕されたファイルの内容は、同様に00000ですhexdump file2.txt。私は何を見逃していますか?

答え1

ファイルシステムはそのブロックデバイスに排他的にアクセスできる必要があります。ddファイルシステムをマウントするときは、ブロックデバイスで直接作業しないでください。

dd(または他のユーザ空間プログラム)を使用してブロックデバイスから直接バイトを読み出すと、読み出しはキャッシュされます。もう一度繰り返すと、ddキャッシュからデータを読み込みます。

残念ながら、(ファイルシステムを介して)データ書き込みはこのキャッシュを更新しません。したがって、キャッシュ内のデータがディスク上のデータを反映しない状況が発生する可能性があります。

これが起こるもう1つの例はTRIMです。ブロックデバイスデータがキャッシュされている場合、TRIMがそのデータを削除してもキャッシュからデータを引き続き取得できます。だからこそTRIMテスト時にキャッシュを削除する必要があります。

いくつかのファイルでファイルシステムを作成します。

# truncate -s 10G filesystem.img
# mkfs.ext4 filesystem.img
# losetup --find --show filesystem.img
/dev/loop1
# mount /dev/loop1 loop/
# for n in {000..100} ; do yes $n | dd bs=1M count=1 iflag=fullblock of=loop/$n; done 2> /dev/null
# sync

ファイルの内容と物理オフセットを確認してください。

# hexdump -C loop/042
00000000  30 34 32 0a 30 34 32 0a  30 34 32 0a 30 34 32 0a  |042.042.042.042.|
*
00100000
# filefrag -ve loop/042
Filesystem type is: ef53
File size of loop/042 is 1048576 (256 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..     255:      44800..     45055:    256:             last,eof
loop/042: 1 extent found

ブロックデバイスから読む:

# dd bs=4096 skip=44800 count=256 if=/dev/loop1 | hexdump -C
00000000  30 34 32 0a 30 34 32 0a  30 34 32 0a 30 34 32 0a  |042.042.042.042.|
*
00100000

彫刻:

# shred -v -n 1 loop/042
shred: loop/042: pass 1/1 (random)...

ブロックデバイス(キャッシュ)から読み取る:

# dd bs=4096 skip=44800 count=256 if=/dev/loop1 | hexdump -C
00000000  30 34 32 0a 30 34 32 0a  30 34 32 0a 30 34 32 0a  |042.042.042.042.|
*
00100000

ブロックデバイスから読み込む()iflag=nocache

# dd bs=4096 skip=44800 count=256 if=/dev/loop1 iflag=nocache | hexdump -C
00000000  30 34 32 0a 30 34 32 0a  30 34 32 0a 30 34 32 0a  |042.042.042.042.|
*
00100000
# dd bs=4096 skip=44800 count=256 if=/dev/loop1 iflag=nocache | hexdump -C | head
00000000  59 c2 d8 d4 5a 02 35 15  a1 fb f1 07 ae 53 59 99  |Y...Z.5......SY.|
00000010  5b 47 4f fc 2c e7 d3 db  10 70 c6 72 3e 6f 0b 05  |[GO.,....p.r>o..|
00000020  f5 07 c6 f7 95 64 8b a2  4e 7f 32 4f 0c b1 a3 32  |.....d..N.2O...2|
00000030  18 b5 99 7d 7d 6e 6d d6  b9 36 77 af 30 02 ba 23  |...}}nm..6w.0..#|
00000040  f5 55 a5 b7 01 51 cd 5b  64 c9 29 1f f6 48 23 6c  |.U...Q.[d.)..H#l|

dd iflag=nocacheキャッシュからのみデータを削除する後ろにキャッシュから読み取られるため、新しいデータを表示するには2回行う必要があります。あるいは、sync; echo 3 > /proc/sys/vm/drop_cachesすべてのキャッシュを消去したり、直接I / Oを使用して運を試したりすることもできます。

関連情報