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

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