DragonFlyBSD Kernel Audit
DF-0108 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/subr_disklabel32.c b/sys/kern/subr_disklabel32.c
--- a/sys/kern/subr_disklabel32.c
+++ b/sys/kern/subr_disklabel32.c
@@ -332,6 +332,16 @@
 	if (lp->d_partitions[RAW_PART].p_offset != 0)
 		return (EXDEV);			/* not quite right */
 
+	/*
+	 * Validate d_secsize before allocating the pbuf and using it as a
+	 * transfer length.  Without this a crafted label with an oversized
+	 * d_secsize drives bp->b_bcount > bp->b_bufsize (the KKASSERT below
+	 * is a no-op on production kernels without INVARIANTS).  Check before
+	 * getpbuf_mem() so we don't leak a pbuf on the error path.
+	 */
+	if (lp->d_secsize < DEV_BSIZE || lp->d_secsize > MAXPHYS)
+		return (EINVAL);
+
 	bp = getpbuf_mem(NULL);
 	KKASSERT((int)lp->d_secsize <= bp->b_bufsize);
 	bp->b_bio1.bio_offset = (off_t)LABELSECTOR32 * lp->d_secsize;