From: Karel Zak Date: Mon, 22 Jun 2026 08:25:12 +0000 (+0200) Subject: libfdisk: fix OOM on GPT with huge partition entries array X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c6a01958c4eb01833a2b2325562e8ff6921a67a0;p=thirdparty%2Futil-linux.git libfdisk: fix OOM on GPT with huge partition entries array Add sanity checks to gpt_read_entries() to prevent out-of-memory when reading a crafted GPT header with an absurdly large npartition_entries value. The entries array size is now limited by: - GPT_NPARTITIONS_MAX hard cap (~4MiB) - first_usable_lba, since entries must fit before the first usable sector Also reorder validation in gpt_read_header() to perform all cheap header-only checks (my_lba, LBA sanity) before attempting to allocate and read the entries array. Addresses: https://github.com/util-linux/util-linux/issues/4432 Signed-off-by: Karel Zak --- diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c index b985f087a..a2a9314c3 100644 --- a/libfdisk/src/gpt.c +++ b/libfdisk/src/gpt.c @@ -52,6 +52,7 @@ #define MSDOS_MBR_SIGNATURE 0xAA55 #define GPT_PART_NAME_LEN (72 / sizeof(uint16_t)) #define GPT_NPARTITIONS ((size_t) FDISK_GPT_NPARTITIONS_DEFAULT) +#define GPT_NPARTITIONS_MAX (4 * 1024 * 1024 / sizeof(struct gpt_entry)) /* Globally unique identifier */ struct gpt_guid { @@ -1019,6 +1020,11 @@ static unsigned char *gpt_read_entries(struct fdisk_context *cxt, if (gpt_sizeof_entries(header, &sz)) return NULL; + if (sz > GPT_NPARTITIONS_MAX * sizeof(struct gpt_entry) + || sz / cxt->sector_size >= le64_to_cpu(header->first_usable_lba)) { + DBG(GPT, ul_debug("entries array too large")); + return NULL; + } ret = calloc(1, sz); if (!ret) @@ -1198,10 +1204,17 @@ static struct gpt_header *gpt_read_header(struct fdisk_context *cxt, if (!gpt_check_header_crc(header, NULL)) goto invalid; + /* valid header must be at MyLBA */ + if (le64_to_cpu(header->my_lba) != lba) + goto invalid; + /* entry size must be large enough to hold struct gpt_entry */ if (le32_to_cpu(header->sizeof_partition_entry) < sizeof(struct gpt_entry)) goto invalid; + if (!gpt_check_lba_sanity(cxt, header)) + goto invalid; + /* read and verify entries */ ents = gpt_read_entries(cxt, header); if (!ents) @@ -1210,13 +1223,6 @@ static struct gpt_header *gpt_read_header(struct fdisk_context *cxt, if (!gpt_check_entryarr_crc(header, ents)) goto invalid; - if (!gpt_check_lba_sanity(cxt, header)) - goto invalid; - - /* valid header must be at MyLBA */ - if (le64_to_cpu(header->my_lba) != lba) - goto invalid; - if (_ents) *_ents = ents; else