Module Name: src Committed By: christos Date: Sat Jan 11 16:29:07 UTC 2020
Modified Files: src/sbin/fsck_msdos: boot.c Log Message: Don't add the 2 reserved clusters before we determine if we using fat16/fat32. >From FreeBSD: https://reviews.freebsd.org/D23082: 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. To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/sbin/fsck_msdos/boot.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sbin/fsck_msdos/boot.c diff -u src/sbin/fsck_msdos/boot.c:1.21 src/sbin/fsck_msdos/boot.c:1.22 --- src/sbin/fsck_msdos/boot.c:1.21 Thu Feb 8 04:05:17 2018 +++ src/sbin/fsck_msdos/boot.c Sat Jan 11 11:29:07 2020 @@ -27,7 +27,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: boot.c,v 1.21 2018/02/08 09:05:17 dholland Exp $"); +__RCSID("$NetBSD: boot.c,v 1.22 2020/01/11 16:29:07 christos Exp $"); #endif /* not lint */ #include <stdlib.h> @@ -210,8 +210,12 @@ readboot(int dosfs, struct bootblock *bo return FSFATAL; } - boot->NumClusters = (boot->NumSectors - boot->FirstCluster) / boot->SecPerClust - + CLUST_FIRST; + /* + * The number of clusters is derived from available data sectors, + * divided by sectors per cluster. + */ + boot->NumClusters = + (boot->NumSectors - boot->FirstCluster) / boot->SecPerClust; if (boot->flags&FAT32) boot->ClustMask = CLUST32_MASK; @@ -237,11 +241,19 @@ readboot(int dosfs, struct bootblock *bo 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 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->BytesPerSec * boot->SecPerClust; boot->NumFiles = 1;