hfs_mdb_get() loops "while (1)" around hfs_part_find(), rereading the volume header wherever the partition table points. A partition entry with a zero start (pdStart or pmPyPartStart) leaves part_start where it was, and the loop reads the same blocks forever. An Apple partition map sits at the start of the raw device: the boot ROM reads it from block 1 (TN1189), and nothing Apple documents nests one inside a partition. Follow at most one partition-table hop and fail with -EIO after that, as for a table that cannot be parsed. A zero start is caught on the second pass, when the loop comes round again. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Matthias Goergens --- A partition entry pointing at its own table hangs the mount forever without this patch and fails at once with it: img=hfs-partmap-loop.img put() { printf "$2" | dd of=$img bs=1 seek=$1 conv=notrunc status=none; } truncate --size=64K $img put $((512+0x00)) '\x50\x4d' # pmSig 'PM' put $((512+0x04)) '\x00\x00\x00\x01' # pmMapBlkCnt 1 put $((512+0x08)) '\x00\x00\x00\x00' # pmPyPartStart 0 (self) put $((512+0x0c)) '\x00\x00\x00\x64' # pmPartBlkCnt 100 put $((512+0x30)) 'Apple_HFS' # pmPartType mount -o ro,loop -t hfs $img /mnt --- fs/hfs/mdb.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index 277de712f9d4..1704f332e28d 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -134,6 +134,7 @@ int hfs_mdb_get(struct super_block *sb) sector_t part_start, part_size; loff_t off; __be16 attrib; + bool part_hop_done = false; /* set the device driver to 512-byte blocks */ size = sb_min_blocksize(sb, HFS_SECTOR_SIZE); @@ -152,11 +153,18 @@ int hfs_mdb_get(struct super_block *sb) break; brelse(bh); - /* check for a partition block + /* + * check for a partition block * (should do this only for cdrom/loop though) + * + * The partition map is at the start of the device: follow + * it once, or an entry pointing at itself loops forever. */ + if (part_hop_done) + return -EIO; if (hfs_part_find(sb, &part_start, &part_size)) return -EIO; + part_hop_done = true; } HFS_SB(sb)->alloc_blksz = size = be32_to_cpu(mdb->drAlBlkSiz); base-commit: 6812ce4e4379ffc99c52401ec28f0d7ffbc36206 -- 2.55.0