On Tue, 11 Jul 2006, Robert Watson wrote: > In both FreeBSD and Darwin, I've noticed that the kernel msdosfs code is > excessively permissive as to what it considers a FAT file system. This is > presumably necessary due to the enourmous diversity of FAT file systems > floating around, but it makes it a little too easy to cause msdos to trip > over layouts that violate its layout assumptions. :-) FAT is much more > reliably detected by looking at the partition type it lives in than by > looking at the bytes that appear inside the partition, I believe. Um, most msdosfs file systems are on floppies so they don't even have a partition. Msdosfs can be very reliably detected from the bpb provided the bpb isn't uncleared garbage left from a previous file system, but the checks aren't very cocomplete and people keep relaxing them. In the old version that I use, the checks are mainly: % #ifndef MSDOSFS_NOCHECKSIG % if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 % || bsp->bs50.bsBootSectSig1 != BOOTSIG1) { % error = EINVAL; % goto error_exit; % } % #endif Was relaxed. % [... a few too many assignments before checking anything] % /* XXX - We should probably check more values here */ % if (!pmp->pm_BytesPerSec || !SecPerClust % || !pmp->pm_Heads % #ifdef PC98 % || !pmp->pm_SecPerTrack || pmp->pm_SecPerTrack > 255) { % #else % || !pmp->pm_SecPerTrack || pmp->pm_SecPerTrack > 63) { % #endif % error = EINVAL; % goto error_exit; % } Not a very good check. % if (pmp->pm_Sectors == 0) { % pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); % pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); % } else { % pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); % pmp->pm_HugeSectors = pmp->pm_Sectors; % } Not a consistency check, but how the extension works. % if (pmp->pm_HugeSectors > 0xffffffff / % (pmp->pm_BytesPerSec / sizeof(struct direntry)) + 1) { % /* % * We cannot deal currently with this size of disk % * due to fileid limitations (see msdosfs_getattr and % * msdosfs_readdir) % */ % error = EINVAL; % printf("mountmsdosfs(): disk too big, sorry\n"); % goto error_exit; % } Consistency check only as a side effect. % % if (pmp->pm_RootDirEnts == 0) { % if (bsp->bs710.bsBootSectSig2 != BOOTSIG2 % || bsp->bs710.bsBootSectSig3 != BOOTSIG3 % || pmp->pm_Sectors % || pmp->pm_FATsecs % || getushort(b710->bpbFSVers)) { % error = EINVAL; % printf("mountmsdosfs(): bad FAT32 filesystem\n"); % goto error_exit; % } Not a very good consistency check. % pmp->pm_fatmask = FAT32_MASK; % pmp->pm_fatmult = 4; % pmp->pm_fatdiv = 1; % pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs); % if (getushort(b710->bpbExtFlags) & FATMIRROR) % pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM; % else % pmp->pm_flags |= MSDOSFS_FATMIRROR; % } else % pmp->pm_flags |= MSDOSFS_FATMIRROR; % % /* % * 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 % * - number of FAT sectors: >= 1 % */ % if ( (SecPerClust == 0) % || (SecPerClust & (SecPerClust - 1)) % || (pmp->pm_BytesPerSec < DEV_BSIZE) % || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) % || (pmp->pm_HugeSectors == 0) % || (pmp->pm_FATsecs == 0) % ) { % error = EINVAL; % goto error_exit; % } More not very good consistency checks. Better checks would determine the location of the FAT and root directory and check that is there. % if (pmp->pm_fatmask == 0) { % if (pmp->pm_maxcluster % <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) { % /* % * This will usually be a floppy disk. This size makes % * sure that one fat entry will not be split across % * multiple blocks. % */ % pmp->pm_fatmask = FAT12_MASK; % pmp->pm_fatmult = 3; % pmp->pm_fatdiv = 2; % } else { % pmp->pm_fatmask = FAT16_MASK; % pmp->pm_fatmult = 2; % pmp->pm_fatdiv = 1; % } % } We do check the FAT, but default to FAT16 if it doesn't lool like FAT12. % [... a few more] BruceReceived on Thu Jul 13 2006 - 09:03:35 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:58 UTC