Blame SOURCES/0261-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch

1c6ba0
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
1c6ba0
From: Darren Kenny <darren.kenny@oracle.com>
1c6ba0
Date: Thu, 7 Apr 2022 15:18:12 +0000
1c6ba0
Subject: [PATCH] fs/btrfs: Fix more fuzz issues related to chunks
1c6ba0
1c6ba0
The corpus we generating issues in grub_btrfs_read_logical() when
1c6ba0
attempting to iterate over nstripes entries in the boot mapping.
1c6ba0
1c6ba0
In most cases the reason for the failure was that the number of strips
1c6ba0
exceeded the possible space statically allocated in superblock bootmapping
1c6ba0
space. Each stripe entry in the bootmapping block consists of
1c6ba0
a grub_btrfs_key followed by a grub_btrfs_chunk_stripe.
1c6ba0
1c6ba0
Another issue that came up was that while calculating the chunk size,
1c6ba0
in an earlier piece of code in that function, depending on the data
1c6ba0
provided in the btrfs file system, it would end up calculating a size
1c6ba0
that was too small to contain even 1 grub_btrfs_chunk_item, which is
1c6ba0
obviously invalid too.
1c6ba0
1c6ba0
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
1c6ba0
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
1c6ba0
(cherry picked from commit e00cd76cbadcc897a9cc4087cb2fcb5dbe15e596)
1c6ba0
(cherry picked from commit b74a6fc95b0839937acf4f2b7445ae9d179f49ec)
1c6ba0
---
1c6ba0
 grub-core/fs/btrfs.c | 24 ++++++++++++++++++++++++
1c6ba0
 1 file changed, 24 insertions(+)
1c6ba0
1c6ba0
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
1c6ba0
index b104da085c..8ec885a93b 100644
1c6ba0
--- a/grub-core/fs/btrfs.c
1c6ba0
+++ b/grub-core/fs/btrfs.c
1c6ba0
@@ -947,6 +947,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
1c6ba0
 	  return grub_error (GRUB_ERR_BAD_FS,
1c6ba0
 			     "got an invalid zero-size chunk");
1c6ba0
 	}
1c6ba0
+
1c6ba0
+      /*
1c6ba0
+       * The space being allocated for a chunk should at least be able to
1c6ba0
+       * contain one chunk item.
1c6ba0
+       */
1c6ba0
+      if (chsize < sizeof (struct grub_btrfs_chunk_item))
1c6ba0
+       {
1c6ba0
+         grub_dprintf ("btrfs", "chunk-size too small\n");
1c6ba0
+         return grub_error (GRUB_ERR_BAD_FS,
1c6ba0
+                            "got an invalid chunk size");
1c6ba0
+       }
1c6ba0
       chunk = grub_malloc (chsize);
1c6ba0
       if (!chunk)
1c6ba0
 	return grub_errno;
1c6ba0
@@ -1194,6 +1205,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
1c6ba0
 	if (csize > (grub_uint64_t) size)
1c6ba0
 	  csize = size;
1c6ba0
 
1c6ba0
+	/*
1c6ba0
+	 * The space for a chunk stripe is limited to the space provide in the super-block's
1c6ba0
+	 * bootstrap mapping with an initial btrfs key at the start of each chunk.
1c6ba0
+	 */
1c6ba0
+	grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) /
1c6ba0
+	  (sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe));
1c6ba0
+
1c6ba0
 	for (j = 0; j < 2; j++)
1c6ba0
 	  {
1c6ba0
 	    grub_size_t est_chunk_alloc = 0;
1c6ba0
@@ -1220,6 +1238,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
1c6ba0
 		break;
1c6ba0
 	      }
1c6ba0
 
1c6ba0
+	   if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes)
1c6ba0
+             {
1c6ba0
+               err = GRUB_ERR_BAD_FS;
1c6ba0
+               break;
1c6ba0
+             }
1c6ba0
+
1c6ba0
 	    if (is_raid56)
1c6ba0
 	      {
1c6ba0
 		err = btrfs_read_from_chunk (data, chunk, stripen,