]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: fix integer overflows in HFS+ offset calculations
authorKarel Zak <kzak@redhat.com>
Wed, 25 Feb 2026 09:21:56 +0000 (10:21 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 25 Feb 2026 09:21:56 +0000 (10:21 +0100)
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 <kzak@redhat.com>
libblkid/src/superblocks/hfs.c

index 49a0e609327338c50a1578f6aea0fb34fcc88b95..2198b10afb118b6fe1918be6bba446c5e393284f 100644 (file)
@@ -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++) {