diff --git a/ChangeLog b/ChangeLog index 752bde8..eac8b8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-07-25 Vladimir Serbinenko + + * partmap/pc.c (pc_partition_map_iterate): Detect and break loops. + 2009-07-25 Felix Zielcke * kern/file.c (grub_file_open): Revert to previous check with diff --git a/partmap/pc.c b/partmap/pc.c index 6f68ecf..165d3ac 100644 --- a/partmap/pc.c +++ b/partmap/pc.c @@ -97,6 +97,8 @@ pc_partition_map_iterate (grub_disk_t disk, struct grub_pc_partition_mbr mbr; struct grub_pc_partition_disk_label label; struct grub_disk raw; + int labeln = 0; + grub_disk_addr_t lastaddr; /* Enforce raw disk access. */ raw = *disk; @@ -117,6 +119,18 @@ pc_partition_map_iterate (grub_disk_t disk, if (grub_disk_read (&raw, p.offset, 0, sizeof (mbr), &mbr)) goto finish; + /* This is our loop-detection algorithm. It works the following way: + It saves last position which was a power of two. Then it compares the + saved value with a current one. This way it's guaranteed that the loop + will be broken by at most third walk. + */ + if (labeln && lastaddr == p.offset) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected"); + + labeln++; + if ((labeln & (labeln - 1)) == 0) + lastaddr = p.offset; + /* Check if it is valid. */ if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");