* libparted/labels/gpt.c (_header_is_valid): Reject as invalid if FirstUsableLBA < 3. (gpt_get_max_supported_partition_count): Ensure that we don't divide by zero: verify that the GPT header is valid before dividing by its "size of partition entry". Under normal circumstances, the on-disk PE size field is reasonable because we have just written it. However, there are two ways it can end up zero: we lose the race when some other process pokes a 4-byte 0 into just the right location between when we write it and when we re-read the value we're about to divide by. Then there's the case that I encountered: using an old USB (8MB) key, mklabel gpt failed due to division by zero. The device reported no failure when writing the initial header, yet when reading back that very same sector (also successful), parted got all 0 bytes. * NEWS (Bug fixes): Mention it. --- NEWS | 5 +++++ libparted/labels/gpt.c | 11 +++++++++++ 2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/NEWS b/NEWS index 604b53d..b7143eb 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,11 @@ GNU parted NEWS -*- outline -*- libparted: zero-length devices (other than files) are ignored rather than throwing an exception. + libparted: gpt label creation can no longer divide by zero with a + defective device or when a concurrent writer modifies the PE-size + bytes in the small interval between the write and subsequent read + of the primary GPT header. + ** Changes in behavior "parted $dev print" now prints information about the device (model, size, diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c index 54f0785..bfbe7f9 100644 --- a/libparted/labels/gpt.c +++ b/libparted/labels/gpt.c @@ -660,6 +660,10 @@ _header_is_valid (PedDisk const *disk, GuidPartitionTableHeader_t *gpt, if (check_PE_array_CRC (disk, gpt, &crc_match) != 0 || !crc_match) return 0; + PedSector first_usable = PED_LE64_TO_CPU (gpt->FirstUsableLBA); + if (first_usable < 3) + return 0; + origcrc = gpt->HeaderCRC32; gpt->HeaderCRC32 = 0; if (pth_crc32 (dev, gpt, &crc) != 0) @@ -1741,6 +1745,13 @@ gpt_get_max_supported_partition_count (const PedDisk *disk, int *max_n) if (pth == NULL) return false; + if (!_header_is_valid (disk, pth, 1)) + { + pth->FirstUsableLBA = 34; + pth->SizeOfPartitionEntry + = PED_CPU_TO_LE32 (sizeof (GuidPartitionEntry_t)); + } + *max_n = (disk->dev->sector_size * (pth->FirstUsableLBA - 2) / PED_LE32_TO_CPU (pth->SizeOfPartitionEntry)); pth_free (pth); -- 1.7.4.1.430.g5aa4d _______________________________________________ bug-parted mailing list bug-parted@gnu.org http://lists.gnu.org/mailman/listinfo/bug-parted