]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: Fix out of bounds reads on bad GPT header
authorAlden Tondettar <alden.tondettar@gmail.com>
Tue, 24 Jan 2017 06:28:00 +0000 (23:28 -0700)
committerKarel Zak <kzak@redhat.com>
Tue, 21 Feb 2017 12:10:51 +0000 (13:10 +0100)
If a GUID Partition Table claims to have more than 2**25 entries, or if the
size of each entry is not exactly 128 bytes, libblkid can read out of bounds
and segfault. Perform the appropriate checks.

[kzak@redhat.com: - fix typo]

Signed-off-by: Alden Tondettar <alden.tondettar@gmail.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
libblkid/src/partitions/gpt.c

index e6baa598b8f2354621b3f3060a61dc5f8e487738..d987236d3eddacfc74e5a8af0a25b21f363126df 100644 (file)
@@ -210,7 +210,7 @@ static struct gpt_header *get_gpt_header(
        struct gpt_header *h;
        uint32_t crc;
        uint64_t lu, fu;
-       size_t esz;
+       uint64_t esz;
        uint32_t hsz, ssz;
 
        ssz = blkid_probe_get_sectorsize(pr);
@@ -264,17 +264,16 @@ static struct gpt_header *get_gpt_header(
                return NULL;
        }
 
-       if (le32_to_cpu(h->num_partition_entries) == 0 ||
-           le32_to_cpu(h->sizeof_partition_entry) == 0 ||
-           ULONG_MAX / le32_to_cpu(h->num_partition_entries) < le32_to_cpu(h->sizeof_partition_entry)) {
+       /* Size of blocks with GPT entries */
+       esz = (uint64_t)le32_to_cpu(h->num_partition_entries) *
+               le32_to_cpu(h->sizeof_partition_entry);
+
+       if (esz == 0 || esz >= UINT32_MAX ||
+           le32_to_cpu(h->sizeof_partition_entry) != sizeof(struct gpt_entry)) {
                DBG(LOWPROBE, ul_debug("GPT entries undefined"));
                return NULL;
        }
 
-       /* Size of blocks with GPT entries */
-       esz = le32_to_cpu(h->num_partition_entries) *
-                       le32_to_cpu(h->sizeof_partition_entry);
-
        /* The header seems valid, save it
         * (we don't care about zeros in hdr->reserved2 area) */
        memcpy(hdr, h, sizeof(*h));