Subject: kern/35455: bogus sanity tests in msdosfs_mountfs()
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <apb@cequrux.com>
List: netbsd-bugs
Date: 01/21/2007 09:35:00
>Number:         35455
>Category:       kern
>Synopsis:       bogus sanity tests in msdosfs_mountfs()
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jan 21 09:35:00 +0000 2007
>Originator:     Alan Barrett
>Release:        NetBSD 4.99.9
>Organization:
Not much
>Environment:
System: NetBSD 4.99.9 i386
>Description:
mount_msdos(8) refuses to mount FAT file systems with larger than
expected values for the number of heads.

The underlying cause seems to be a test in msdosfs_mountfs(), around
line 559 of src/sys/fs/msdosfs/msdosfs_vfsops.c.  The file system that I
was trying to mount when I encountered the problem has pmp->pm_Heads =
256, but the mount fails if pmp->pm_Heads > 255.

By code inspection, a similar problem would arise if there were more than
63 secors per track.
>How-To-Repeat:
Have a FAT file system with 256 heads.  Try to mount it:

    $ mount -t msdos /dev/sd0e /mnt
    mount_msdos: /dev/sd0e on /mnt: Invalid argument
    $ dmesg | grep sd0
    sd0 at scsibus0 target 0 lun 0: <Freecom, DataCard, 1100> disk removable
    sd0: 991 MB, 1968 cyl, 16 head, 63 sec, 512 bytes/sect x 2030592 sectors

>Fix:
The following patch works for me, but it almost certainly not the right
thing.  I don't know what the correct limits are.

--- msdosfs_vfsops.c	20 Jan 2007 23:34:09 -0000	1.42
+++ msdosfs_vfsops.c	21 Jan 2007 09:09:53 -0000
@@ -557,7 +557,7 @@
 	if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
 		/* XXX - We should probably check more values here */
     		if (!pmp->pm_BytesPerSec || !SecPerClust
-	    		|| pmp->pm_Heads > 255 || pmp->pm_SecPerTrack > 63) {
+	    		|| pmp->pm_Heads > 1023 || pmp->pm_SecPerTrack > 1023) {
 			DPRINTF(("bytespersec %d secperclust %d "
 			    "heads %d secpertrack %d\n", 
 			    pmp->pm_BytesPerSec, SecPerClust,