From patchwork Mon Nov 28 05:03:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zygo Blaxell X-Patchwork-Id: 9449103 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DFAAD6071E for ; Mon, 28 Nov 2016 05:08:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C40382022C for ; Mon, 28 Nov 2016 05:08:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B64EC20564; Mon, 28 Nov 2016 05:08:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C148A2022C for ; Mon, 28 Nov 2016 05:08:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751400AbcK1FIk (ORCPT ); Mon, 28 Nov 2016 00:08:40 -0500 Received: from james.kirk.hungrycats.org ([174.142.39.145]:48836 "EHLO james.kirk.hungrycats.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752565AbcK1FIi (ORCPT ); Mon, 28 Nov 2016 00:08:38 -0500 X-Greylist: delayed 313 seconds by postgrey-1.27 at vger.kernel.org; Mon, 28 Nov 2016 00:08:38 EST Received: by james.kirk.hungrycats.org (Postfix, from userid 1002) id CE51051465BC; Mon, 28 Nov 2016 00:03:23 -0500 (EST) From: Zygo Blaxell To: linux-btrfs@vger.kernel.org Subject: [PATCH] btrfs: fix hole read corruption for compressed inline extents Date: Mon, 28 Nov 2016 00:03:12 -0500 Message-Id: <1480309392-4786-1-git-send-email-ce3g8jdj@umail.furryterror.org> X-Mailer: git-send-email 2.1.4 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Liu Bo --- 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; }