[PATCH] partitions: efi: fix overflow issues while allocating gpt entries
Abdelrahman Youssef
abdelrahmanyossef12 at gmail.com
Thu Oct 31 05:48:52 PDT 2024
while parsting the GPT header in alloc_read_gpt_entries() the number
of partitions can be large that multiplying it with the size of a single
partition overflows 32-bit multiplication.
we already enforce a MAX_PARTITION limit of 128 partitions in efi_partition(),
so allowing any bigger value in alloc_read_gpt_entries() would fail,
even if we fix the overflow.
Therefore, we can enforce the limit strictly and treat any overflow as
a failing condition.
Signed-off-by: Abdelrahman Youssef <abdelrahmanyossef12 at gmail.com>
---
common/partitions/efi.c | 36 ++++++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index 9a04b7014d..8014579b67 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -35,6 +35,25 @@ struct efi_partition {
static const int force_gpt = IS_ENABLED(CONFIG_PARTITION_DISK_EFI_GPT_NO_FORCE);
+/**
+* compute_partitions_entries_size() - return the size of all partitions
+* @gpt: GPT header
+*
+* Description: return size of all partitions, 0 on error
+*
+* This is a helper function that compute the size of all partitions
+* by multiplying the size of a single partition by the number of partitions
+*/
+static u32 compute_partitions_entries_size(const gpt_header *gpt) {
+ u32 nb_parts, sz_parts, total_size;
+
+ nb_parts = min(MAX_PARTITION, le32_to_cpu(gpt->num_partition_entries));
+ sz_parts = le32_to_cpu(gpt->sizeof_partition_entry);
+ if (check_mul_overflow(nb_parts, sz_parts, &total_size))
+ return 0;
+ return total_size;
+}
+
/**
* efi_crc32() - EFI version of crc32 function
* @buf: buffer to calculate crc32 of
@@ -81,14 +100,12 @@ static u64 last_lba(struct block_device *bdev)
static gpt_entry *alloc_read_gpt_entries(struct block_device *blk,
gpt_header * pgpt_head)
{
- size_t count = 0;
+ u32 count = 0;
gpt_entry *pte = NULL;
unsigned long from, size;
int ret;
- count = le32_to_cpu(pgpt_head->num_partition_entries) *
- le32_to_cpu(pgpt_head->sizeof_partition_entry);
-
+ count = compute_partitions_entries_size(pgpt_head);
if (!count)
return NULL;
@@ -156,7 +173,7 @@ static gpt_header *alloc_read_gpt_header(struct block_device *blk,
static int is_gpt_valid(struct block_device *blk, u64 lba,
gpt_header **gpt, gpt_entry **ptes)
{
- u32 crc, origcrc;
+ u32 crc, origcrc, count;
u64 lastlba;
if (!ptes)
@@ -215,10 +232,13 @@ static int is_gpt_valid(struct block_device *blk, u64 lba,
if (!(*ptes = alloc_read_gpt_entries(blk, *gpt)))
goto fail;
+ /* Check the size of all partitions */
+ count = compute_partitions_entries_size(*gpt);
+ if (!count)
+ goto fail_ptes;
+
/* Check the GUID Partition Table Entry Array CRC */
- crc = efi_crc32((const unsigned char *)*ptes,
- le32_to_cpu((*gpt)->num_partition_entries) *
- le32_to_cpu((*gpt)->sizeof_partition_entry));
+ crc = efi_crc32((const unsigned char *)*ptes, count);
if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
dev_dbg(blk->dev, "GUID Partitition Entry Array CRC check failed: 0x%08x 0x%08x\n",
--
2.43.0
More information about the barebox
mailing list