[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