diff options
Diffstat (limited to 'libblkid/src/superblocks/hfs.c')
-rw-r--r-- | libblkid/src/superblocks/hfs.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/libblkid/src/superblocks/hfs.c b/libblkid/src/superblocks/hfs.c index 68cb30e..49a0e60 100644 --- a/libblkid/src/superblocks/hfs.c +++ b/libblkid/src/superblocks/hfs.c @@ -154,7 +154,7 @@ static int hfs_set_uuid(blkid_probe pr, unsigned char const *hfs_info, size_t le static int probe_hfs(blkid_probe pr, const struct blkid_idmag *mag) { - struct hfs_mdb *hfs; + const struct hfs_mdb *hfs; int size; hfs = blkid_probe_get_sb(pr, mag, struct hfs_mdb); @@ -183,11 +183,11 @@ static int probe_hfs(blkid_probe pr, const struct blkid_idmag *mag) static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) { struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; - struct hfsplus_bnode_descriptor *descr; - struct hfsplus_bheader_record *bnode; - struct hfsplus_catalog_key *key; - struct hfsplus_vol_header *hfsplus; - struct hfs_mdb *sbd; + const struct hfsplus_bnode_descriptor *descr; + const struct hfsplus_bheader_record *bnode; + const struct hfsplus_catalog_key *key; + const struct hfsplus_vol_header *hfsplus; + const struct hfs_mdb *sbd; unsigned int alloc_block_size; unsigned int alloc_first_block; unsigned int embed_first_block; @@ -203,7 +203,7 @@ static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) unsigned int leaf_block; int ext; uint64_t leaf_off; - unsigned char *buf; + const unsigned char *buf; sbd = blkid_probe_get_sb(pr, mag, struct hfs_mdb); if (!sbd) @@ -217,6 +217,10 @@ static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) return 1; alloc_block_size = be32_to_cpu(sbd->al_blk_size); + if (alloc_block_size < HFSPLUS_SECTOR_SIZE || + alloc_block_size % HFSPLUS_SECTOR_SIZE) + return 1; + alloc_first_block = be16_to_cpu(sbd->al_bl_st); embed_first_block = be16_to_cpu(sbd->embed_startblock); off = (alloc_first_block * 512) + @@ -225,7 +229,7 @@ static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) buf = blkid_probe_get_buffer(pr, off + (mag->kboff * 1024), sizeof(struct hfsplus_vol_header)); - hfsplus = (struct hfsplus_vol_header *) buf; + hfsplus = (const struct hfsplus_vol_header *) buf; } else hfsplus = blkid_probe_get_sb(pr, mag, @@ -238,17 +242,23 @@ static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) (memcmp(hfsplus->signature, "HX", 2) != 0)) return 1; - hfs_set_uuid(pr, hfsplus->finder_info.id, sizeof(hfsplus->finder_info.id)); - + /* Verify blocksize is initialized */ blocksize = be32_to_cpu(hfsplus->blocksize); - if (blocksize < HFSPLUS_SECTOR_SIZE) + if (blocksize < HFSPLUS_SECTOR_SIZE || !is_power_of_2(blocksize)) return 1; - blkid_probe_set_fsblocksize(pr, blocksize); - blkid_probe_set_block_size(pr, blocksize); - + /* Save extends (hfsplus buffer may be later overwritten) */ memcpy(extents, hfsplus->cat_file.extents, sizeof(extents)); + + /* Make sure start_block is properly initialized */ cat_block = be32_to_cpu(extents[0].start_block); + if (off + ((uint64_t) cat_block * blocksize) > pr->size) + return 1; + + hfs_set_uuid(pr, hfsplus->finder_info.id, sizeof(hfsplus->finder_info.id)); + + blkid_probe_set_fsblocksize(pr, blocksize); + blkid_probe_set_block_size(pr, blocksize); buf = blkid_probe_get_buffer(pr, off + ((uint64_t) cat_block * blocksize), 0x2000); |