|
|
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 |
|