[Bug 205816] [ext2fs] [patch] EXT4 sparse blocks unsupported, contain garbage when read

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Sun Jan 3 04:35:00 UTC 2016


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=205816

            Bug ID: 205816
           Summary: [ext2fs] [patch] EXT4 sparse blocks unsupported,
                    contain garbage when read
           Product: Base System
           Version: 11.0-CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Keywords: patch
          Severity: Affects Many People
          Priority: ---
         Component: kern
          Assignee: freebsd-bugs at FreeBSD.org
          Reporter: damjan.jov at gmail.com
                CC: freebsd-fs at FreeBSD.org

Created attachment 164979
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=164979&action=edit
preliminary patch to implement support for EXT4 sparse files

The ext2fs module does not support sparse files on EXT4 filesystems, yet
doesn't fail. When attempting to read the sparse blocks from a sparse file,
instead of zeroes, they contain garbage data read from the wrong disk blocks.

Here's an example sparse file in debugfs:

debugfs:  dump_extents /home/user/Documents/file.iso
Level Entries           Logical            Physical Length Flags
 0/ 1   1/  1       0 - 1122599  1082775            1122600
 1/ 1   1/ 53       0 -       5  1372160 -  1372165      6
 1/ 1   2/ 53       8 -      11  1372168 -  1372171      4
 1/ 1   3/ 53      16 -      19  1372176 -  1372179      4
 1/ 1   4/ 53      24 -      27  1372184 -  1372187      4
 1/ 1   5/ 53      32 -      33  1372192 -  1372193      2
...

Note how block ranges 0-5, 8-11, 16-19 are allocated, but the in between blocks
are sparse.

The problem starts in the ext4_ext_binsearch() function in ext2_extents.c which
expects the block ranges in the extents to be continuous, and doesn't check
whether the lbn parameter even lies inside the found extent's block range. It
blindly sets:

path->ep_ext = l - 1;

which will set the pointer to invalid memory (a part of struct
ext2_extent_header) when lbn=0 and the first block of a file is sparse. Also in
the above example, lbn=6 will use the 0-5 extent, reading block 0 instead.

My preliminary patch improves ext4_ext_binsearch() to check for out of range
blocks, marks the path as being sparse, and stores the range of extents
starting at the lbn that is sparse. Sparse extents are cached in
ext4_ext_read() for future reuse. Actual reading of sparse blocks is
implemented by copying from a static array of zeroes (is there a better way of
doing it?) and read() definitely works, but mmap() doesn't seem to (system
instantly reboots when reading even 1 byte from mapped region, but this also
happens for some dense files, so it's not (just?) my patch).

If testing against other EXT4 implementations, note that ext4fuse also has this
bug.

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list