[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <lsq.1587683028.206849923@decadent.org.uk>
Date: Fri, 24 Apr 2020 00:04:17 +0100
From: Ben Hutchings <ben@...adent.org.uk>
To: linux-kernel@...r.kernel.org, stable@...r.kernel.org
CC: akpm@...ux-foundation.org, Denis Kirjanov <kda@...ux-powerpc.org>,
"Ben Hutchings" <ben.hutchings@...ethink.co.uk>,
"Greg Kroah-Hartman" <gregkh@...uxfoundation.org>,
"Liu Bo" <bo.li.liu@...cle.com>, "David Sterba" <dsterba@...e.com>,
"Chris Mason" <clm@...com>
Subject: [PATCH 3.16 030/245] Btrfs: check btree node's nritems
3.16.83-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <bo.li.liu@...cle.com>
commit 053ab70f0604224c7893b43f9d9d5efa283580d6 upstream.
When btree node (level = 1) has nritems which equals to zero,
we can end up with panic due to insert_ptr()'s
BUG_ON(slot > nritems);
where slot is 1 and nritems is 0, as copy_for_split() calls
insert_ptr(.., path->slots[1] + 1, ...);
A invalid value results in the whole mess, this adds the check
for btree's node nritems so that we stop reading block when
when something is wrong.
Signed-off-by: Liu Bo <bo.li.liu@...cle.com>
Reviewed-by: David Sterba <dsterba@...e.com>
Signed-off-by: David Sterba <dsterba@...e.com>
Signed-off-by: Chris Mason <clm@...com>
Signed-off-by: Ben Hutchings <ben.hutchings@...ethink.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Signed-off-by: Ben Hutchings <ben@...adent.org.uk>
---
fs/btrfs/disk-io.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -594,6 +594,19 @@ static noinline int check_leaf(struct bt
return 0;
}
+static int check_node(struct btrfs_root *root, struct extent_buffer *node)
+{
+ unsigned long nr = btrfs_header_nritems(node);
+
+ if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
+ btrfs_crit(root->fs_info,
+ "corrupt node: block %llu root %llu nritems %lu",
+ node->start, root->objectid, nr);
+ return -EIO;
+ }
+ return 0;
+}
+
static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
u64 phy_offset, struct page *page,
u64 start, u64 end, int mirror)
@@ -666,6 +679,9 @@ static int btree_readpage_end_io_hook(st
ret = -EIO;
}
+ if (found_level > 0 && check_node(root, eb))
+ ret = -EIO;
+
if (!ret)
set_extent_buffer_uptodate(eb);
err:
Powered by blists - more mailing lists