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

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