为什么dd命令可以恢复使用shred删除的文件?

为什么dd命令可以恢复使用shred删除的文件?

我使用 找到了文件的索引节点ls -li。然后我在磁盘上找到了文件的起始块。我使用该命令将该块的内容复制到另一个目录dd。然后我使用实用程序粉碎了该文件shredshred -uvz -n=10 file1.txt。我dd再次运行相同的命令。文件已恢复。文件被粉碎后我应该得到 00000 。我缺少什么?

在第二次迭代中,我shred -vz -n=10 file2.txt改为运行,这不会删除文件。按照与之前相同的步骤,我再次能够使用命令dd和块位置恢复原始文件。然而,粉碎文件的内容为 00000,如 所示hexdump file2.txt。我缺少什么?

答案1

文件系统应该具有对其块设备的独占访问权。dd在安装文件系统时,您不应该直接在块设备上使用。

当您使用dd(或任何其他用户空间程序)直接从块设备读取字节时,该读取会被缓存。如果再次重复dd,它将从缓存中读取数据。

不幸的是,写入数据(通过文件系统)不会更新此缓存。因此,您会遇到缓存中的数据不反映磁盘上的数据的情况。

发生这种情况的另一个例子是 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仅从缓存中删除数据从缓存中读取它,因此必须执行两次才能看到新数据。或者,您可以使用sync; echo 3 > /proc/sys/vm/drop_caches删除所有缓存或使用直接 I/O 碰碰运气。

相关内容