summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortom <tom@openbsd.org>2006-12-14 07:37:24 +0000
committertom <tom@openbsd.org>2006-12-14 07:37:24 +0000
commita64fed607950afd10a8e1f2e0d487192d12bf148 (patch)
tree190b50bff5c9240a6cb9f7c141cbb149ddc59850
parent- enable nested interrupts on zaurus. most obvious side-effect of this is (diff)
downloadwireguard-openbsd-a64fed607950afd10a8e1f2e0d487192d12bf148.tar.xz
wireguard-openbsd-a64fed607950afd10a8e1f2e0d487192d12bf148.zip
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@
-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;