Bug 2466034 (CVE-2026-89085)
| Summary: | CVE-2026-89085 parted: parted: Heap-based buffer overflow via crafted FAT32 filesystem image | ||
|---|---|---|---|
| Product: | [Other] Security Response | Reporter: | OSIDB Bzimport <bzimport> |
| Component: | vulnerability | Assignee: | Product Security DevOps Team <prodsec-dev> |
| Status: | NEW --- | QA Contact: | |
| Severity: | medium | Docs Contact: | |
| Priority: | medium | ||
| Version: | unspecified | CC: | rhel-process-autobot, security-response-team, watson-tool-maintainers |
| Target Milestone: | --- | Keywords: | Security |
| Target Release: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | --- | |
| Doc Text: |
A flaw was found in parted. A heap-based buffer overflow can occur when processing a specially crafted FAT32 filesystem due to an integer calculation error during buffer allocation. A local attacker could exploit this by enticing a user or automated service to open a malicious filesystem image, resulting in an application crash leading to a Denial of Service (DoS) or potential memory corruption.
|
Story Points: | --- |
| Clone Of: | Environment: | ||
| Last Closed: | Type: | --- | |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | 2554405 | ||
| Bug Blocks: | |||
AI_ONLY_REPORT package: parted-3.6-7.el10 ------ Summary: Heap Buffer Overflow in FAT Resize/Open Path (`_init_fats` / `fat_table_read`) via Integer Truncation: a crafted FAT32 image can declare a FAT large enough to truncate the computed table allocation size, after which the full on-disk FAT is read into the undersized heap buffer. Requirements to exploit: An attacker must supply a crafted FAT32 filesystem image or block device and have it opened through the `libparted-fs-resize` FAT open path on a non-`DEBUG` build. Reachability also depends on using a backing geometry large enough for the declared FAT length to be accepted and read. Component affected: `parted-3.6-7.el10`; FAT resize/open path in `libparted-fs-resize`, specifically `_init_fats` and `fat_table_read` Version affected: `parted-3.6-7.el10`; reachable when the FAT resize/open path is used to open attacker-controlled FAT32 media or images on non-`DEBUG` builds Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:H - 7.1 (HIGH) AV:L - The attacker supplies a local disk image or removable media rather than exploiting a network-reachable service. AC:L - The malformed FAT metadata is straightforward to construct once the vulnerable code path is known. PR:N - No privileges are required to create or provide the crafted filesystem. UI:R - A user or consuming application must open or inspect the crafted filesystem through the affected path. S:U - The corruption occurs within the privileges and security scope of the consuming process. C:L - Memory corruption may expose limited process memory, but broader confidentiality impact is not established from the available evidence. I:L - Memory corruption may permit limited in-process data corruption, but stronger integrity impact is not demonstrated here. A:H - The available evidence supports a reliable crash or other severe availability impact when the oversized FAT is read. Impact: Moderate. This is a real heap overflow in a filesystem parsing path, but the attack vector is local and user-assisted, and exploitation depends on the `libparted-fs-resize` FAT open path being exercised against attacker-controlled media. The available evidence firmly supports denial of service and heap corruption; broader compromise is plausible but not demonstrated. That combination is more consistent with Red Hat's Moderate classification than Important or Critical. Embargo: no Reason: The issue is local, requires user interaction or an application opening crafted media, and affects a specific parser path rather than a default remote service. Public remediation without embargo is proportionate. Acknowledgement: Aisle Research Vulnerability Details: In the FAT resize/open path, the computed FAT table size is derived from attacker-controlled on-disk metadata and stored in a 32-bit `FatCluster` without a bounds check. For FAT32, `fs_info->fat_sectors` comes from the boot sector `fat_length` field: ```c /* libparted/fs/r/fat/bootsector.c */ fs_info->fat_sectors = PED_LE32_TO_CPU (bs->u.fat32.fat_length) fs_info->logical_sector_size; ``` That value is then used to compute the FAT table allocation in `_init_fats`: ```c /* libparted/fs/r/fat/fat.c */ static int _init_fats (PedFileSystem* fs) { FatSpecific* fs_info = FAT_SPECIFIC (fs); FatCluster table_size; table_size = fs_info->fat_sectors * 512 / fat_table_entry_size (fs_info->fat_type); fs_info->fat = fat_table_new (fs_info->fat_type, table_size); ... if (!fat_table_read (fs_info->fat, fs, 0)) ... } ``` Later, `fat_table_read` reads `fs_info->fat_sectors` sectors into the allocated table buffer. The only size check shown in the affected path is a `PED_ASSERT`, which is not a runtime protection in non-`DEBUG` builds: ```c /* libparted/fs/r/fat/table.c */ PED_ASSERT (ft->raw_size >= fs_info->fat_sectors * 512); if (!ped_geometry_read (fs->geom, (void *) ft->table, fs_info->fat_offset + table_num * fs_info->fat_sectors, fs_info->fat_sectors)) return 0; ``` The result is an undersized-allocation plus oversized-read condition. When the computed table size truncates during assignment to `FatCluster`, `fat_table_new()` can allocate a smaller heap buffer than `fat_table_read()` later fills. In the observed path, this is reachable when the filesystem is opened through `ped_file_system_open()` into `fat_open()`, which in turn calls `_init_fats()` and then `fat_table_read()`. Steps to reproduce: 1. Build the affected code in a non-`DEBUG` configuration with ASan or another memory safety checker. 2. Create a sufficiently large sparse disk image or backing geometry so FAT32 probe/open checks can succeed. 3. Craft a FAT32 boot sector with valid signature and required fields, and set `u.fat32.fat_length = 0x02000000`. 4. Trigger `ped_file_system_open()` on that geometry so execution reaches `fat_open()`, `_init_fats()`, and then `fat_table_read()`. 5. Observe that the allocation size is derived from truncated 32-bit `table_size`, while the read size still uses the full `fs_info->fat_sectors` value. 6. Under ASan, expect a heap out-of-bounds report during FAT table loading. Mitigation: Until a fix is available, avoid opening untrusted FAT32 media or disk images through the `libparted-fs-resize` FAT open path. If such parsing is required, isolate it in a sandboxed helper process and reject filesystems whose declared FAT length is implausibly large before passing them to this code. Proposed Fix: Add explicit range checks before converting the computed FAT size to `FatCluster`, and replace the `PED_ASSERT`-only buffer size check in `fat_table_read` with a runtime error path. ```diff diff --git a/libparted/fs/r/fat/fat.c b/libparted/fs/r/fat/fat.c @@ -141,9 +141,22 @@ _init_fats (PedFileSystem* fs) { FatSpecific* fs_info = FAT_SPECIFIC (fs); FatCluster table_size; + uint64_t fat_bytes; + uint64_t table_size64; + int entry_size; table_size = fs_info->fat_sectors * 512 / fat_table_entry_size (fs_info->fat_type); + entry_size = fat_table_entry_size (fs_info->fat_type); + fat_bytes = (uint64_t) fs_info->fat_sectors * 512ULL; + table_size64 = fat_bytes / (uint64_t) entry_size; + if (table_size64 > UINT32_MAX) { + ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("FAT table is too large.")); + return 0; + } + table_size = (FatCluster) table_size64; + fs_info->fat = fat_table_new (fs_info->fat_type, table_size); if (!fs_info->fat) goto error; diff --git a/libparted/fs/r/fat/table.c b/libparted/fs/r/fat/table.c @@ -121,7 +121,13 @@ fat_table_read (FatTable* ft, const PedFileSystem* fs, int table_num) { FatSpecific* fs_info = FAT_SPECIFIC (fs); + uint64_t need = (uint64_t) fs_info->fat_sectors * 512ULL; PED_ASSERT (ft->raw_size >= fs_info->fat_sectors * 512); + if ((uint64_t) ft->raw_size < need) { + ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("FAT table buffer smaller than on-disk FAT.")); + return 0; + } memset (ft->table, 0, ft->raw_size); ``` ------ This report was generated using AI technology. Always review AI-generated content prior to use