This is a discussion on Fix for msdosfs panic within the lucky.openbsd.tech forums, part of the OpenBSD category; --> Executive summary: There's a diff at the end that stops some corrupt msdos filesystems from causing a panic() at ...
| |||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| Executive summary: There's a diff at the end that stops some corrupt msdos filesystems from causing a panic() at mount. If you can test, please check that it does not prevent you from mounting any valid filesystems, and report back to me. Long version (including successful tests of this diff with the six msdos filesystems I have to hand for camera cards/flash drives/mp3 players): Mark sent me an MS-DOS filesystem which causes our msdosfs code to panic: uvm_fault(xxx) -> d kernel: page fault trap, code=0 Stopped at fillinusemap+0xd7: movzbl 0(%esi,%eax,1),%edx This is probably not the best way do discover that you have a corrupt filesystem. And the filesystem in question really is hosed. hexdump -C: 00000000 00 00 00 2b 24 6d 69 46 49 48 43 00 02 04 01 00 |...+$miFIHC.....| 00000010 02 00 02 00 00 f8 31 00 3f 00 20 00 3f 00 00 00 |.....x1.?. .?...| 00000020 5c d9 03 00 80 00 29 58 30 d5 12 4e 4f 20 4e 41 |\Y....)X0U.NO NA| 00000030 4d 45 20 20 20 20 46 41 54 31 36 20 20 20 00 00 |ME FAT16 ..| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000200 00 00 00 2b 24 6d 69 46 49 48 43 00 02 04 01 00 |...+$miFIHC.....| 00000210 02 00 02 00 00 f8 31 00 3f 00 20 00 3f 00 00 00 |.....x1.?. .?...| 00000220 5c d9 03 00 80 00 29 58 30 d5 12 4e 4f 20 4e 41 |\Y....)X0U.NO NA| 00000230 4d 45 20 20 20 20 46 41 54 31 36 20 20 20 00 00 |ME FAT16 ..| 00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000400 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff || * 00078000 b5 b7 3c 9a 88 13 cf 8a 7d 1e 2c bb e8 c4 c1 0a |57<...O.}.,;hDA.| 00078010 36 bb 9b 5b a8 7e 92 26 e6 d4 bc fb 5b b1 f5 37 |6;.[(~.&fT<{[1u7| 00078020 d4 d3 25 9d 1e ba a3 ef 9e 36 20 8b 8f 43 a0 76 |TS%..:#o.6 ..C v| i.e. the whole area where the FAT and root directory would be has been overwritten with 0xFF bytes. No chance of recovery. (Sorry, Mark.) The crash happens in msdosfs_fat.c:fillinusemap(), at the getushort() call: if (FAT32(pmp)) readcn = getulong(&bp->b_data[bo]); else HERE>>> readcn = getushort(&bp->b_data[bo]); if (FAT12(pmp) && (cn & 1)) readcn >>= 4; readcn &= pmp->pm_fatmask; This is within a for() loop for cn from first cluster to last cluster. Going back and looking at the filesystem header, we see: Bytes per sector: 512 Sectors per cluster: 4 Reserved sectors: 1 Number of FATs: 2 Root Dir Entries: 512 Old Total Sectors: 0 Media indicator: F8 Sectors in a FAT: 49 Total sectors: 252,252 so we were heading to read information for up to 252,252/4 = 63,063 clusters, but the FAT allegedly only has 49 sectors in it, each of which can hold information on 512/2 = 256 clusters, for a total of 49 * 256 = 12,544 clusters in the FAT. In my testing, it was actually when we tried to get readcn for cluster 14,336 that we hit an unmapped page and died. Now, obviously this 49 sectors/FAT value is wrong, but since both copies of the FAT have been trashed we can't begin to guess the correct value. But it would be great if we didn't try to read past the end of the FAT at all. Therefore I propose the diff at the end. It will abort the mount if there are not enough sectors in the FAT (according to the filesystem header) to store information about all the clusters that are in the filesystem. It stops the panic on the corrupt filesystem Mark sent me, and does not interfere with the operation of any of the valid filesystems I have to hand. zinc $ sudo vnconfig -c svnd0 /var/tmp/kettenis.fs Password: zinc $ sudo mount -t msdos /dev/svnd0c /mnt msdosfs_mountfs(): FAT is too small mount_msdos: /dev/svnd0c on /mnt: Inappropriate file type or format zinc $ sudo vnconfig -u svnd0 zinc $ sudo mount /cf zinc $ ls -l /cf total 121822 -rwxr-xr-x 1 root wheel 1916782 Feb 15 22:12 dscf0261.jpg -rwxr-xr-x 1 root wheel 1868876 Feb 15 22:12 dscf0263.jpg -rwxr-xr-x 1 root wheel 1903796 Feb 15 22:12 dscf0279.jpg -rwxr-xr-x 1 root wheel 1883124 Feb 15 22:11 dscf0282.jpg -rwxr-xr-x 1 root wheel 1865769 Feb 15 22:10 dscf0347.jpg -rwxr-xr-x 1 root wheel 1934449 Feb 15 22:10 dscf0349.jpg -rwxr-xr-x 1 root wheel 1932140 Feb 15 22:09 dscf0389.jpg -rwxr-xr-x 1 root wheel 1936589 Feb 15 22:08 dscf0392.jpg -rwxr-xr-x 1 root wheel 1917505 Feb 15 22:08 dscf0408.jpg -rwxr-xr-x 1 root wheel 1940802 Feb 15 22:06 dscf0420.jpg -rwxr-xr-x 1 root wheel 2008697 Feb 15 22:06 dscf0473.jpg -rwxr-xr-x 1 root wheel 1861787 Feb 15 22:06 dscf0482.jpg -rwxr-xr-x 1 root wheel 1883828 Feb 15 22:05 dscf0521.jpg -rwxr-xr-x 1 root wheel 1918612 Feb 15 22:04 dscf0524.jpg -rwxr-xr-x 1 root wheel 1846415 Feb 15 22:04 dscf0540.jpg -rwxr-xr-x 1 root wheel 1806521 Feb 15 22:03 dscf0544.jpg -r-xr-xr-x 1 root wheel 2021258 Feb 15 22:02 dscf0631.jpg -r-xr-xr-x 1 root wheel 1810664 Feb 15 22:02 dscf0636.jpg -r-xr-xr-x 1 root wheel 1781688 Feb 15 22:01 dscf0645.jpg -r-xr-xr-x 1 root wheel 1771589 Feb 15 22:00 dscf0647.jpg -r-xr-xr-x 1 root wheel 1833478 Feb 15 22:00 dscf0650.jpg -r-xr-xr-x 1 root wheel 1862033 Feb 15 21:59 dscf0668.jpg -r-xr-xr-x 1 root wheel 1854509 Feb 15 21:59 dscf0706.jpg -r-xr-xr-x 1 root wheel 1928003 Feb 15 21:58 dscf1237.jpg -r-xr-xr-x 1 root wheel 1872838 Feb 15 21:57 dscf1269.jpg -r-xr-xr-x 1 root wheel 1821897 Feb 15 21:57 dscf1273.jpg -r-xr-xr-x 1 root wheel 1936066 Feb 15 21:56 dscf1311.jpg -r-xr-xr-x 1 root wheel 1904162 Feb 15 21:55 dscf1320.jpg -r-xr-xr-x 1 root wheel 1988093 Feb 15 21:55 dscf1350.jpg -r-xr-xr-x 1 root wheel 1866264 Feb 15 21:54 dscf1372.jpg -r-xr-xr-x 1 root wheel 1937037 Feb 15 21:53 dscf1396.jpg -r-xr-xr-x 1 root wheel 1917175 Feb 15 21:53 dscf1398.jpg -r-xr-xr-x 1 root wheel 1821700 Feb 15 21:52 dscf1404.jpg zinc $ sudo umount /cf zinc $ sudo mount /cf zinc $ ls -l /cf total 4 drwxr-xr-x 1 root wheel 2048 Feb 21 20:29 gill/ zinc $ sudo umount /cf zinc $ sudo mount /cf zinc $ ls -l /cf total 10176 drwxr-xr-x 1 root wheel 4096 Feb 11 18:04 Win98-driver-P20/ -rwxr-xr-x 1 root wheel 5204066 Feb 11 18:03 Win98-driver-P20.zip zinc $ sudo umount /cf zinc $ sudo mount /cf zinc $ ls -l /cf total 96 drwxr-xr-x 1 root wheel 16384 Feb 23 11:16 01-FranzFerdinand/ drwxr-xr-x 1 root wheel 16384 Feb 23 11:11 02-TheEnid/ drwxr-xr-x 1 root wheel 16384 Feb 23 11:12 03-Various/ zinc $ sudo umount /cf zinc $ sudo mount /cf zinc $ ls -l /cf zinc $ df -h /cf Filesystem Size Used Avail Capacity Mounted on /dev/sd0i 15.6M 0B 15.6M 0% /cf zinc $ sudo umount /cf zinc $ sudo mount /cf zinc $ ls -l /cf total 32 drwxr-xr-x 1 root wheel 16384 Dec 25 07:11 dcim/ zinc $ df -h /cf Filesystem Size Used Avail Capacity Mounted on /dev/sd0i 249M 19.6M 230M 8% /cf zinc $ sudo umount /cf dmesg during all this was as follows. msdosfs_mountfs(): FAT is too small umass0 at uhub0 port 1 configuration 1 interface 0 umass0: SMSC USB 2 Flash Media Device, rev 2.00/1.97, addr 2 umass0: using SCSI over Bulk-Only scsibus0 at umass0: 2 targets sd0 at scsibus0 targ 1 lun 0: <SMSC, USB 2 HS-CF, 1.97> SCSI0 0/direct removable sd0: 62MB, 62 cyl, 64 head, 32 sec, 512 bytes/sec, 126976 sec total sd1 at scsibus0 targ 1 lun 1: <SMSC, USB 2 HS-MS, 1.97> SCSI0 0/direct removable sd1: drive offline sd2 at scsibus0 targ 1 lun 2: <SMSC, USB 2 HS-SM, 1.97> SCSI0 0/direct removable sd2: drive offline sd3 at scsibus0 targ 1 lun 3: <SMSC, USB 2 HS-SD/MMC, 1.97> SCSI0 0/direct removable sd3: drive offline umass0: at uhub0 port 1 (addr 2) disconnected sd0 detached sd1 detached sd2 detached sd3 detached scsibus0 detached umass0 detached umass0 at uhub0 port 1 configuration 1 interface 0 umass0: SMSC USB 2 Flash Media Device, rev 2.00/1.97, addr 2 umass0: using SCSI over Bulk-Only scsibus0 at umass0: 2 targets sd0 at scsibus0 targ 1 lun 0: <SMSC, USB 2 HS-CF, 1.97> SCSI0 0/direct removable sd0: 122MB, 122 cyl, 64 head, 32 sec, 512 bytes/sec, 250368 sec total sd1 at scsibus0 targ 1 lun 1: <SMSC, USB 2 HS-MS, 1.97> SCSI0 0/direct removable sd1: drive offline sd2 at scsibus0 targ 1 lun 2: <SMSC, USB 2 HS-SM, 1.97> SCSI0 0/direct removable sd2: drive offline sd3 at scsibus0 targ 1 lun 3: <SMSC, USB 2 HS-SD/MMC, 1.97> SCSI0 0/direct removable sd3: drive offline umass0: at uhub0 port 1 (addr 2) disconnected sd0 detached sd1 detached sd2 detached sd3 detached scsibus0 detached umass0 detached umass0 at uhub0 port 1 configuration 1 interface 0 umass0: vendor 0x0d7d USB DISK 2.0, rev 2.00/0.50, addr 2 umass0: using SCSI over Bulk-Only scsibus0 at umass0: 2 targets sd0 at scsibus0 targ 1 lun 0: <, USB DISK 2.0, 1.16> SCSI0 0/direct removable sd0: 248MB, 248 cyl, 64 head, 32 sec, 512 bytes/sec, 507904 sec total umass0: at uhub0 port 1 (addr 2) disconnected sd0 detached scsibus0 detached umass0 detached umass0 at uhub0 port 1 configuration 1 interface 0 umass0: Creative Tech NOMAD MuVo NX, rev 1.10/0.01, addr 2 umass0: using SCSI over Bulk-Only scsibus0 at umass0: 2 targets sd0 at scsibus0 targ 1 lun 0: <CREATIVE, NOMAD MuVo NX, 0001> SCSI4 0/direct removable sd0: 247MB, 247 cyl, 64 head, 32 sec, 512 bytes/sec, 505856 sec total umass0: at uhub0 port 1 (addr 2) disconnected sd0 detached scsibus0 detached umass0 detached umass0 at uhub0 port 1 configuration 1 interface 0 umass0: Generic Mass Storage Device, rev 1.10/1.00, addr 2 umass0: using SCSI over Bulk-Only scsibus0 at umass0: 2 targets sd0 at scsibus0 targ 1 lun 0: <Generic, USB XD Reader, 1.05> SCSI0 0/direct removable sd0: 15MB, 15 cyl, 64 head, 32 sec, 512 bytes/sec, 32000 sec total umass0: at uhub0 port 1 (addr 2) disconnected sd0 detached scsibus0 detached umass0 detached umass0 at uhub0 port 1 configuration 1 interface 0 umass0: Generic Mass Storage Device, rev 1.10/1.00, addr 2 umass0: using SCSI over Bulk-Only scsibus0 at umass0: 2 targets sd0 at scsibus0 targ 1 lun 0: <Generic, USB XD Reader, 1.05> SCSI0 0/direct removable sd0: 250MB, 250 cyl, 64 head, 32 sec, 512 bytes/sec, 512000 sec total umass0: at uhub0 port 1 (addr 2) disconnected sd0 detached scsibus0 detached umass0 detached I'd really like people to test that that does not stop any currently- working filesystems from working. Positive results (i.e. everything still works, cases where corrupt filesystems stop panic()ing) to me; negative results (it stops you mounting a valid filesystem) to the list. Thanks Tom Index: msdosfs_vfsops.c ================================================== ================= RCS file: /cvs/src/sys/msdosfs/msdosfs_vfsops.c,v retrieving revision 1.36 diff -u -r1.36 msdosfs_vfsops.c --- msdosfs_vfsops.c 2 Mar 2005 00:46:10 -0000 1.36 +++ msdosfs_vfsops.c 14 Mar 2005 23:11:19 -0000 @@ -273,6 +273,7 @@ int ronly, error; int bsize = 0, dtype = 0, tmp; uint32_t dirsperblk; + uint32_t maxclusters = 0; /* * Disallow multiple mounts of the same device. @@ -511,6 +512,48 @@ */ brelse(bp); bp = NULL; + + /* + * An additional sanity check: + * The number of sectors in the FAT must be enough to hold "next + * cluster" information for all of the clusters in the file system. + */ + if (pmp->pm_fatmult != 0) { + /* + * Work out the max number of FAT entries in the FAT. + * This is the maximum number of clusters this filesystem + * can support. + * + * One sector can support (bytesPerSec * fatdiv / fatmult) + * clusters, so multiply by number of sectors in a FAT to + * get the total. Do it this way round to avoid rounding + * errors (in FAT12, one sector supports 341 1/3 clusters). + */ + maxclusters = (pmp->pm_BytesPerSec * pmp->pm_fatdiv * + pmp->pm_FATsecs) / pmp->pm_fatmult; + + /* + * In case the calculation above wraps around (since sectors + * per FAT is a 32-bit value), we work things out the other + * way, too: Even on FAT32, only 28 bits are used for the + * cluster number, so there is an absolute maximum of + * 0x10000000 clusters. Work out how big the FAT would need + * to be to store all of these (it's about 2 million sectors, + * or 1 GB). If we've got a FAT this big, we can support + * the max number of clusters we'll ever get on a FAT f/s. + * At least, on any of the ones we support at the moment. + */ + if (pmp->pm_FATsecs >= 0x10000000 * 4 / pmp->pm_BytesPerSec) + maxclusters = 0x10000000; + } + + if (maxclusters > 0 && pmp->pm_nmbrofclusters > maxclusters) { +#ifdef DIAGNOSTIC + printf("msdosfs_mountfs(): FAT is too small\n"); +#endif + error = EFTYPE; + goto error_exit; + } /* * Check FSInfo |
| Thread Tools | |
| Display Modes | |
|
|