diff mbox series

btrfs-progs: save item data end in u64 to avoid overflow in btrfs_check_leaf()

Message ID 20220222090528.1211-1-l@damenly.su (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: save item data end in u64 to avoid overflow in btrfs_check_leaf() | expand

Commit Message

Su Yue Feb. 22, 2022, 9:05 a.m. UTC
Similar to kernel check_leaf(), calling btrfs_item_end_nr() may get a
reasonable value even an item has invalid offset/size due to u32
overflow.

Fix it by use u64 variable to store item data end in btrfs_check_leaf()
to avoid u32 overflow.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=215299
Reported-by: Wenqing Liu <wenqingliu0120@gmail.com>
Signed-off-by: Su Yue <l@damenly.su>
---
 kernel-shared/ctree.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

Comments

David Sterba July 18, 2022, 4:25 p.m. UTC | #1
On Tue, Feb 22, 2022 at 05:05:28PM +0800, Su Yue wrote:
> Similar to kernel check_leaf(), calling btrfs_item_end_nr() may get a
> reasonable value even an item has invalid offset/size due to u32
> overflow.
> 
> Fix it by use u64 variable to store item data end in btrfs_check_leaf()
> to avoid u32 overflow.
> 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=215299
> Reported-by: Wenqing Liu <wenqingliu0120@gmail.com>
> Signed-off-by: Su Yue <l@damenly.su>

Added to devel, thanks.
diff mbox series

Patch

diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c
index 950923d03165..8440e55ee280 100644
--- a/kernel-shared/ctree.c
+++ b/kernel-shared/ctree.c
@@ -706,6 +706,7 @@  btrfs_check_leaf(struct btrfs_fs_info *fs_info,
 	 */
 	for (slot = 0; slot < nritems; slot++) {
 		u32 item_end_expected;
+		u64 item_data_end;
 
 		btrfs_item_key_to_cpu(leaf, &key, slot);
 
@@ -720,6 +721,8 @@  btrfs_check_leaf(struct btrfs_fs_info *fs_info,
 			goto fail;
 		}
 
+		item_data_end = (u64)btrfs_item_offset_nr(leaf, slot) +
+				btrfs_item_size_nr(leaf, slot);
 		/*
 		 * Make sure the offset and ends are right, remember that the
 		 * item data starts at the end of the leaf and grows towards the
@@ -730,11 +733,10 @@  btrfs_check_leaf(struct btrfs_fs_info *fs_info,
 		else
 			item_end_expected = btrfs_item_offset_nr(leaf,
 								 slot - 1);
-		if (btrfs_item_end_nr(leaf, slot) != item_end_expected) {
+		if (item_data_end != item_end_expected) {
 			generic_err(leaf, slot,
-				"unexpected item end, have %u expect %u",
-				btrfs_item_end_nr(leaf, slot),
-				item_end_expected);
+				"unexpected item end, have %llu expect %u",
+				item_data_end, item_end_expected);
 			ret = BTRFS_TREE_BLOCK_INVALID_OFFSETS;
 			goto fail;
 		}
@@ -744,12 +746,10 @@  btrfs_check_leaf(struct btrfs_fs_info *fs_info,
 		 * just in case all the items are consistent to each other, but
 		 * all point outside of the leaf.
 		 */
-		if (btrfs_item_end_nr(leaf, slot) >
-		    BTRFS_LEAF_DATA_SIZE(fs_info)) {
+		if (item_data_end > BTRFS_LEAF_DATA_SIZE(fs_info)) {
 			generic_err(leaf, slot,
-			"slot end outside of leaf, have %u expect range [0, %u]",
-				btrfs_item_end_nr(leaf, slot),
-				BTRFS_LEAF_DATA_SIZE(fs_info));
+			"slot end outside of leaf, have %llu expect range [0, %u]",
+				item_data_end, BTRFS_LEAF_DATA_SIZE(fs_info));
 			ret = BTRFS_TREE_BLOCK_INVALID_OFFSETS;
 			goto fail;
 		}