From 5fe21c996893b9ef4d22a728b40f75d4b4cd7566 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Fri, 6 Mar 2015 22:33:20 +0100 Subject: [PATCH] hfsplus: Fix potential access to uninited memory on invalid FS --- grub-core/fs/hfsplus.c | 6 ++++++ include/grub/hfsplus.h | 14 +++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 8f07f8544..110d85815 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -336,6 +336,9 @@ grub_hfsplus_mount (grub_disk_t disk) data->case_sensitive = ((magic == GRUB_HFSPLUSX_MAGIC) && (header.key_compare == GRUB_HFSPLUSX_BINARYCOMPARE)); + if (data->catalog_tree.nodesize < 2) + goto fail; + if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, sizeof (struct grub_hfsplus_btnode), sizeof (header), (char *) &header) <= 0) @@ -350,6 +353,9 @@ grub_hfsplus_mount (grub_disk_t disk) data->extoverflow_tree.root = grub_be_to_cpu32 (header.root); data->extoverflow_tree.nodesize = grub_be_to_cpu16 (header.nodesize); + if (data->extoverflow_tree.nodesize < 2) + goto fail; + if (grub_hfsplus_read_file (&data->attr_tree.file, 0, 0, sizeof (struct grub_hfsplus_btnode), sizeof (header), (char *) &header) <= 0) diff --git a/include/grub/hfsplus.h b/include/grub/hfsplus.h index 8ba8f3246..117740ae2 100644 --- a/include/grub/hfsplus.h +++ b/include/grub/hfsplus.h @@ -171,7 +171,7 @@ struct grub_hfsplus_catkey grub_uint16_t keylen; grub_uint32_t parent; grub_uint16_t namelen; - grub_uint16_t name[30]; + grub_uint16_t name[0]; } GRUB_PACKED; /* The on disk layout of an extent overflow file key. */ @@ -207,12 +207,14 @@ struct grub_hfsplus_btnode /* Return the offset of the record with the index INDEX, in the node NODE which is part of the B+ tree BTREE. */ -static inline grub_off_t +static inline grub_uint16_t grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, - struct grub_hfsplus_btnode *node, int index) + struct grub_hfsplus_btnode *node, unsigned index) { char *cnode = (char *) node; void *recptr; + if (btree->nodesize < index * sizeof (grub_uint16_t) + 2) + index = 0; recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]); return grub_be_to_cpu16 (grub_get_unaligned16 (recptr)); } @@ -221,11 +223,13 @@ grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, NODE which is part of the B+ tree BTREE. */ static inline struct grub_hfsplus_key * grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree, - struct grub_hfsplus_btnode *node, int index) + struct grub_hfsplus_btnode *node, unsigned index) { char *cnode = (char *) node; - grub_off_t offset; + grub_uint16_t offset; offset = grub_hfsplus_btree_recoffset (btree, node, index); + if (offset > btree->nodesize - sizeof (struct grub_hfsplus_key)) + offset = 0; return (struct grub_hfsplus_key *) &cnode[offset]; }