Module Name:    src
Committed By:   msaitoh
Date:           Sun Nov  9 06:38:55 UTC 2014

Modified Files:
        src/sys/fs/msdosfs [netbsd-6-1]: msdosfs_vfsops.c

Log Message:
Pull up following revision(s) (requested by maxv in ticket #1171):
        sys/fs/msdosfs/msdosfs_vfsops.c: revision 1.110 via patch
- From me, FreeBSD, OpenBSD and the FAT specification. Ok christos@
  - Perform sanity checks not just for GEMDOSFS, but for all FAT devices. This
    also fixes a division-by-zero bug that could crash the system.
  - Define GEMDOSFS_BSIZE instead of a hard-coded 512 value, and remove 'bsize'.
  - Rename 'tmp' to 'BlkPerSec'.
- Remove 'secsize==0' and added 'secsize<DEV_BSIZE'


To generate a diff of this commit:
cvs rdiff -u -r1.93.6.1.6.1 -r1.93.6.1.6.2 \
    src/sys/fs/msdosfs/msdosfs_vfsops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/msdosfs/msdosfs_vfsops.c
diff -u src/sys/fs/msdosfs/msdosfs_vfsops.c:1.93.6.1.6.1 src/sys/fs/msdosfs/msdosfs_vfsops.c:1.93.6.1.6.2
--- src/sys/fs/msdosfs/msdosfs_vfsops.c:1.93.6.1.6.1	Mon Apr 21 10:17:48 2014
+++ src/sys/fs/msdosfs/msdosfs_vfsops.c	Sun Nov  9 06:38:55 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: msdosfs_vfsops.c,v 1.93.6.1.6.1 2014/04/21 10:17:48 bouyer Exp $	*/
+/*	$NetBSD: msdosfs_vfsops.c,v 1.93.6.1.6.2 2014/11/09 06:38:55 msaitoh Exp $	*/
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.93.6.1.6.1 2014/04/21 10:17:48 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.93.6.1.6.2 2014/11/09 06:38:55 msaitoh Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -93,6 +93,8 @@ MODULE(MODULE_CLASS_VFS, msdos, NULL);
 #define DPRINTF(a)
 #endif
 
+#define GEMDOSFS_BSIZE	512
+
 #define MSDOSFS_NAMEMAX(pmp) \
 	(pmp)->pm_flags & MSDOSFSMNT_LONGNAME ? WIN_MAXLEN : 12
 
@@ -474,8 +476,7 @@ msdosfs_mountfs(struct vnode *devvp, str
 	struct byte_bpb50 *b50;
 	struct byte_bpb710 *b710;
 	uint8_t SecPerClust;
-	int	ronly, error, tmp;
-	int	bsize;
+	int	ronly, error, BlkPerSec;
 	uint64_t psize;
 	unsigned secsize;
 
@@ -493,7 +494,7 @@ msdosfs_mountfs(struct vnode *devvp, str
 		goto error_exit;
 
 	error = getdisksize(devvp, &psize, &secsize);
-	if (error || secsize == 0) {
+	if (error) {
 		if (argp->flags & MSDOSFSMNT_GEMDOSFS)
 			goto error_exit;
 
@@ -502,16 +503,19 @@ msdosfs_mountfs(struct vnode *devvp, str
 		psize = 0;
 		error = 0;
 	}
+	if (secsize < DEV_BSIZE) {
+		DPRINTF(("Invalid block secsize (%d < DEV_BSIZE)", secsize));
+		error = EINVAL;
+		goto error_exit;
+	}
 
 	if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
-		bsize = secsize;
-		if (bsize != 512) {
-			DPRINTF(("Invalid block bsize %d for gemdos\n", bsize));
+		if (secsize != GEMDOSFS_BSIZE) {
+			DPRINTF(("Invalid block secsize %d for GEMDOS\n", secsize));
 			error = EINVAL;
 			goto error_exit;
 		}
-	} else
-		bsize = 0;
+	}
 
 	/*
 	 * Read the boot sector of the filesystem, and then check the
@@ -555,19 +559,6 @@ msdosfs_mountfs(struct vnode *devvp, str
 	pmp->pm_Heads = getushort(b50->bpbHeads);
 	pmp->pm_Media = b50->bpbMedia;
 
-	if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
-		/* XXX - We should probably check more values here */
-    		if (!pmp->pm_BytesPerSec || !SecPerClust
-	    		|| pmp->pm_SecPerTrack > 63) {
-			DPRINTF(("bytespersec %d secperclust %d "
-			    "secpertrack %d\n", 
-			    pmp->pm_BytesPerSec, SecPerClust,
-			    pmp->pm_SecPerTrack));
-			error = EINVAL;
-			goto error_exit;
-		}
-	}
-
 	if (pmp->pm_Sectors == 0) {
 		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
 		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
@@ -576,6 +567,29 @@ msdosfs_mountfs(struct vnode *devvp, str
 		pmp->pm_HugeSectors = pmp->pm_Sectors;
 	}
 
+	/*
+	 * Sanity checks, from the FAT specification:
+	 * - sectors per cluster: >= 1, power of 2
+	 * - logical sector size: >= 1, power of 2
+	 * - cluster size:        <= max FS block size
+	 * - number of sectors:   >= 1
+	 */
+	if ((SecPerClust == 0) || !powerof2(SecPerClust) ||
+	    (pmp->pm_BytesPerSec == 0) || !powerof2(pmp->pm_BytesPerSec) ||
+	    (SecPerClust * pmp->pm_BytesPerSec > MAXBSIZE) ||
+	    (pmp->pm_HugeSectors == 0)) {
+		DPRINTF(("consistency checks\n"));
+		error = EINVAL;
+		goto error_exit;
+	}
+
+	if (!(argp->flags & MSDOSFSMNT_GEMDOSFS) &&
+	    (pmp->pm_SecPerTrack > 63)) {
+		DPRINTF(("SecPerTrack %d\n", pmp->pm_SecPerTrack));
+		error = EINVAL;
+		goto error_exit;
+	}
+
 	if (pmp->pm_RootDirEnts == 0) {
 		unsigned short vers = getushort(b710->bpbFSVers);
 		/*
@@ -614,17 +628,12 @@ msdosfs_mountfs(struct vnode *devvp, str
 
 		/*
 		 * Check a few values (could do some more):
-		 * - logical sector size: power of 2, >= block size
-		 * - sectors per cluster: power of 2, >= 1
-		 * - number of sectors:   >= 1, <= size of partition
+		 * - logical sector size: >= block size
+		 * - number of sectors:   <= size of partition
 		 */
-		if ( (SecPerClust == 0)
-		  || (SecPerClust & (SecPerClust - 1))
-		  || (pmp->pm_BytesPerSec < bsize)
-		  || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
-		  || (pmp->pm_HugeSectors == 0)
-		  || (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize)
-		      > psize)) {
+		if ((pmp->pm_BytesPerSec < GEMDOSFS_BSIZE) ||
+		    (pmp->pm_HugeSectors *
+		     (pmp->pm_BytesPerSec / GEMDOSFS_BSIZE) > psize)) {
 			DPRINTF(("consistency checks for gemdos\n"));
 			error = EINVAL;
 			goto error_exit;
@@ -635,14 +644,14 @@ msdosfs_mountfs(struct vnode *devvp, str
 		 * always be the same as the number of bytes per disk block
 		 * Let's pretend it is.
 		 */
-		tmp = pmp->pm_BytesPerSec / bsize;
-		pmp->pm_BytesPerSec  = bsize;
-		pmp->pm_HugeSectors *= tmp;
-		pmp->pm_HiddenSects *= tmp;
-		pmp->pm_ResSectors  *= tmp;
-		pmp->pm_Sectors     *= tmp;
-		pmp->pm_FATsecs     *= tmp;
-		SecPerClust         *= tmp;
+		BlkPerSec = pmp->pm_BytesPerSec / GEMDOSFS_BSIZE;
+		pmp->pm_BytesPerSec  = GEMDOSFS_BSIZE;
+		pmp->pm_HugeSectors *= BlkPerSec;
+		pmp->pm_HiddenSects *= BlkPerSec;
+		pmp->pm_ResSectors  *= BlkPerSec;
+		pmp->pm_Sectors     *= BlkPerSec;
+		pmp->pm_FATsecs     *= BlkPerSec;
+		SecPerClust         *= BlkPerSec;
 	}
 
 	/* Check that fs has nonzero FAT size */

Reply via email to