dcavalca / rpms / grub2

Forked from rpms/grub2 3 years ago
Clone

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

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