mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(storage/fatfs): fix FAT32 mount integer overflow (CVE-2026-6682)
The initial CVE-2026-6682 fix (merged in !50362) hardened the exFAT mount path, but the CVE as reported by runZero is a FAT32 defect in mount_volume() and is reachable in ESP-IDF's default configuration (exFAT and 64-bit LBA disabled). This corrects the fix. Root cause: `fasize *= fs->n_fats` is a DWORD multiply with no overflow guard. A crafted BPB_FATSz32 such as 0x80000001 with NumFATs=2 wraps `fasize` to 0x00000002. The wrapped (too-small) FAT size then places `fs->database` inside the FAT region, so a forged directory entry in the overlapping sector yields an attacker-controlled `finfo.fsize`. Any caller that uses that size as a read length overflows its buffer with attacker-controlled bytes (CVSS 7.6, path to RCE). The later `fs->fsize < szbfat` check does not catch this because it compares the un-doubled single-FAT size, which is still large. Fix: reject a per-FAT size that overflows DWORD when multiplied by the FAT count, and reject a reserved+FAT+root system-area size that overflows DWORD, before either value is used to derive the data-area base. The previous exFAT cluster-heap/bitmap 64-bit promotions are retained as defense-in-depth and their comments relabeled accordingly (they are not CVE-2026-6682). The SBOM cve-exclude-list reason is updated to describe the FAT32 overflow and its fix.
This commit is contained in:
@@ -3561,7 +3561,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
fs->volbase = bsect;
|
||||
fs->database = bsect + ld_32(fs->win + BPB_DataOfsEx);
|
||||
fs->fatbase = bsect + ld_32(fs->win + BPB_FatOfsEx);
|
||||
if (maxlba < (QWORD)fs->database + (QWORD)ncl * fs->csize) return FR_NO_FILESYSTEM; /* CVE-2026-6682: promote to 64-bit before multiply to avoid integer overflow that would accept an undersized volume */
|
||||
if (maxlba < (QWORD)fs->database + (QWORD)ncl * fs->csize) return FR_NO_FILESYSTEM; /* exFAT mount hardening (defense-in-depth): promote to 64-bit before multiply to avoid integer overflow that would accept an undersized volume */
|
||||
fs->dirbase = ld_32(fs->win + BPB_RootClusEx);
|
||||
|
||||
/* Get bitmap location and check if it is contiguous (implementation assumption) */
|
||||
@@ -3577,7 +3577,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
}
|
||||
bcl = ld_32(fs->win + i + 20); /* Bitmap cluster */
|
||||
if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM; /* (Wrong cluster#) */
|
||||
fs->bitbase = fs->database + (LBA_t)fs->csize * (bcl - 2); /* Bitmap sector (CVE-2026-6682: 64-bit multiply to avoid overflow) */
|
||||
fs->bitbase = fs->database + (LBA_t)fs->csize * (bcl - 2); /* Bitmap sector (exFAT mount hardening: 64-bit multiply to avoid overflow) */
|
||||
for (;;) { /* Check if bitmap is contiguous */
|
||||
if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR;
|
||||
cv = ld_32(fs->win + bcl % (SS(fs) / 4) * 4);
|
||||
@@ -3603,6 +3603,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
|
||||
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
|
||||
if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
|
||||
if (fs->n_fats == 2 && fasize > 0xFFFFFFFF / 2) return FR_NO_FILESYSTEM; /* CVE-2026-6682: reject a per-FAT size that overflows DWORD when multiplied by the FAT count; a wrapped (too-small) fasize would move the data area into the FAT region and let a crafted image forge a directory entry with an attacker-controlled file size */
|
||||
fasize *= fs->n_fats; /* Number of sectors for FAT area */
|
||||
|
||||
fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */
|
||||
@@ -3619,6 +3620,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
|
||||
/* Determine the FAT sub type */
|
||||
sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + FF_DIR */
|
||||
if (sysect < fasize) return FR_NO_FILESYSTEM; /* CVE-2026-6682: reject reserved+FAT+root system-area size that overflows DWORD (same data-area displacement as the FAT-count overflow above) */
|
||||
if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
||||
nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
|
||||
if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
||||
|
||||
Reference in New Issue
Block a user