Ping?

This is still reproducible on 4.9.8.

On Mon, Nov 28, 2016 at 12:03:12AM -0500, Zygo Blaxell wrote:
> Commit c8b978188c ("Btrfs: Add zlib compression support") produces
> data corruption when reading a file with a hole positioned after an
> inline extent.  btrfs_get_extent will return uninitialized kernel memory
> instead of zero bytes in the hole.
> 
> Commit 93c82d5750 ("Btrfs: zero page past end of inline file items")
> fills the hole by memset to zero after *uncompressed* inline extents.
> 
> This patch provides the missing memset for holes after *compressed*
> inline extents.
> 
> The offending holes appear in the wild and will appear during routine
> data integrity audits (e.g. comparing backups against their originals).
> They can also be created intentionally by fuzzing or crafting a filesystem
> image.
> 
> Holes like these are not intended to occur in btrfs; however, I tested
> tagged kernels between v3.5 and the present, and found that all of them
> can create such holes.  Whether we like them or not, this kind of hole
> is now part of the btrfs de-facto on-disk format, and we need to be able
> to read such holes without an infoleak or wrong data.
> 
> An example of a hole leading to data corruption:
> 
>         item 61 key (606890 INODE_ITEM 0) itemoff 9662 itemsize 160
>                 inode generation 50 transid 50 size 47424 nbytes 49141
>                 block group 0 mode 100644 links 1 uid 0 gid 0
>                 rdev 0 flags 0x0(none)
>         item 62 key (606890 INODE_REF 603050) itemoff 9642 itemsize 20
>                 inode ref index 3 namelen 10 name: DB_File.so
>         item 63 key (606890 EXTENT_DATA 0) itemoff 8280 itemsize 1362
>                 inline extent data size 1341 ram 4085 compress(zlib)
>         item 64 key (606890 EXTENT_DATA 4096) itemoff 8227 itemsize 53
>                 extent data disk byte 5367308288 nr 20480
>                 extent data offset 0 nr 45056 ram 45056
>                 extent compression(zlib)
> 
> Different data appears in userspace during each uncached read of the 10
> bytes between offset 4085 and 4095.  The extent in item 63 is not long
> enough to fill the first page of the file, so a memset is required to
> fill the space between item 63 (ending at 4085) and item 64 (beginning
> at 4096) with zero.
> 
> Signed-off-by: Zygo Blaxell <ce3g8...@umail.furryterror.org>
> 
> ---
>  fs/btrfs/inode.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 8e3a5a2..b1314d6 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -6803,6 +6803,12 @@ static noinline int uncompress_inline(struct 
> btrfs_path *path,
>       max_size = min_t(unsigned long, PAGE_SIZE, max_size);
>       ret = btrfs_decompress(compress_type, tmp, page,
>                              extent_offset, inline_size, max_size);
> +     WARN_ON(max_size > PAGE_SIZE);
> +     if (max_size < PAGE_SIZE) {
> +             char *map = kmap(page);
> +             memset(map + max_size, 0, PAGE_SIZE - max_size);
> +             kunmap(page);
> +     }
>       kfree(tmp);
>       return ret;
>  }
> -- 
> 2.1.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to