diff options
author | Tom Cosgrove <tom@cvs.openbsd.org> | 2006-12-14 07:37:25 +0000 |
---|---|---|
committer | Tom Cosgrove <tom@cvs.openbsd.org> | 2006-12-14 07:37:25 +0000 |
commit | e64474383110b1c01ce1542de084bc347c443e11 (patch) | |
tree | 432b91cf96bd85f6d75188a8ce0a757eada4f913 /sys/msdosfs | |
parent | 1b2927765b9e1b5878d22d803522219cdb5b8e7f (diff) |
If an MS-DOS filesystem claims to have more clusters than can be
represented in the FAT, limit the number of clusters we work with
to the FAT value. This stops corrupt filesystems causing us to run
off the end of the FAT and panic()ing in fillinusemap().
Found by Jason Crawford (jasonrcrawford at gmail.com) with the MOKB
fs fuzzer. Initial debugging by thib@.
ok krw@
Diffstat (limited to 'sys/msdosfs')
-rw-r--r-- | sys/msdosfs/msdosfs_vfsops.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c index 114644f0e9f..a0de9923ad1 100644 --- a/sys/msdosfs/msdosfs_vfsops.c +++ b/sys/msdosfs/msdosfs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfs_vfsops.c,v 1.42 2006/11/29 13:35:07 deraadt Exp $ */ +/* $OpenBSD: msdosfs_vfsops.c,v 1.43 2006/12/14 07:37:24 tom Exp $ */ /* $NetBSD: msdosfs_vfsops.c,v 1.48 1997/10/18 02:54:57 briggs Exp $ */ /*- @@ -273,6 +273,7 @@ msdosfs_mountfs(devvp, mp, p, argp) int ronly, error, bmapsiz; int bsize = 0, dtype = 0, tmp; uint32_t dirsperblk; + uint32_t fat_max_clusters; /* * Disallow multiple mounts of the same device. @@ -485,6 +486,29 @@ msdosfs_mountfs(devvp, mp, p, argp) else pmp->pm_fatblocksize = MAXBSIZE; + /* + * We now have the number of sectors in each FAT, so can work + * out how many clusters can be represented in a FAT. Let's + * make sure the file system doesn't claim to have more clusters + * than this. + * + * We perform the calculation like we do to avoid integer overflow. + * + * This will give us a count of clusters. They are numbered + * from 0, so the max cluster value is one less than the value + * we end up with. + */ + fat_max_clusters = pmp->pm_fatsize / pmp->pm_fatmult; + fat_max_clusters *= pmp->pm_fatdiv; + if (pmp->pm_maxcluster >= fat_max_clusters) { +#ifndef SMALL_KERNEL + printf("msdosfs: reducing max cluster to %d from %d " + "due to FAT size\n", fat_max_clusters - 1, + pmp->pm_maxcluster); +#endif + pmp->pm_maxcluster = fat_max_clusters - 1; + } + pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1; |