summaryrefslogtreecommitdiff
path: root/sys/msdosfs
diff options
context:
space:
mode:
authorTom Cosgrove <tom@cvs.openbsd.org>2006-12-14 07:37:25 +0000
committerTom Cosgrove <tom@cvs.openbsd.org>2006-12-14 07:37:25 +0000
commite64474383110b1c01ce1542de084bc347c443e11 (patch)
tree432b91cf96bd85f6d75188a8ce0a757eada4f913 /sys/msdosfs
parent1b2927765b9e1b5878d22d803522219cdb5b8e7f (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.c26
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;