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;

Reply via email to