Commit c5082b70 authored by Alden Tondettar's avatar Alden Tondettar Committed by Jens Axboe

partitions/efi: Fix integer overflow in GPT size calculation

If a GUID Partition Table claims to have more than 2**25 entries, the
calculation of the partition table size in alloc_read_gpt_entries() will
overflow a 32-bit integer and not enough space will be allocated for the
table.

Nothing seems to get written out of bounds, but later efi_partition() will
read up to 32768 bytes from a 128 byte buffer, possibly OOPSing or exposing
information to /proc/partitions and uevents.

The problem exists on both 64-bit and 32-bit platforms.

Fix the overflow and also print a meaningful debug message if the table
size is too large.
Signed-off-by: default avatarAlden Tondettar <alden.tondettar@gmail.com>
Acked-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 1e668f4e
...@@ -293,7 +293,7 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state, ...@@ -293,7 +293,7 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state,
if (!gpt) if (!gpt)
return NULL; return NULL;
count = le32_to_cpu(gpt->num_partition_entries) * count = (size_t)le32_to_cpu(gpt->num_partition_entries) *
le32_to_cpu(gpt->sizeof_partition_entry); le32_to_cpu(gpt->sizeof_partition_entry);
if (!count) if (!count)
return NULL; return NULL;
...@@ -352,7 +352,7 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, ...@@ -352,7 +352,7 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
gpt_header **gpt, gpt_entry **ptes) gpt_header **gpt, gpt_entry **ptes)
{ {
u32 crc, origcrc; u32 crc, origcrc;
u64 lastlba; u64 lastlba, pt_size;
if (!ptes) if (!ptes)
return 0; return 0;
...@@ -434,13 +434,20 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, ...@@ -434,13 +434,20 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
goto fail; goto fail;
} }
/* Sanity check partition table size */
pt_size = (u64)le32_to_cpu((*gpt)->num_partition_entries) *
le32_to_cpu((*gpt)->sizeof_partition_entry);
if (pt_size > KMALLOC_MAX_SIZE) {
pr_debug("GUID Partition Table is too large: %llu > %lu bytes\n",
(unsigned long long)pt_size, KMALLOC_MAX_SIZE);
goto fail;
}
if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) if (!(*ptes = alloc_read_gpt_entries(state, *gpt)))
goto fail; goto fail;
/* Check the GUID Partition Entry Array CRC */ /* Check the GUID Partition Entry Array CRC */
crc = efi_crc32((const unsigned char *) (*ptes), crc = efi_crc32((const unsigned char *) (*ptes), pt_size);
le32_to_cpu((*gpt)->num_partition_entries) *
le32_to_cpu((*gpt)->sizeof_partition_entry));
if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
pr_debug("GUID Partition Entry Array CRC check failed.\n"); pr_debug("GUID Partition Entry Array CRC check failed.\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment