-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
RT-Thread Version
master (verified on commit 2b58dec87b584aa7ded6e8c736498716f8d29cd0)
Hardware Type/Architectures
any BSP using the new block partition probing path with EFI/GPT enabled
Develop Toolchain
GCC
Describe the bug
GPT Partition Entry Underflow in RT-Thread EFI/GPT Parser
Affected Components
| Field | Detail |
|---|---|
| File 1 | components/drivers/block/partitions/efi.c |
| File 2 | components/drivers/block/blk_partition.c |
| Function 1 | rt_inline rt_bool_t is_pte_valid(const gpt_entry *pte, const rt_size_t lastlba) |
| Function 2 | rt_err_t efi_partition(struct rt_blk_disk *disk) |
| Function 3 | rt_err_t blk_put_partition(struct rt_blk_disk *disk, const char *type, rt_size_t start, rt_size_t count, int partno) |
Vulnerability Details
1. GPT entries accepted without checking ending_lba >= starting_lba
In efi.c, GPT entries are considered valid by is_pte_valid() if:
partition_type_guidis notNULL_GUIDstarting_lba <= lastlbaending_lba <= lastlba
Current code:
rt_inline rt_bool_t is_pte_valid(const gpt_entry *pte, const rt_size_t lastlba)
{
if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
rt_le64_to_cpu(pte->starting_lba) > lastlba ||
rt_le64_to_cpu(pte->ending_lba) > lastlba)
{
return RT_FALSE;
}
return RT_TRUE;
}There is no check that ending_lba >= starting_lba. So a malformed GPT entry with:
starting_lbainside disk boundsending_lbainside disk bounds- but
ending_lba < starting_lba
is still accepted as valid.
2. Partition size calculation underflows
efi_partition() computes the partition length as:
rt_uint64_t start = rt_le64_to_cpu(ptes[i].starting_lba);
rt_uint64_t size = rt_le64_to_cpu(ptes[i].ending_lba) -
rt_le64_to_cpu(ptes[i].starting_lba) + 1ULL;If ending_lba < starting_lba, the subtraction underflows in unsigned arithmetic and produces a very large wrapped size.
That underflowed size is then passed to blk_put_partition():
blk_put_partition(disk, "gpt", start, size, i)and stored into the logical partition device:
blk->sector_start = start;
blk->sector_count = count;
blk->partition.offset = start;
blk->partition.size = count;As a result, a malformed GPT entry can create a logical partition object with an attacker-controlled start and a huge wrapped size.
Trigger Condition
The bug is reached during normal GPT partition probing:
rt_blk_disk_probe_partition()
-> efi_partition()
-> find_valid_gpt()
-> iterate GPT entries
-> is_pte_valid()
-> size = ending_lba - starting_lba + 1ULL
-> blk_put_partition(...)
No local code changes are required. A crafted GPT image with valid headers/CRCs and a malformed partition entry is sufficient.
ℹ️ This appears to be distinct from the already reported GPT allocation bug in #11260.
Proof of Concept
A PoC can be implemented with a crafted GPT disk image used by any block backend that reaches rt_blk_disk_probe_partition().
PoC Shape
Create a disk image with:
- A valid PMBR
- A valid primary GPT header
- A valid GPT entry array CRC
- At least one GPT partition entry satisfying:
partition_type_guid != NULL_GUIDstarting_lba <= lastlbaending_lba <= lastlbaending_lba < starting_lba
For example:
starting_lba = 0x1000
ending_lba = 0x0FFF
Both fields are inside disk bounds, but the end is before the start.
Expected Result
During partition probing:
is_pte_valid()accepts the entryefi_partition()computes:
size = 0x0FFF - 0x1000 + 1which underflows to a huge rt_uint64_t value.
blk_put_partition()registers a logical partition with that wrapped size.
Minimal Reproduction Steps
- Enable the new block partition probing path with EFI/GPT support.
- Supply the crafted GPT image through any disk backend.
- Trigger
rt_blk_disk_probe_partition(). - Observe that the malformed partition is accepted and a partition with a huge wrapped size is created.
Impact
The immediate impact is that malformed GPT metadata can create an invalid logical partition with a huge sector count. This can break the partition abstraction and may enable later incorrect reads/writes, boundary confusion, or other follow-on faults in code that trusts the partition object's stored geometry.
So even though the trigger is a malformed GPT image, the root cause is a missing semantic validity check in the parser.
Upstream / Downstream Impact
Upstream
Verified on current master in the new block EFI/GPT parser implementation.
Downstream
Any downstream product based on current master that includes the new block partition subsystem and parses untrusted or externally supplied GPT media/images may be affected.
Suggested Fix
Reject GPT entries where the end LBA is before the start LBA:
rt_inline rt_bool_t is_pte_valid(const gpt_entry *pte, const rt_size_t lastlba)
{
rt_uint64_t start = rt_le64_to_cpu(pte->starting_lba);
rt_uint64_t end = rt_le64_to_cpu(pte->ending_lba);
if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
start > lastlba ||
end > lastlba ||
end < start)
{
return RT_FALSE;
}
return RT_TRUE;
}Optionally, efi_partition() may also defensively re-check the relation before computing size = end - start + 1ULL, to avoid similar bugs if future validation changes.
Kindly let me know if you intend to request a CVE ID upon confirmation of the vulnerability.
Other additional context
No response