btrfs-progs: tests: add crafted and fuzzed images

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>
master
David Sterba 2015-09-09 17:04:12 +02:00
parent afff169e1a
commit a365b84a32
12 changed files with 248 additions and 0 deletions

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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.