bug-parted
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 5/6] gpt: avoid division by zero


From: Jim Meyering
Subject: [PATCH 5/6] gpt: avoid division by zero
Date: Wed, 16 Mar 2011 19:41:10 +0100

* 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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]