btrfs-progs: tests: add crafted and fuzzed images
authorDavid Sterba <dsterba@suse.com>
Wed, 9 Sep 2015 15:04:12 +0000 (17:04 +0200)
committerDavid Sterba <dsterba@suse.com>
Wed, 9 Sep 2015 15:09:01 +0000 (17:09 +0200)
A collection of several images that were produced in a non-standard way
and cause various errors in check or image tools. They do not fit into
the fsck tests as we're not able to repair any of them, but the tools
should not crash or do out-of-bounds access.

Signed-off-by: David Sterba <dsterba@suse.com>
12 files changed:
tests/fuzz-tests/images/bad-superblock-1.raw.xz [new file with mode: 0644]
tests/fuzz-tests/images/bad-superblock-2.raw.xz [new file with mode: 0644]
tests/fuzz-tests/images/bad-superblock-3.raw.xz [new file with mode: 0644]
tests/fuzz-tests/images/bad-superblock.txt [new file with mode: 0644]
tests/fuzz-tests/images/bko-104131-fsck-oob-read.raw.xz [new file with mode: 0644]
tests/fuzz-tests/images/bko-104131-fsck-oob-read.txt [new file with mode: 0644]
tests/fuzz-tests/images/bko-104141-fsck-exception.raw.xz [new file with mode: 0644]
tests/fuzz-tests/images/bko-104141-fsck-exception.txt [new file with mode: 0644]
tests/fuzz-tests/images/bko-97191-btrfs-image.raw.txt [new file with mode: 0644]
tests/fuzz-tests/images/bko-97191-btrfs-image.raw.xz [new file with mode: 0644]
tests/fuzz-tests/images/bko-97271-btrfs-image.raw.txt [new file with mode: 0644]
tests/fuzz-tests/images/bko-97271-btrfs-image.raw.xz [new file with mode: 0644]

diff --git a/tests/fuzz-tests/images/bad-superblock-1.raw.xz b/tests/fuzz-tests/images/bad-superblock-1.raw.xz
new file mode 100644 (file)
index 0000000..3d6358f
Binary files /dev/null and b/tests/fuzz-tests/images/bad-superblock-1.raw.xz differ
diff --git a/tests/fuzz-tests/images/bad-superblock-2.raw.xz b/tests/fuzz-tests/images/bad-superblock-2.raw.xz
new file mode 100644 (file)
index 0000000..7db7610
Binary files /dev/null and b/tests/fuzz-tests/images/bad-superblock-2.raw.xz differ
diff --git a/tests/fuzz-tests/images/bad-superblock-3.raw.xz b/tests/fuzz-tests/images/bad-superblock-3.raw.xz
new file mode 100644 (file)
index 0000000..4aa3148
Binary files /dev/null and b/tests/fuzz-tests/images/bad-superblock-3.raw.xz differ
diff --git a/tests/fuzz-tests/images/bad-superblock.txt b/tests/fuzz-tests/images/bad-superblock.txt
new file mode 100644 (file)
index 0000000..f7dd9aa
--- /dev/null
@@ -0,0 +1,17 @@
+bad-superblock-*.txt
+
+Crafted images from Jiri Slaby, produced by some symbolic execution framework
+that finds unhandled cases at mount time.
+
+Relevant kernel patches to backport:
+
+e3540eab29e1b2260bc4b9b3979a49a00e3e3af8
+btrfs: add more checks to btrfs_read_sys_array
+
+ce7fca5f57ed0fcd7e7b3d7b1a3e1791f8e56fa3
+btrfs: add checks for sys_chunk_array sizes
+
+75d6ad382bb91f363452119d34238e156589ca2d
+btrfs: more superblock checks, lower bounds on devices and sectorsize/nodesize
+
+(and more from fs/btrfs/super.c)
diff --git a/tests/fuzz-tests/images/bko-104131-fsck-oob-read.raw.xz b/tests/fuzz-tests/images/bko-104131-fsck-oob-read.raw.xz
new file mode 100644 (file)
index 0000000..7848f8b
Binary files /dev/null and b/tests/fuzz-tests/images/bko-104131-fsck-oob-read.raw.xz differ
diff --git a/tests/fuzz-tests/images/bko-104131-fsck-oob-read.txt b/tests/fuzz-tests/images/bko-104131-fsck-oob-read.txt
new file mode 100644 (file)
index 0000000..0e829c2
--- /dev/null
@@ -0,0 +1,31 @@
+URL: https://bugzilla.kernel.org/show_bug.cgi?id=104131
+Hanno Boeck 2015-09-07 07:24:32 UTC
+
+Created attachment 186941 [details]
+malformed btrfs filesystem causing oob read
+
+The attached malformed filesystem image will cause an invalid heap out of bounds memory read in btrfsck.
+
+This was found while fuzzing btrfs-progs with american fuzzy lop.
+
+Stack trace from Address Sanitizer:
+==31289==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60f00000f003 at pc 0x0000005d0dbb bp 0x7ffdf444c180 sp 0x7ffdf444c178
+READ of size 8 at 0x60f00000f003 thread T0
+    #0 0x5d0dba in btrfs_header_bytenr /mnt/ram/btrfs-progs-v4.1.2/./ctree.h:1797:1
+    #1 0x5d0dba in check_tree_block /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:60
+    #2 0x5d0dba in read_tree_block /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:337
+    #3 0x5dc00e in btrfs_setup_chunk_tree_and_device_map /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:1169:30
+    #4 0x5dcf89 in __open_ctree_fd /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:1261:8
+    #5 0x5dc50a in open_ctree_fs_info /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:1302:9
+    #6 0x52f22f in cmd_check /mnt/ram/btrfs-progs-v4.1.2/cmds-check.c:9333:9
+    #7 0x4e7bcc in main /mnt/ram/btrfs-progs-v4.1.2/btrfs.c:245:7
+    #8 0x7f98bb101f9f in __libc_start_main /var/tmp/portage/sys-libs/glibc-2.20-r2/work/glibc-2.20/csu/libc-start.c:289
+    #9 0x41f748 in _start (/mnt/ram/btrfs/btrfs+0x41f748)
+
+0x60f00000f003 is located 3 bytes to the right of 176-byte region [0x60f00000ef50,0x60f00000f000)
+allocated by thread T0 here:
+    #0 0x4bade8 in malloc (/mnt/ram/btrfs/btrfs+0x4bade8)
+    #1 0x622c24 in __alloc_extent_buffer /mnt/ram/btrfs-progs-v4.1.2/extent_io.c:541:7
+    #2 0x622c24 in alloc_extent_buffer /mnt/ram/btrfs-progs-v4.1.2/extent_io.c:648
+    #3 0x5cf436 in btrfs_find_create_tree_block /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:186:9
+    #4 0x5cf436 in read_tree_block /mnt/ram/btrfs-progs-v4.1.2/disk-io.c:314
diff --git a/tests/fuzz-tests/images/bko-104141-fsck-exception.raw.xz b/tests/fuzz-tests/images/bko-104141-fsck-exception.raw.xz
new file mode 100644 (file)
index 0000000..d24a32f
Binary files /dev/null and b/tests/fuzz-tests/images/bko-104141-fsck-exception.raw.xz differ
diff --git a/tests/fuzz-tests/images/bko-104141-fsck-exception.txt b/tests/fuzz-tests/images/bko-104141-fsck-exception.txt
new file mode 100644 (file)
index 0000000..aed9190
--- /dev/null
@@ -0,0 +1,9 @@
+URL: https://bugzilla.kernel.org/show_bug.cgi?id=104141
+Hanno Boeck 2015-09-07 07:27:58 UTC
+
+Created attachment 186951 [details]
+malformed filesystem causing floating point exception
+
+The attacked file will cause a floating point exception in btrfsck.
+
+This was found while fuzzing btrfs-progs with american fuzzy lop.
diff --git a/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.txt b/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.txt
new file mode 100644 (file)
index 0000000..f0d8189
--- /dev/null
@@ -0,0 +1,137 @@
+URL: https://bugzilla.kernel.org/show_bug.cgi?id=97191
+Lukas Lueg 2015-04-23 22:20:35 UTC
+
+Running btrfs-progs v3.19.1
+
+The btrfs-image attached to this bug causes the btrfs-userland tool to
+overflow some data structures, leading to unallocated memory being written to
+and read from. A segfault results shortly after. Reproduced on x86-64 and
+i686.
+
+The kernel seems to be less affected and fails to mount the image. I didn't
+investigate whether the reads/writes could be used to gain control over $EIP.
+Since the first invalid write of 8 bytes seems to run into adjacent heap
+blocks (crash in unlink()), it may be possible though.
+
+gdb output:
+
+Program received signal SIGSEGV, Segmentation fault.
+malloc_consolidate (av=av@entry=0x32629b7cc0 <main_arena>) at malloc.c:4151
+4151               unlink(av, p, bck, fwd);
+(gdb) bt
+#0  malloc_consolidate (av=av@entry=0x32629b7cc0 <main_arena>) at malloc.c:4151
+#1  0x0000003262680628 in _int_malloc (av=av@entry=0x32629b7cc0 <main_arena>, bytes=bytes@entry=4224) at malloc.c:3420
+#2  0x000000326268315e in __GI___libc_malloc (bytes=4224) at malloc.c:2896
+#3  0x0000000000449d15 in __alloc_extent_buffer (tree=0x88c078, bytenr=4288512, blocksize=4096) at extent_io.c:541
+#4  0x000000000044a8b4 in alloc_extent_buffer (tree=0x88c078, bytenr=4288512, blocksize=4096) at extent_io.c:648
+#5  0x000000000043b1a0 in btrfs_find_create_tree_block (root=root@entry=0x895840, bytenr=<optimized out>, 
+    blocksize=<optimized out>) at disk-io.c:159
+#6  0x000000000043ca4e in read_tree_block (root=root@entry=0x895840, bytenr=<optimized out>, blocksize=<optimized out>, 
+    parent_transid=13) at disk-io.c:287
+#7  0x000000000043ccb7 in find_and_setup_root (tree_root=0x88c250, fs_info=<optimized out>, objectid=5, root=0x895840)
+    at disk-io.c:557
+#8  0x000000000043ce92 in btrfs_read_fs_root_no_cache (fs_info=fs_info@entry=0x88c010, location=location@entry=0x7fffffffd960)
+    at disk-io.c:640
+#9  0x000000000043d060 in btrfs_read_fs_root (fs_info=fs_info@entry=0x88c010, location=location@entry=0x7fffffffd960)
+    at disk-io.c:739
+#10 0x000000000043d48c in btrfs_setup_all_roots (fs_info=fs_info@entry=0x88c010, root_tree_bytenr=<optimized out>, 
+    root_tree_bytenr@entry=0, flags=flags@entry=OPEN_CTREE_EXCLUSIVE) at disk-io.c:988
+#11 0x000000000043d802 in __open_ctree_fd (fp=fp@entry=3, path=path@entry=0x7fffffffe20d "ramdisk/btrfs_fukked.bin", 
+    sb_bytenr=65536, sb_bytenr@entry=0, root_tree_bytenr=root_tree_bytenr@entry=0, flags=flags@entry=OPEN_CTREE_EXCLUSIVE)
+    at disk-io.c:1199
+#12 0x000000000043d965 in open_ctree_fs_info (filename=0x7fffffffe20d "ramdisk/btrfs_fukked.bin", sb_bytenr=sb_bytenr@entry=0, 
+    root_tree_bytenr=root_tree_bytenr@entry=0, flags=flags@entry=OPEN_CTREE_EXCLUSIVE) at disk-io.c:1231
+#13 0x0000000000427bf5 in cmd_check (argc=1, argv=0x7fffffffdea0) at cmds-check.c:9326
+#14 0x000000000040e5a2 in main (argc=2, argv=0x7fffffffdea0) at btrfs.c:245
+
+
+valgrind output:
+
+==32463== Memcheck, a memory error detector
+==32463== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
+==32463== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
+==32463== Command: btrfs check ramdisk/btrfs_fukked.bin
+==32463== 
+==32463== Invalid write of size 8
+==32463==    at 0x4386FB: btrfs_search_slot (ctree.c:1119)
+==32463==    by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463==    by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463==    by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463==    by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463==    by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463==    by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463==    by 0x40E5A1: main (btrfs.c:245)
+==32463==  Address 0x4c409f0 is 16 bytes after a block of size 144 alloc'd
+==32463==    at 0x4A08946: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==32463==    by 0x4427AB: btrfs_read_block_groups (extent-tree.c:3162)
+==32463==    by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463==    by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463==    by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463==    by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463==    by 0x40E5A1: main (btrfs.c:245)
+==32463== 
+==32463== Invalid read of size 8
+==32463==    at 0x436E70: check_block.part.14 (ctree.c:548)
+==32463==    by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==32463==    by 0x438954: btrfs_search_slot (ctree.c:1120)
+==32463==    by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463==    by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463==    by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463==    by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463==    by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463==    by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463==    by 0x40E5A1: main (btrfs.c:245)
+==32463==  Address 0x4c409f8 is 24 bytes after a block of size 144 in arena "client"
+==32463== 
+==32463== Invalid read of size 4
+==32463==    at 0x436E84: UnknownInlinedFun (ctree.h:1605)
+==32463==    by 0x436E84: UnknownInlinedFun (ctree.h:1612)
+==32463==    by 0x436E84: check_block.part.14 (ctree.c:550)
+==32463==    by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==32463==    by 0x438954: btrfs_search_slot (ctree.c:1120)
+==32463==    by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463==    by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463==    by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463==    by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463==    by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463==    by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463==    by 0x40E5A1: main (btrfs.c:245)
+==32463==  Address 0x4c409e4 is 4 bytes after a block of size 144 alloc'd
+==32463==    at 0x4A08946: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==32463==    by 0x4427AB: btrfs_read_block_groups (extent-tree.c:3162)
+==32463==    by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463==    by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463==    by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463==    by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463==    by 0x40E5A1: main (btrfs.c:245)
+==32463== 
+==32463== Invalid read of size 1
+==32463==    at 0x4A0B3A0: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==32463==    by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==32463==    by 0x436E99: check_block.part.14 (ctree.c:550)
+==32463==    by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==32463==    by 0x438954: btrfs_search_slot (ctree.c:1120)
+==32463==    by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463==    by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463==    by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463==    by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463==    by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463==    by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463==    by 0x40E5A1: main (btrfs.c:245)
+==32463==  Address 0x1b1 is not stack'd, malloc'd or (recently) free'd
+==32463== 
+==32463== 
+==32463== Process terminating with default action of signal 11 (SIGSEGV)
+==32463==  Access not within mapped region at address 0x1B1
+==32463==    at 0x4A0B3A0: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==32463==    by 0x436E99: UnknownInlinedFun (ctree.h:1613)
+==32463==    by 0x436E99: check_block.part.14 (ctree.c:550)
+==32463==    by 0x438954: UnknownInlinedFun (kerncompat.h:91)
+==32463==    by 0x438954: btrfs_search_slot (ctree.c:1120)
+==32463==    by 0x4427F7: UnknownInlinedFun (extent-tree.c:3117)
+==32463==    by 0x4427F7: btrfs_read_block_groups (extent-tree.c:3167)
+==32463==    by 0x43D4F2: btrfs_setup_all_roots (disk-io.c:983)
+==32463==    by 0x43D801: __open_ctree_fd (disk-io.c:1199)
+==32463==    by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==32463==    by 0x427BF4: cmd_check (cmds-check.c:9326)
+==32463==    by 0x40E5A1: main (btrfs.c:245)
diff --git a/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.xz b/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.xz
new file mode 100644 (file)
index 0000000..b2e48c0
Binary files /dev/null and b/tests/fuzz-tests/images/bko-97191-btrfs-image.raw.xz differ
diff --git a/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.txt b/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.txt
new file mode 100644 (file)
index 0000000..67f2096
--- /dev/null
@@ -0,0 +1,54 @@
+URL: https://bugzilla.kernel.org/show_bug.cgi?id=97271
+Lukas Lueg 2015-04-25 20:34:39 UTC
+
+The attached btrfs-image causes "btrfs check" to write outside of allocated
+memory locations and ultimately die due to a segfault. An adjacent heap block's
+control structure is overwritten with a `struct extent_buffer *`, which is not
+controllable by the user.
+
+"btrfs version" is v3.19.1. Running "btrfs check" immediately dies with
+
+*** Error in `btrfs': double free or corruption (!prev): 0x0000000002396ec0 ***
+*** Error in `btrfs': malloc(): memory corruption: 0x0000000002396f60 ***
+
+Debugging with valgrind and gdb gives
+
+==11670== Invalid write of size 8
+==11670==    at 0x4386FB: btrfs_search_slot (ctree.c:1119)
+==11670==    by 0x44E16E: btrfs_read_chunk_tree (volumes.c:1814)
+==11670==    by 0x43D654: btrfs_setup_chunk_tree_and_device_map (disk-io.c:1115)
+==11670==    by 0x43D7D0: __open_ctree_fd (disk-io.c:1190)
+==11670==    by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==11670==    by 0x427BF4: cmd_check (cmds-check.c:9326)
+==11670==    by 0x40E5A1: main (btrfs.c:245)
+==11670==  Address 0x4c3bb98 is 8 bytes after a block of size 144 alloc'd
+==11670==    at 0x4A08946: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==11670==    by 0x44E133: btrfs_read_chunk_tree (volumes.c:1801)
+==11670==    by 0x43D654: btrfs_setup_chunk_tree_and_device_map (disk-io.c:1115)
+==11670==    by 0x43D7D0: __open_ctree_fd (disk-io.c:1190)
+==11670==    by 0x43D964: open_ctree_fs_info (disk-io.c:1231)
+==11670==    by 0x427BF4: cmd_check (cmds-check.c:9326)
+==11670==    by 0x40E5A1: main (btrfs.c:245)
+
+Program received signal SIGTRAP, Trace/breakpoint trap.
+btrfs_search_slot (trans=trans@entry=0x0, root=root@entry=0x4c36d30, key=key@entry=0xffefff830, p=p@entry=0x4c3bb00,
+    ins_len=ins_len@entry=0, cow=cow@entry=0) at ctree.c:1119
+1119                    p->nodes[level] = b;
+(gdb) p p->nodes
+$1 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
+(gdb) p p
+$2 = (struct btrfs_path *) 0x4c3bb00
+(gdb) p b
+$3 = (struct extent_buffer *) 0x4c3a990
+
+
+The corresponding part in ctree.c:btrfs_search_slot() seems to fail to check if `level` overflows outside of `node`:
+
+level = btrfs_header_level(b);
+...
+if (level != btrfs_header_level(b))
+    WARN_ON(1);
+level = btrfs_header_level(b);
+p->nodes[level] = b;  // <- Illegal write
+
+Maybe the repeated calls to btrfs_header_level() were meant to do something once, they seem to be noise.
diff --git a/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.xz b/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.xz
new file mode 100644 (file)
index 0000000..3c79edb
Binary files /dev/null and b/tests/fuzz-tests/images/bko-97271-btrfs-image.raw.xz differ