From: Karel Zak Date: Wed, 25 Feb 2026 09:21:56 +0000 (+0100) Subject: libblkid: fix integer overflows in HFS+ offset calculations X-Git-Tag: v2.43-devel~37^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e589e409b7fa3ecd6b0baeed7660edbf5f93bb65;p=thirdparty%2Futil-linux.git libblkid: fix integer overflows in HFS+ offset calculations Two 32-bit multiplications using on-disk values can overflow: - leaf_node_head (uint32_t) * leaf_node_size (uint16_t) used to calculate leaf_block; overflow produces a wrong block number, causing reads from incorrect offsets. - embed_first_block (uint16_t) * alloc_block_size (uint32_t) used to calculate the embedded HFS+ volume offset; overflow truncates the result, again causing reads from wrong offsets. Fix by widening leaf_block and off to uint64_t and casting multiplication operands. Bogus results from crafted images are then safely rejected by blkid_probe_get_buffer() bounds checking and the extent loop exhaustion. Signed-off-by: Karel Zak --- diff --git a/libblkid/src/superblocks/hfs.c b/libblkid/src/superblocks/hfs.c index 49a0e6093..2198b10af 100644 --- a/libblkid/src/superblocks/hfs.c +++ b/libblkid/src/superblocks/hfs.c @@ -191,7 +191,7 @@ static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) unsigned int alloc_block_size; unsigned int alloc_first_block; unsigned int embed_first_block; - unsigned int off = 0; + uint64_t off = 0; unsigned int blocksize; unsigned int cat_block; unsigned int ext_block_start = 0; @@ -200,7 +200,7 @@ static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) unsigned int leaf_node_head; unsigned int leaf_node_count; unsigned int leaf_node_size; - unsigned int leaf_block; + uint64_t leaf_block; int ext; uint64_t leaf_off; const unsigned char *buf; @@ -223,8 +223,8 @@ static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) alloc_first_block = be16_to_cpu(sbd->al_bl_st); embed_first_block = be16_to_cpu(sbd->embed_startblock); - off = (alloc_first_block * 512) + - (embed_first_block * alloc_block_size); + off = ((uint64_t) alloc_first_block * 512) + + ((uint64_t) embed_first_block * alloc_block_size); buf = blkid_probe_get_buffer(pr, off + (mag->kboff * 1024), @@ -276,7 +276,7 @@ static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) sizeof(struct hfsplus_catalog_key) || leaf_node_count == 0) return 0; - leaf_block = (leaf_node_head * leaf_node_size) / blocksize; + leaf_block = ((uint64_t) leaf_node_head * leaf_node_size) / blocksize; /* get physical location */ for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {