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