⬢ DragonFlyBSD Kernel Audit
DF-3128 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/msdosfs/msdosfs_vfsops.c
+++ b/sys/vfs/msdosfs/msdosfs_vfsops.c
@@ -53,6 +53,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
+#include <sys/device.h>
 #include <sys/proc.h>
 #include <sys/nlookup.h>
 #include <sys/kernel.h>
@@ -300,6 +301,7 @@
 	struct byte_bpb710 *b710;
 	uint8_t SecPerClust;
 	u_long clusters;
+	int64_t devsize;
 	int ronly, error;
 
 	/*
@@ -325,6 +327,12 @@
 	if (error)
 		return (error);
 	dev = devvp->v_rdev;
+	/*
+	 * Size of the backing device (slice or whole disk) in DEV_BSIZE
+	 * blocks, or 0 if the device cannot report it.  (dev_dpsize()
+	 * returns DEV_BSIZE-scale block counts, see vm_swap.c.)
+	 */
+	devsize = dev_dpsize(dev);
 	bp  = NULL; /* both used in error_exit */
 	pmp = NULL;
 
@@ -430,8 +438,10 @@
 	}
 
 	if ((off_t)pmp->pm_HugeSectors * pmp->pm_BytesPerSec <
-	    pmp->pm_HugeSectors /* overflow */) {
-		/* XXX FreeBSD also checks media size in above */
+	    pmp->pm_HugeSectors /* overflow */ ||
+	    (devsize > 0 &&
+	     (off_t)pmp->pm_HugeSectors * pmp->pm_BlkPerSec > devsize)
+	    /* past end of volume */) {
 		error = EINVAL;
 		goto error_exit;
 	}