DragonFlyBSD Kernel Audit
DF-0863 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/hpfs/hpfs_subr.c b/sys/vfs/hpfs/hpfs_subr.c
--- a/sys/vfs/hpfs/hpfs_subr.c
+++ b/sys/vfs/hpfs/hpfs_subr.c
@@ -225,6 +225,25 @@
 
 	cpdsp = (struct cpdsec *)bp->b_data;
 
+	if (cpdsp->d_magic != CPD_MAGIC) {
+		brelse(bp);
+		return (EINVAL);
+	}
+
+	/*
+	 * d_cpfirst / d_cpcnt are attacker-controlled on-disk u16 values.
+	 * d_cpdblk[] is a fixed-size array of 3 entries (sys/vfs/hpfs/hpfs.h:
+	 * struct cpdsec.d_cpdblk[3]); an unchecked d_cpcnt drives the loop
+	 * past the array and past the 512-byte DEV_BSIZE bp->b_data buffer
+	 * (DF-0863).  Clamp both to the array bounds before iterating.
+	 */
+	if (cpdsp->d_cpfirst >= nitems(cpdsp->d_cpdblk)) {
+		brelse(bp);
+		return (ENOENT);
+	}
+	if (cpdsp->d_cpcnt > nitems(cpdsp->d_cpdblk))
+		cpdsp->d_cpcnt = nitems(cpdsp->d_cpdblk);
+
 	for (i=cpdsp->d_cpfirst; i<cpdsp->d_cpcnt; i++) {
 		if (cpdsp->d_cpdblk[i].b_cpid == cpibp->b_cpid) {
 			bcopy(cpdsp->d_cpdblk + i, cpdbp,