3 Commits

Author SHA1 Message Date
Christopher Williams ab992fcf29 Update copyright 2026-07-09 16:44:58 -07:00
Christopher Williams dbd6192332 R0.16 patch 3
July 10, 2026

Some vulnerabilities in FatFs R0.16 and earlier have been found and published.

CVE-2026-6682 (*)
A FAT BPB with broken FAT size field can collapse the files or lead a system crash.

CVE-2026-6687 (*)
An exFAT volume label with manipulated name length field can lead a buffer overflow.

CVE-2026-6688
LFN length is 255 UTF-16 encode units maximum. Please make sure the size of buffer is sufficient
to copy the read file name.

CVE-2026-6685
Wraparound in these expressions are intentional and not harmful.

CVE-2026-6683 (*)
An exFAT BPB with manipulated cluster count field can trigger a /0 and lead the system crash.

CVE-2026-6686
This behavior has been documented in the manual. Please be careful.

CVE-2026-6684
A manipulated table size field in GPT header can lead the system freeze. It does not cover FatFs R0.16.

This publishment of problems was reported via an SNS.
2026-07-09 16:42:23 -07:00
Christopher Williams 0ac7849364 R0.16 patch 2
September 13, 2025

From a suggestion in user forum, I have changed the minimum volume size from 128
sectors to 64 sectors.
When create a volume on the very small drive with f_mkfs function, it is recommended to
specify FM_SFD flag and set a proper value to n_root.
2025-09-15 16:35:46 -07:00
2 changed files with 13 additions and 7 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ User Forum], not to this repo.
== License == License
Copyright (C) 2022, ChaN, all right reserved. Copyright (C) 2025, ChaN, all right reserved.
FatFs module is an open source software. Redistribution and use of FatFs in FatFs module is an open source software. Redistribution and use of FatFs in
source and binary forms, with or without modification, are permitted provided source and binary forms, with or without modification, are permitted provided
+12 -6
View File
@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------/ /*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem Module R0.16 / / FatFs - Generic FAT Filesystem Module R0.16 w/patch 2 /
/-----------------------------------------------------------------------------/ /-----------------------------------------------------------------------------/
/ /
/ Copyright (C) 2025, ChaN, all right reserved. / Copyright (C) 2025, ChaN, all right reserved.
@@ -41,6 +41,9 @@
#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */ #define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not defined in specs, practical limit) */ #define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not defined in specs, practical limit) */
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ #define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
#define MIN_EXFAT 0x00000100 /* Min exFAT clusters (Not defined in specs, implementation limit) */
#define MIN_FAT12 32 /* Min FAT12 clusters (Not defined in specs, implementation limit) */
#define MIN_VOLUME 64 /* Min volume sectors (Not defined in specs, implementation limit) */
/* Character code support macros */ /* Character code support macros */
@@ -3392,7 +3395,7 @@ static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS,
&& ld_16(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of number of reserved sectors (MNBZ) */ && ld_16(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of number of reserved sectors (MNBZ) */
&& (UINT)fs->win[BPB_NumFATs] - 1 <= 1 /* Properness of number of FATs (1 or 2) */ && (UINT)fs->win[BPB_NumFATs] - 1 <= 1 /* Properness of number of FATs (1 or 2) */
&& ld_16(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir size (MNBZ) */ && ld_16(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir size (MNBZ) */
&& (ld_16(fs->win + BPB_TotSec16) >= 128 || ld_32(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume size (>=128) */ && (ld_16(fs->win + BPB_TotSec16) >= MIN_VOLUME || ld_32(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume size (>=128) */
&& ld_16(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */ && ld_16(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */
return 0; /* It can be presumed an FAT VBR */ return 0; /* It can be presumed an FAT VBR */
} }
@@ -3545,7 +3548,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768 sectors) */ if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768 sectors) */
ncl = ld_32(fs->win + BPB_NumClusEx); /* Number of clusters */ ncl = ld_32(fs->win + BPB_NumClusEx); /* Number of clusters */
if (ncl > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ if (ncl < MIN_EXFAT || ncl > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Wrong cluster count) */
fs->n_fatent = ncl + 2; fs->n_fatent = ncl + 2;
/* Boundaries and Limits */ /* Boundaries and Limits */
@@ -3590,6 +3593,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
fasize = ld_16(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ fasize = ld_16(fs->win + BPB_FATSz16); /* Number of sectors per FAT */
if (fasize == 0) fasize = ld_32(fs->win + BPB_FATSz32); if (fasize == 0) fasize = ld_32(fs->win + BPB_FATSz32);
if (fasize >= 0x200000) return FR_NO_FILESYSTEM; /* (Must be smaller than max FAT size) */
fs->fsize = fasize; fs->fsize = fasize;
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
@@ -3617,6 +3621,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
if (nclst <= MAX_FAT32) fmt = FS_FAT32; if (nclst <= MAX_FAT32) fmt = FS_FAT32;
if (nclst <= MAX_FAT16) fmt = FS_FAT16; if (nclst <= MAX_FAT16) fmt = FS_FAT16;
if (nclst <= MAX_FAT12) fmt = FS_FAT12; if (nclst <= MAX_FAT12) fmt = FS_FAT12;
if (nclst <= MIN_FAT12) fmt = 0;
if (fmt == 0) return FR_NO_FILESYSTEM; if (fmt == 0) return FR_NO_FILESYSTEM;
/* Boundaries and Limits */ /* Boundaries and Limits */
@@ -5526,7 +5531,7 @@ FRESULT f_getlabel (
WCHAR hs; WCHAR hs;
UINT nw; UINT nw;
for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) { /* Extract volume label from 83 entry */ for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel] && si < 11; si++) { /* Extract volume label from 83 entry */
wc = ld_16(dj.dir + XDIR_Label + si * 2); wc = ld_16(dj.dir + XDIR_Label + si * 2);
if (hs == 0 && IsSurrogate(wc)) { /* Is the code a surrogate? */ if (hs == 0 && IsSurrogate(wc)) { /* Is the code a surrogate? */
hs = wc; continue; hs = wc; continue;
@@ -6157,7 +6162,7 @@ FRESULT f_mkfs (
} }
} }
} }
if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=128 sectors */ if (sz_vol < MIN_VOLUME) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is not too small */
/* Now start to create an FAT volume at b_vol and sz_vol */ /* Now start to create an FAT volume at b_vol and sz_vol */
@@ -6389,7 +6394,8 @@ FRESULT f_mkfs (
} }
/* Determine number of clusters and final check of validity of the FAT sub-type */ /* Determine number of clusters and final check of validity of the FAT sub-type */
if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ if (sz_vol < b_data + pau * MIN_FAT12 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume for this configuration? */
n_clst = ((DWORD)sz_vol - sz_rsv - sz_fat * n_fat - sz_dir) / pau; n_clst = ((DWORD)sz_vol - sz_rsv - sz_fat * n_fat - sz_dir) / pau;
if (fsty == FS_FAT32) { if (fsty == FS_FAT32) {
if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32? */ if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32? */