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