Blame SOURCES/0440-fs-hfsplus-Don-t-use-uninitialized-data-on-corrupt-f.patch

468bd4
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
468bd4
From: Daniel Axtens <dja@axtens.net>
468bd4
Date: Tue, 2 Feb 2021 16:59:35 +1100
468bd4
Subject: [PATCH] fs/hfsplus: Don't use uninitialized data on corrupt
468bd4
 filesystems
468bd4
468bd4
Valgrind identified the following use of uninitialized data:
468bd4
468bd4
  ==2782220== Conditional jump or move depends on uninitialised value(s)
468bd4
  ==2782220==    at 0x42B364: grub_hfsplus_btree_search (hfsplus.c:566)
468bd4
  ==2782220==    by 0x42B21D: grub_hfsplus_read_block (hfsplus.c:185)
468bd4
  ==2782220==    by 0x42A693: grub_fshelp_read_file (fshelp.c:386)
468bd4
  ==2782220==    by 0x42C598: grub_hfsplus_read_file (hfsplus.c:219)
468bd4
  ==2782220==    by 0x42C598: grub_hfsplus_mount (hfsplus.c:330)
468bd4
  ==2782220==    by 0x42B8C5: grub_hfsplus_dir (hfsplus.c:958)
468bd4
  ==2782220==    by 0x4C1AE6: grub_fs_probe (fs.c:73)
468bd4
  ==2782220==    by 0x407C94: grub_ls_list_files (ls.c:186)
468bd4
  ==2782220==    by 0x407C94: grub_cmd_ls (ls.c:284)
468bd4
  ==2782220==    by 0x4D7130: grub_extcmd_dispatcher (extcmd.c:55)
468bd4
  ==2782220==    by 0x4045A6: execute_command (grub-fstest.c:59)
468bd4
  ==2782220==    by 0x4045A6: fstest (grub-fstest.c:433)
468bd4
  ==2782220==    by 0x4045A6: main (grub-fstest.c:772)
468bd4
  ==2782220==  Uninitialised value was created by a heap allocation
468bd4
  ==2782220==    at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
468bd4
  ==2782220==    by 0x4C0305: grub_malloc (mm.c:42)
468bd4
  ==2782220==    by 0x42C21D: grub_hfsplus_mount (hfsplus.c:239)
468bd4
  ==2782220==    by 0x42B8C5: grub_hfsplus_dir (hfsplus.c:958)
468bd4
  ==2782220==    by 0x4C1AE6: grub_fs_probe (fs.c:73)
468bd4
  ==2782220==    by 0x407C94: grub_ls_list_files (ls.c:186)
468bd4
  ==2782220==    by 0x407C94: grub_cmd_ls (ls.c:284)
468bd4
  ==2782220==    by 0x4D7130: grub_extcmd_dispatcher (extcmd.c:55)
468bd4
  ==2782220==    by 0x4045A6: execute_command (grub-fstest.c:59)
468bd4
  ==2782220==    by 0x4045A6: fstest (grub-fstest.c:433)
468bd4
  ==2782220==    by 0x4045A6: main (grub-fstest.c:772)
468bd4
468bd4
This happens when the process of reading the catalog file goes sufficiently
468bd4
wrong that there's an attempt to read the extent overflow file, which has
468bd4
not yet been loaded. Keep track of when the extent overflow file is
468bd4
fully loaded and refuse to use it before then.
468bd4
468bd4
The load valgrind doesn't like is btree->nodesize, and that's then used
468bd4
to allocate a data structure. It looks like there are subsequently a lot
468bd4
of reads based on that pointer so OOB reads are likely, and indeed crashes
468bd4
(albeit difficult-to-replicate ones) have been observed in fuzzing.
468bd4
468bd4
Signed-off-by: Daniel Axtens <dja@axtens.net>
468bd4
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
468bd4
---
468bd4
 grub-core/fs/hfsplus.c | 14 ++++++++++++++
468bd4
 include/grub/hfsplus.h |  2 ++
468bd4
 2 files changed, 16 insertions(+)
468bd4
468bd4
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
468bd4
index 423f4b956ba..8c0c804735d 100644
468bd4
--- a/grub-core/fs/hfsplus.c
468bd4
+++ b/grub-core/fs/hfsplus.c
468bd4
@@ -177,6 +177,17 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
468bd4
 	  break;
468bd4
 	}
468bd4
 
468bd4
+      /*
468bd4
+       * If the extent overflow tree isn't ready yet, we can't look
468bd4
+       * in it. This can happen where the catalog file is corrupted.
468bd4
+       */
468bd4
+      if (!node->data->extoverflow_tree_ready)
468bd4
+	{
468bd4
+	  grub_error (GRUB_ERR_BAD_FS,
468bd4
+		      "attempted to read extent overflow tree before loading");
468bd4
+	  break;
468bd4
+	}
468bd4
+
468bd4
       /* Set up the key to look for in the extent overflow file.  */
468bd4
       extoverflow.extkey.fileid = node->fileid;
468bd4
       extoverflow.extkey.type = 0;
468bd4
@@ -241,6 +252,7 @@ grub_hfsplus_mount (grub_disk_t disk)
468bd4
     return 0;
468bd4
 
468bd4
   data->disk = disk;
468bd4
+  data->extoverflow_tree_ready = 0;
468bd4
 
468bd4
   /* Read the bootblock.  */
468bd4
   grub_disk_read (disk, GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader),
468bd4
@@ -357,6 +369,8 @@ grub_hfsplus_mount (grub_disk_t disk)
468bd4
   if (data->extoverflow_tree.nodesize < 2)
468bd4
     goto fail;
468bd4
 
468bd4
+  data->extoverflow_tree_ready = 1;
468bd4
+
468bd4
   if (grub_hfsplus_read_file (&data->attr_tree.file, 0, 0,
468bd4
 			      sizeof (struct grub_hfsplus_btnode),
468bd4
 			      sizeof (header), (char *) &header) <= 0)
468bd4
diff --git a/include/grub/hfsplus.h b/include/grub/hfsplus.h
468bd4
index 117740ae269..e14dd31ff54 100644
468bd4
--- a/include/grub/hfsplus.h
468bd4
+++ b/include/grub/hfsplus.h
468bd4
@@ -113,6 +113,8 @@ struct grub_hfsplus_data
468bd4
   struct grub_hfsplus_btree extoverflow_tree;
468bd4
   struct grub_hfsplus_btree attr_tree;
468bd4
 
468bd4
+  int extoverflow_tree_ready;
468bd4
+
468bd4
   struct grub_hfsplus_file dirroot;
468bd4
   struct grub_hfsplus_file opened_file;
468bd4