⬢ DragonFlyBSD Kernel Audit
DF-4321 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/ath/ath_hal/ah.c
+++ b/sys/dev/netif/ath/ath_hal/ah.c
@@ -852,17 +852,24 @@
 	uint32_t *dp = dstbuf;
 	int i;
 
-	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
+	/*
+	 * NB: space is a signed int; compare against signed constants.
+	 * Comparing against sizeof() (size_t) converts negative space to
+	 * a huge unsigned value and defeats these bounds checks, turning
+	 * a truncated register dump into an uncontrolled heap overflow
+	 * (DF-4321).  Also check space before the first value write.
+	 */
+	for (i = 0; space >= (int)(2*sizeof(uint32_t)); i++) {
 		uint32_t r = regs[i].start;
 		uint32_t e = regs[i].end;
 		*dp++ = r;
 		*dp++ = e;
-		space -= 2*sizeof(uint32_t);
-		do {
+		space -= (int)(2*sizeof(uint32_t));
+		while (r <= e && space >= (int)sizeof(uint32_t)) {
 			*dp++ = OS_REG_READ(ah, r);
 			r += sizeof(uint32_t);
-			space -= sizeof(uint32_t);
-		} while (r <= e && space >= sizeof(uint32_t));
+			space -= (int)sizeof(uint32_t);
+		}
 	}
 	return (char *) dp - (char *) dstbuf;
 }