From d3dd66792bfbd6264c65aad5da1d9e47505a52b0 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Sat, 11 Jan 2020 17:41:20 +0000 Subject: [PATCH] Correct off-by-two issue when determining FAT type. In the code we used NumClusters as the upper (non-inclusive) boundary of valid cluster number, so the actual value was 2 (CLUST_FIRST) more than the real number of clusters. This causes a FAT16 media with 65524 clusters be treated as FAT32 and might affect FAT12 media with 4084 clusters as well. To fix this, we increment NumClusters by CLUST_FIRST after the type determination. PR: 243179 MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D23082 --- sbin/fsck_msdosfs/boot.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sbin/fsck_msdosfs/boot.c b/sbin/fsck_msdosfs/boot.c index ff76ac34919d..86528ce83df9 100644 --- a/sbin/fsck_msdosfs/boot.c +++ b/sbin/fsck_msdosfs/boot.c @@ -266,8 +266,11 @@ readboot(int dosfs, struct bootblock *boot) return FSFATAL; } - boot->NumClusters = (boot->NumSectors - boot->FirstCluster) / boot->bpbSecPerClust + - CLUST_FIRST; + /* + * The number of clusters is derived from available data sectors, divided + * by sectors per cluster. + */ + boot->NumClusters = (boot->NumSectors - boot->FirstCluster) / boot->bpbSecPerClust; if (boot->flags & FAT32) { if (boot->NumClusters > (CLUST_RSRVD & CLUST32_MASK)) { @@ -310,11 +313,19 @@ readboot(int dosfs, struct bootblock *boot) break; } - if (boot->NumFatEntries < boot->NumClusters - CLUST_FIRST) { + if (boot->NumFatEntries < boot->NumClusters) { pfatal("FAT size too small, %u entries won't fit into %u sectors\n", boot->NumClusters, boot->FATsecs); return FSFATAL; } + + /* + * There are two reserved clusters. To avoid adding CLUST_FIRST every time + * when we perform boundary checks, we increment the NumClusters by 2, + * which is CLUST_FIRST to denote the first out-of-range cluster number. + */ + boot->NumClusters += CLUST_FIRST; + boot->ClusterSize = boot->bpbBytesPerSec * boot->bpbSecPerClust; boot->NumFiles = 1;